Ir ao conteúdo
  • Cadastre-se

Python Os dados no banco de dados não alteram depois de editar


Posts recomendados

Sou iniciante e entusiasta em programação, nunca fiz curso ou algo parecido, sou apenas um autodidata, estou criando o meu primeiro projeto, é um sistema de cadastro de clientes que busca os dados da API da receita federal(cartão CNPJ) utilizando linguagem py(versão 3.11) e banco de dados sqlite3, já criei a interface no QT, já converti para ui_main.py, escrevi o main_py a database.py, e o ui_funtions.py, pois esse sistema é integrado para buscar informações do CNPJ da API da receita federal através de uma QTablewidget,(tab_company) na primeira tela é digitado o CNPJ, e através da API os dados da empresa são retornados automaticamente para campos criados no QTablewidget (optei por escolher para que o código busque campos específicos do cartão CNPJ e não todos, configurei main.py e ui_funtions.py para isto).

 

Ao clicar no botão cadastrar da interface(pushButton_5) automaticamente essas informações são jogadas para uma tabela QTablewidget(tab_company) onde possui três botões:

 

Gerar Excel, Alterar, Excluir

 

Eu no momento estou trabalhando na opção: Alterar, chamando uma função update_company mas travei neste passo pois ocorre que, quando faço uma alteração em qualquer dado de uma empresa cadastrada e clico em alterar é retornada a msg box: Dados alterados com sucesso!

 

OK, porém quando vou verificar na base de dados nada foi alterado, já exclui a base e criei uma nova porém o problema persiste.

já peguei o arquivo da base(system.db) e joguei em um visualizador Sqlite e os dados permanecem sem as alterações que fiz nos testes.

Já adicionei linhas de depuração porém no console não é retornado nenhum erro, já fiz os testes de conexão com banco de dados e ela abre e fecha com sucesso conforme mostrado no console. já verifiquei se há exceções ao atualizar o banco de dados porém o console também não retorna erros, algum dos colegas poderia me ajudar a resolver este mistério?

 

Vou compartilhar aqui o código main.py o database.py e o ui_funtions.py, nesta ordem.

 

from PySide6.QtCore import Qt, QEasingCurve, QPropertyAnimation
from PySide6.QtGui import QIcon
from PySide6.QtWidgets import (
    QApplication,
    QMainWindow,
    QStyleFactory,
    QMessageBox,
    QTableWidgetItem
)
from ui_main import Ui_MainWindow
import sys
from ui_funtions import consulta_cnpj
from database import Data_base


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.setWindowTitle("ATRIBUT - Sistema de cadastro")
        appIcon = QIcon()  # Use QtGui.QIcon()
        self.setWindowIcon(appIcon)

        # TOGGLE BUTTON
        self.btn_toggle.clicked.connect(self.leftMenu)

        # PÁGINAS DO SISTEMA
        self.btn_home.clicked.connect(lambda: self.Pages.setCurrentWidget(self.pg_home))

        # Botão à esquerda (navegar para a página de cadastro)
        self.btn_cadastrar.clicked.connect(lambda: self.Pages.setCurrentWidget(self.pg_cadastrar))

        # Botão inferior (cadastrar a empresa)
        self.pushButton_5.clicked.connect(self.cadastrar_empresas)  # Nome corrigido
        self.btn_alterar.clicked.connect(self.update_company)

        self.buscar_empresas()

        self.btn_sobre.clicked.connect(lambda: self.Pages.setCurrentWidget(self.pg_sobre))
        self.btn_contatos.clicked.connect(lambda: self.Pages.setCurrentWidget(self.pg_contatos))

        # PREENCHER AUTOMATICAMENTE OS DADOS DO CNPJ
        self.txt_cnpj.editingFinished.connect(self.consult_api)

    def leftMenu(self):
        width = self.left_menu.width()

        if width == 9:
            newWidth = 200
        else:
            newWidth = 9

        self.animation = QPropertyAnimation(self.left_menu, b"maximumWidth")
        self.animation.setDuration(500)
        self.animation.setStartValue(width)
        self.animation.setEndValue(newWidth)
        self.animation.setEasingCurve(QEasingCurve.InOutQuart)
        self.animation.start()

    def consult_api(self):
        campos = consulta_cnpj(self.txt_cnpj.text())

        # Organize os dados corretamente
        self.txt_cnpj.setText(campos[0])  # CNPJ
        self.txt_nome.setText(campos[1])  # Nome da empresa
        self.txt_logradouro.setText(campos[2])  # Logradouro
        self.txt_numero.setText(campos[3])  # Número do estabelecimento
        self.txt_complemento.setText(campos[4])  # Complemento do endereço
        self.txt_bairro.setText(campos[5])  # Bairro da empresa
        self.txt_municipio.setText(campos[6])  # Município
        self.txt_uf.setText(campos[7])  # UF
        self.txt_cep.setText(campos[8].replace('.', '').replace('-', ''))  # CEP
        self.txt_telefone.setText(campos[9].replace('(', '').replace('-', '').replace(')', ''))  # Telefone
        self.txt_email.setText(campos[10])  # Email
        self.txt_tributacao.setText("")  # Deixe o campo de Tributação em branco

    def cadastrar_empresas(self):
        db = Data_base()
        db.connect()

        # Verifique se o campo de tributação foi preenchido corretamente
        tributacao = self.txt_tributacao.text().strip().lower()  # Converte para minúsculas
        tributacao_valida = tributacao in ["mei", "simples nacional", "imune", "isenta", "lucro presumido", "lucro real"]

        if not tributacao_valida:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Warning)
            msg.setWindowTitle("Erro de Tributação")
            msg.setText("Informe o regime de tributação!\nOpções válidas: MEI, SIMPLES NACIONAL, IMUNE, ISENTA, LUCRO PRESUMIDO, LUCRO REAL")
            msg.exec()
            db.close_connection()
            return

        # Organize os dados na ordem correta das colunas
        fullDataSet = (
            self.txt_cnpj.text(),
            self.txt_nome.text(),
            self.txt_logradouro.text(),
            self.txt_numero.text(),
            self.txt_complemento.text(),
            self.txt_bairro.text(),
            self.txt_cep.text(),
            self.txt_municipio.text(),
            self.txt_uf.text(),
            self.txt_telefone.text().strip(),
            self.txt_email.text(),
            tributacao,  # Use a tributação validada aqui
        )

        # CADASTRAR NO BANCO DE DADOS
        resp = db.register_company(fullDataSet)
        self.buscar_empresas()

        if resp == "OK":
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)
            msg.setWindowTitle("Cadastro realizado")
            msg.setText("Cadastro realizado com sucesso")
            msg.exec()
            db.close_connection()
            return
        else:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Critical)
            msg.setWindowTitle("Erro")
            msg.setText("Erro ao cadastrar, verifique se as informações foram preenchidas corretamente!")
            msg.exec()
            db.close_connection()
            return

    def buscar_empresas(self):
        db = Data_base()
        db.connect()
        result = db.select_all_companies()

        self.tab_company.clearContents()
        self.tab_company.setRowCount(len(result))

        for row, text in enumerate(result):
            for column, data in enumerate(text):
                self.tab_company.setItem(row, column, QTableWidgetItem(str(data)))

        db.close_connection()

    def update_company(self):
        # Verifique se algum item está selecionado na tabela
        selected_items = self.tab_company.selectedItems()

        if not selected_items or len(selected_items) < 12:
            msg = QMessageBox()
            msg.setIcon(QMessageBox.Warning)
            msg.setText("Selecione uma empresa para atualizar.")
            msg.exec()
            return

        # Obtenha os dados da linha selecionada
        selected_row = [selected_items[i].text() for i in range(12)]

        # Defina o campo de tributação como vazio (ou qualquer valor padrão que desejar)
        selected_row.append("")  # Você pode definir um valor padrão aqui

        try:
            print("Antes de atualizar no banco de dados")
            # ATUALIZAR DADOS NO BANCO
            db = Data_base()
            db.connect()
            db.update_company(tuple(selected_row))
            db.close_connection()
            print("Após atualizar no banco de dados")

            msg = QMessageBox()
            msg.setIcon(QMessageBox.Information)
            msg.setText("Dados atualizados com sucesso!")
            msg.exec()

            # Limpa a tabela completamente
            self.tab_company.clearContents()

            # Recarrega os dados da tabela
            self.buscar_empresas()

        except Exception as e:
            print(f"Erro ao atualizar dados no banco de dados: {e}")


if __name__ == "__main__":
    db = Data_base()
    db.connect()
    db.create_table_company()
    db.close_connection()

    app = QApplication(sys.argv)
    app.setStyle(QStyleFactory.create("WindowsVista"))
    window = MainWindow()
    window.show()
    sys.exit(app.exec())

 

import sqlite3

class Data_base:

    def __init__(self, name='system.db') -> None:
        self.name = name

    def connect(self):
        try:
            print("Abrindo conexão com o banco de dados...")
            self.connection = sqlite3.connect(self.name)
            print("Conexão aberta com sucesso!")
        except Exception as e:
            print(f"Erro ao abrir a conexão com o banco de dados: {e}")

    def close_connection(self):
        try:
            print("Fechando conexão com o banco de dados...")
            self.connection.close()
            print("Conexão fechada com sucesso!")
        except Exception as e:
            print(f"Erro ao fechar a conexão com o banco de dados: {e}")

    def create_table_company(self):
        cursor = self.connection.cursor()
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS Empresa (
                CNPJ TEXT PRIMARY KEY,
                NOME TEXT,
                LOGRADOURO TEXT,
                NUMERO TEXT,
                COMPLEMENTO TEXT,
                BAIRRO TEXT,
                CEP TEXT,
                MUNICIPIO TEXT,
                UF TEXT,
                TELEFONE TEXT,
                EMAIL TEXT,
                TRIBUTACAO TEXT
            )
        """)

    def register_company(self, fullDataSet):
        campos_tabela = ('CNPJ', 'NOME', 'LOGRADOURO', 'NUMERO', 'COMPLEMENTO', 'BAIRRO', 'CEP', 'MUNICIPIO',
                         'UF', 'TELEFONE', 'EMAIL', 'TRIBUTACAO')

        qntd = "?,?,?,?,?,?,?,?,?,?,?,?"
        cursor = self.connection.cursor()

        try:
            cursor.execute(f"""INSERT INTO Empresa ({", ".join(campos_tabela)})
                              VALUES({qntd})""", fullDataSet)
            self.connection.commit()  # Certifique-se de realizar o commit após a inserção.
            print("Registro inserido com sucesso!")
            return "OK"
        except Exception as e:
            print(f"Erro ao inserir registro: {e}")
            return "Erro"

    def select_all_companies(self):
        try:
            cursor = self.connection.cursor()
            cursor.execute("SELECT * FROM Empresa ORDER BY NOME")
            empresas = cursor.fetchall()
            print("Dados recuperados com sucesso!")
            return empresas
        except Exception as e:
            print(f"Erro ao recuperar dados: {e}")
            return None

    def delete_company(self, id):
        try:
            cursor = self.connection.cursor()
            cursor.execute(f"DELETE FROM Empresa WHERE CNPJ = '{id}' ")
            self.connection.commit()
            return "Cadastro de empresa excluído com sucesso!"
        except:
            return "Erro ao excluir registro!"

    def update_company(self, fullDataSet):
        cursor = self.connection.cursor()
        cursor.execute(f"""UPDATE Empresa SET
            CNPJ = ?,
            NOME = ?,
            LOGRADOURO = ?,
            NUMERO = ?,
            COMPLEMENTO = ?,
            BAIRRO = ?,
            CEP = ?,
            MUNICIPIO = ?,
            UF = ?,
            TELEFONE = ?,
            EMAIL = ?,
            TRIBUTACAO = ?
            WHERE CNPJ = ?""", fullDataSet)
        self.connection.commit()

 

import requests
import json

def consulta_cnpj(cnpj):
    url = f"https://www.receitaws.com.br/v1/cnpj/{cnpj}"
    querystring = {"token": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX", "cnpj": cnpj, "plugin": "RF"}
    response = requests.get(url, params=querystring)

    if response.status_code == 200:
        resp = json.loads(response.text)

        # Mapeie os dados da API para os campos corretos
        return (
            resp.get('cnpj', ''),
            resp.get('nome', ''),
            resp.get('logradouro', ''),
            resp.get('numero', ''),
            resp.get('complemento', ''),
            resp.get('bairro', ''),
            resp.get('municipio', ''),
            resp.get('uf', ''),
            resp.get('cep', '').replace('.', '').replace('-', ''),
            resp.get('telefone', '').replace('(', '').replace('-', '').replace(')', ''),
            resp.get('email', ''),
            ""
        )
    else:
        print(f"Erro ao consultar CNPJ: Código de status {response.status_code}")
        return None

 

TELA 01.png

TELA02.png

TELA03.png

db_connect.txt finalizar.txt index.txt Peladasql.txt PONTOS CORRIDOS.xlsx

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@Wanderlan Cardoso ,

Da uma olhada no seu código na parte Update SQL:

"cursor.execute(f"""UPDATE Empresa SET CNPJ = ?, NOME = ?, LOGRADOURO = ?, NUMERO = ?, COMPLEMENTO = ?, BAIRRO = ?, CEP = ?, MUNICIPIO = ?, UF = ?, TELEFONE = ?, EMAIL = ?, TRIBUTACAO = ? WHERE CNPJ = ?""", fullDataSet)"

 

Dúvidas: No "WHERE", você está usando o CNPJ ou ID da tabela? 

 

Veja essa parte:

"cursor.execute(f"""UPDATE Empresa SET CNPJ = ?, NOME = ?, LOGRADOURO = ?, NUMERO = ?, COMPLEMENTO = ?, BAIRRO = ?, CEP = ?, MUNICIPIO = ?, UF = ?, TELEFONE = ?, EMAIL = ?, TRIBUTACAO = ? WHERE CNPJ = {id}""", fullDataSet)"

Link para o comentário
Compartilhar em outros sites

@Kaze_jp

No meu banco de dados eu tenho uma tabela chamada "Empresa" com várias colunas, como CNPJ, NOME, LOGRADOURO, etc. Cada linha dessa tabela representa uma empresa.

 

Quando eu quero atualizar uma empresa específica, eu preciso dizer ao banco de dados qual empresa deseja atualizar eu faço isso usando uma condição no comando SQL. No meu código, acabei por escolher usar o CNPJ como essa condição.  Se eu separar por partes ficaria assim:

 

UPDATE Empresa: Isso diz ao banco de dados que eu desejo atualizar uma linha na tabela "Empresa".

 

SET CNPJ = ?, NOME = ?, ...: Aqui, eu especifico quais colunas da empresa desejo atualizar e com quais valores. Os valores a serem atualizados estão representados por pontos de interrogação (?, que são espaços reservados para valores que eu fornecerei posteriormente).

 

WHERE CNPJ = ?: Essa parte eu escrevi para agir como um filtro garantindo que apenas a empresa com o CNPJ correspondente seja atualizada, e as outras empresas na tabela não sejam afetadas é uma garantia de que a atualização ocorra apenas nas linhas específicas que eu desejo alterar no banco de dados, o que infelizmente não está acontecendo, como você pode ver acima, eu realizo a alteração de determinado dado no cadastro da empresa, ele retorna que foi alterado porém na prática não houve alteração alguma.

 

Suponha que eu queira atualizar a informação de uma empresa com um CNPJ específico, digamos, "123456789". A linha com esse CNPJ será encontrada e atualizada de acordo com os valores fornecidos nas outras colunas (NOME, LOGRADOURO, etc.) no fullDataSet.

 

Eu possuo limitações técnicas que um programador profissional não teria kkkkkkkk e elas não me permitem enxergar uma forma de reverter este problema e prosseguir com as outras etapas afim de finalizar o projeto.

@Kaze_jp

 

Para efeitos de informação: Você pode se fazer essa pergunta: Mas por que você quer atualizar os dados de forma manual?

E ai eu te respondo:

 

A minha área é a contabilidade, eu decidi criar esse sistema para cadastrar todos os meus clientes dentro de uma base de dados, eu optei por escolher alguns dados que seriam salvos nesse banco, dados estes puxados diretamente do CNPJ da empresa através da API da receita federal, porém há um dado que não faz parte do CNPJ, ele esta na minha tabela com o nome TRIBUTAÇÃO, é um dado importante para mim afim de que eu possa controlar a forma de tributação das empresas pois nem todas as minhas empresas possuem a mesma forma de tributação, algumas são lucro presumido, outras simples nacional, outras lucro real, este campo eu escrevi para que ficasse vazio afim de que eu digitasse manualmente qual a forma de tributação de cada empresa que irei cadastrar, sem falar no fato de que essas formas de tributação são mutáveis, uma empresa hoje que é tributada pelo simples nacional, no próximo mês pode não ser mais e passar a ser lucro presumido, em função disto que eu escrevi o update afim de que eu possa especificamente atualizar essa informação da coluna TRIBUTAÇÃO, os demais campos eu nem me interessaria tanto em atualizar manualmente até por que são dados oficiais do CNPJ já importados pela API da receita. Se houvesse uma forma de apenas alterar este campo tributação, eu ja prosseguiria para as proximas etapas do projeto.

Link para o comentário
Compartilhar em outros sites

@Wanderlan Cardoso , Compreendo

 

Como citei para você dar uma olhada nesta parte porque quando você faz ("UPDATE") com SQL.

Porque do UPDATE foi WHERE = CNPJ - não funcionar a alteração.(como citado na imagem).

  • Não encontrou CNPJ, ou encontrou outro CNPJ ( não sei pode ter dois CNPJ com ids(indices diferentes)).
  • Os dados inseridos está indo para "Variavel vazia" ou pra outra Variavel selecionada.
  • Ou SQL tem algum letras, caracteres a mais no código, que executa o UPDATE do SQL mas ignora o campo da tabela.

Sugestão: Nesse chamada da função: "Update" ou Alteração de dados da empresa(nos campos)  na tela um acho melhor ir pelo "ID"/[linha] do que usar o CNPJ, pela tela mostrada na imagem de sistema.( Lembrando de alterações somente um (ID) Empresa).

@Wanderlan Cardoso

 

Nessa parte por exemplo nesta situação: 

"CNPJ = 00001" -> Original 

 CNPJ = 00012 -> alteração.

 

Exemplo: de UPDATE - pelo código

"UPDATE Empresa SET

CNPJ ="00012", ...(codigo resumido)... 

WHERE  CNPJ="00012"

Obs: Mas CNPJ é no antes: "CNPJ = 00001"

 

------------------------------------------------------------------------------------------------------------------------

Aqui que é o confuso da situação: ->  CNPJ = 00012 -> alteração.

"UPDATE Empresa SET

CNPJ ="00012", ...(codigo resumido)... 

WHERE  CNPJ="00001"   <-- Aqui teria que manter o CNPJ=00001 (original).

--------------------------------------------------------------------------------------------------------------------------

 

O mais interessante seria assim: Mesmo com alteração do CNPJ por outro valor ele vai no ID do banco de dados.

 

Original

"ID=2, CNPJ =00001, .... dados do campos...."

 

"UPDATE Empresa SET

CNPJ = ?, NOME = ?, LOGRADOURO = ?, NUMERO = ?, COMPLEMENTO = ?, BAIRRO = ?, CEP = ?, MUNICIPIO = ?, UF = ?, TELEFONE = ?, EMAIL = ?, TRIBUTACAO = ? 

WHERE  ID(ou outro nome do banco de dados) = ?"

 

Alteração:

"ID=2, CNPJ =00012, .... dados do campos...."

Assim você garantiria que qualquer alteração na linha escolhida iria acontecer em todos os campos ao mesmo tempo ou com algum dos campo escolhido para ser alterado.

 

--------------------------------------------------------------------------------------------------------------------------------------------------------

 

Ah você tenta ver se com esse código ao  adicionado - try/except, aparece um erro para você.

 

Adicionei o try/except na funcão.

 

def update_company(self, fullDataSet):
     try:
        cursor = self.connection.cursor()
        cursor.execute(f"""UPDATE Empresa SET
            CNPJ = ?,
            NOME = ?,
            LOGRADOURO = ?,
            NUMERO = ?,
            COMPLEMENTO = ?,
            BAIRRO = ?,
            CEP = ?,
            MUNICIPIO = ?,
            UF = ?,
            TELEFONE = ?,
            EMAIL = ?,
            TRIBUTACAO = ?
            WHERE CNPJ = ?""", fullDataSet)
        self.connection.commit()
            return "Cadastro de empresa alterado com sucesso!"
        except:
            return "Erro ao alterar o registro!"

Link para o comentário
Compartilhar em outros sites

@Wanderlan Cardoso ,

 

2- solução: "Por regra(de negócios e sistema) não poder alterar o CNPJ"

 

Código SQL:

 

"UPDATE Empresa SET

NOME = ?, LOGRADOURO = ?, NUMERO = ?, COMPLEMENTO = ?, BAIRRO = ?, CEP = ?, MUNICIPIO = ?, UF = ?, TELEFONE = ?, EMAIL = ?, TRIBUTACAO = ? 

WHERE  CNPJ = ?"

 

Ficando mais ou menos assim:

 

def update_company(self, fullDataSet):
     try:
        cursor = self.connection.cursor()
        cursor.execute(f"""UPDATE Empresa SET
            NOME = ?,
            LOGRADOURO = ?,
            NUMERO = ?,
            COMPLEMENTO = ?,
            BAIRRO = ?,
            CEP = ?,
            MUNICIPIO = ?,
            UF = ?,
            TELEFONE = ?,
            EMAIL = ?,
            TRIBUTACAO = ?
            WHERE CNPJ = ?""", fullDataSet)
        self.connection.commit()
            return "Cadastro de empresa alterado com sucesso!"
        except:
            return "Erro ao alterar o registro!"

 

@Wanderlan Cardoso ,

//Seu código está faltando uma parte:

# Organize os dados na ordem correta das colunas
        fullDataSet = (
            self.txt_cnpj.text(),
            self.txt_nome.text(),
            self.txt_logradouro.text(),
            self.txt_numero.text(),
            self.txt_complemento.text(),
            self.txt_bairro.text(),
            self.txt_cep.text(),
            self.txt_municipio.text(),
            self.txt_uf.text(),
            self.txt_telefone.text().strip(),
            self.txt_email.text(),
            tributacao,  # Use a tributação validada aqui
        )

 

//corrreção no final.. ( Aqui faltou indicar a variavel e tipo de dados).

# Organize os dados na ordem correta das colunas
        fullDataSet = (
            self.txt_cnpj.text(),
            self.txt_nome.text(),
            self.txt_logradouro.text(),
            self.txt_numero.text(),
            self.txt_complemento.text(),
            self.txt_bairro.text(),
            self.txt_cep.text(),
            self.txt_municipio.text(),
            self.txt_uf.text(),
            self.txt_telefone.text().strip(),
            self.txt_email.text(),
            self.txt_tributacao.text(),  # Use a tributação validada aqui
        )

 

Link para o comentário
Compartilhar em outros sites

@Wanderlan Cardoso , Olá

 

Sobre a parte da tributação:

"TRIBUTAÇÃO, é um dado importante para mim afim de que eu possa controlar a forma de tributação das empresas pois nem todas as minhas empresas possuem a mesma forma de tributação, algumas são lucro presumido, outras simples nacional, outras lucro real, este campo eu escrevi para que ficasse vazio afim de que eu digitasse manualmente qual a forma de tributação de cada..."

 

Sugestão para seu projeto: Se possível separar os dados de tributação em outra tabela no banco de dados.(aplicando conceito da chaves estrangeiras).

image.png.a7dcc9cf9dae838d62810bd9cf0e7454.png

 

Caso tenha que aumentar as informações(campos usados) na tabela "tipo_empresa" fica mais fácil adicionar novos campos de informações. Do que mexer nos campos da tabela "empresa", para melhorar o seu sistema que está sendo desenvolvido.

 

 

Link para o comentário
Compartilhar em outros sites

  • DiF alterou o título para Os dados no banco de dados não alteram depois de editar

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!