Closed ftbarata closed 3 years ago
Bom dia @ftbarata, poste o seu código e o seu erro completo para que eu possa te ajudar. Está fazendo o import da entidade corretamente? Está passando o tipo correto para os atributos das classes? Não tem um outro objeto "cliente" sobrescrevendo o objeto "cliente" da entidade pynfe? Neste código que vc postou cliente.indicador_ie está sendo chamando dentro do construtor de cliente (???)
@juniortada realmente havia uma socrescrita da classe Cliente() pelo Model do Django com o mesmo nome de Cliente. Após corrigir isso, agora tenho o erro "Argument must be bytes or unicode, got 'int' " na linha:
nfe = serializador.exportar()
Código da view do Django que usa o PyNFe:
@login_required(redirect_field_name=None)
def emissor_pynfe(request):
if request.method == 'GET':
return render(request, 'core/emitir_nota_fiscal.html',{'notafiscal_active':True})
else:
certificado = request.user.empresa.certificado.name
senha = request.user.empresa.senha_certificado
homologacao = request.user.empresa.homologacao
if request.user.empresa.inscricao_estadual:
inscricao_estadual = request.user.empresa.inscricao_estadual.replace('.','').replace('-','').replace('/','')
else:
inscricao_estadual = ''
if request.user.empresa.inscricao_municipal:
inscricao_municipal = request.user.empresa.inscricao_municipal.replace('.','').replace('-','').replace('/','')
else:
inscricao_municipal = ''
# emitente
emitente = Emitente(
razao_social=request.user.empresa.razao_social,
nome_fantasia=request.user.empresa.nome_fantasia,
cnpj=request.user.empresa.cnpj.replace('.','').replace('-','').replace('/',''), # cnpj apenas números
codigo_de_regime_tributario=request.user.empresa.codigo_de_regime_tributario, # 1 para simples nacional ou 3 para normal
inscricao_estadual=inscricao_estadual, # numero de IE da empresa
inscricao_municipal=inscricao_municipal,
cnae_fiscal=request.user.empresa.cnae_fiscal, # cnae apenas números
endereco_logradouro=request.user.empresa.logradouro,
endereco_numero=request.user.empresa.numero,
endereco_bairro=request.user.empresa.bairro,
endereco_municipio=request.user.empresa.cidade,
endereco_uf=request.user.empresa.estado.upper(),
endereco_cep=request.user.empresa.cep,
endereco_pais=CODIGO_BRASIL
)
if ClienteSistema.objects.all().filter(cpf=request.POST['cpf_cnpj'].replace('.', '').replace('-', '').replace('/', '')).exists():
cliente_sistema = ClienteSistema.objects.all().get(cpf=request.POST['cpf_cnpj'].replace('.', '').replace('-', '').replace('/', ''))
nome = cliente_sistema.nome_completo
tipo_documento = 'CPF'
documento = cliente_sistema.cpf
else:
cliente_sistema = ClienteSistema.objects.all().get(cnpj=request.POST['cpf_cnpj'].replace('.', '').replace('-', '').replace('/', ''))
nome = cliente_sistema.razao_social
tipo_documento = 'CNPJ'
documento = cliente_sistema.cnpj
endereco = Endereco.objects.all().filter(cliente=cliente_sistema)[0]
telefone = Telefone.objects.all().filter(cliente=cliente_sistema)[0]
# cliente
cliente = Cliente(
razao_social=nome,
tipo_documento=tipo_documento, # CPF ou CNPJ
email=cliente_sistema.email,
numero_documento=documento, # numero do cpf ou cnpj
indicador_ie=cliente_sistema.indicador_ie, # 9=Não contribuinte
endereco_logradouro=endereco.logradouro,
endereco_numero=endereco.numero,
endereco_complemento=endereco.complemento,
endereco_bairro=endereco.bairro,
endereco_municipio=endereco.municipio,
endereco_uf=endereco.estado,
endereco_cep=endereco.cep.replace('.','').replace('-',''),
endereco_pais=CODIGO_BRASIL,
endereco_telefone=telefone.numero.replace(' ','').replace('-','').replace('(','').replace(')','')
)
if request.POST['natureza_operacao'] == 'bonificacao':
natureza_operacao = 'Bonificacao'
elif request.POST['natureza_operacao'] == 'devolucao':
natureza_operacao = 'Devolucao'
elif request.POST['natureza_operacao'] == 'outras_saidas':
natureza_operacao = 'Outras saidas'
elif request.POST['natureza_operacao'] == 'prestacao_servico':
natureza_operacao = 'Prestacao de servico'
elif request.POST['natureza_operacao'] == 'remessa_a_feira':
natureza_operacao = 'Remessa a feira'
elif request.POST['natureza_operacao'] == 'remessa_consignacao':
natureza_operacao = 'Remessa de consignacao'
elif request.POST['natureza_operacao'] == 'remessa_demonstracao':
natureza_operacao = 'Remessa de demonstracao'
elif request.POST['natureza_operacao'] == 'remessa_comodato':
natureza_operacao = 'Remessa comodato'
elif request.POST['natureza_operacao'] == 'Retorno demonstracao':
natureza_operacao = 'Retorno demonstracao'
elif request.POST['natureza_operacao'] == 'simples_faturamento':
natureza_operacao = 'Simples faturamento'
elif request.POST['natureza_operacao'] == 'transferencia':
natureza_operacao = 'Transferencia'
else:
natureza_operacao = 'Venda'
if endereco.estado.upper() == 'RO':
indicador_destino = 11
elif endereco.estado.upper() == 'AC':
indicador_destino = 12
elif endereco.estado.upper() == 'AM':
indicador_destino = 13
elif endereco.estado.upper() == 'RR':
indicador_destino = 14
elif endereco.estado.upper() == 'PA':
indicador_destino = 15
elif endereco.estado.upper() == 'AP':
indicador_destino = 16
elif endereco.estado.upper() == 'TO':
indicador_destino = 17
elif endereco.estado.upper() == 'MA':
indicador_destino = 21
elif endereco.estado.upper() == 'PI':
indicador_destino = 22
elif endereco.estado.upper() == 'CE':
indicador_destino = 23
elif endereco.estado.upper() == 'RN':
indicador_destino = 24
elif endereco.estado.upper() == 'PB':
indicador_destino = 25
elif endereco.estado.upper() == 'PE':
indicador_destino = 26
elif endereco.estado.upper() == 'AL':
indicador_destino = 27
elif endereco.estado.upper() == 'SE':
indicador_destino = 28
elif endereco.estado.upper() == 'BA':
indicador_destino = 29
elif endereco.estado.upper() == 'MG':
indicador_destino = 31
elif endereco.estado.upper() == 'ES':
indicador_destino = 32
elif endereco.estado.upper() == 'RJ':
indicador_destino = 33
elif endereco.estado.upper() == 'SP':
indicador_destino = 35
elif endereco.estado.upper() == 'PR':
indicador_destino = 41
elif endereco.estado.upper() == 'SC':
indicador_destino = 42
elif endereco.estado.upper() == 'RS':
indicador_destino = 43
elif endereco.estado.upper() == 'MS':
indicador_destino = 50
elif endereco.estado.upper() == 'MT':
indicador_destino = 51
elif endereco.estado.upper() == 'GO':
indicador_destino = 52
elif endereco.estado.upper() == 'DF':
indicador_destino = 53
else:
indicador_destino = 91
numero_nf = request.user.empresa.numero_inicial_nf + 1
request.user.empresa.numero_inicial_nf = request.user.empresa.numero_inicial_nf + 1
request.user.empresa.save()
# Nota Fiscal
nota_fiscal = NotaFiscal(
emitente=emitente,
cliente=cliente,
uf=endereco.estado.upper(),
natureza_operacao=natureza_operacao, # venda, compra, transferência, devolução, etc
forma_pagamento=request.POST['forma_pagamento'], # 0=Pagamento à vista; 1=Pagamento a prazo; 2=Outros.
tipo_pagamento=request.POST['tipo_pagamento'],
modelo=request.POST['modelo'], # 55=NF-e; 65=NFC-e
serie='1',
numero_nf=numero_nf, # Número do Documento Fiscal.
data_emissao=datetime.now(),
data_saida_entrada=datetime.now(),
tipo_documento=request.POST['operacao'], # 0=entrada; 1=saida
municipio=request.POST['codigo_ibge_municipio'], # Código IBGE do Município
tipo_impressao_danfe=1, # 0=Sem geração de DANFE;1=DANFE normal, Retrato;2=DANFE normal Paisagem;3=DANFE Simplificado;4=DANFE NFC-e;
forma_emissao='1', # 1=Emissão normal (não em contingência);
cliente_final=1, # 0=Normal;1=Consumidor final;
indicador_destino=indicador_destino,
indicador_presencial=request.POST['presenca'],
finalidade_emissao=request.POST['finalidade'], # 1=NF-e normal;2=NF-e complementar;3=NF-e de ajuste;4=Devolução de mercadoria.
processo_emissao='0', # 0=Emissão de NF-e com aplicativo do contribuinte;
transporte_modalidade_frete=request.POST['modalidade_frete'],
informacoes_adicionais_interesse_fisco=request.POST['informacoes_adicionais'],
totais_tributos_aproximado=Decimal(convert_currency_to_float(request.POST['total_aproximado_tributos'])),
)
# Produto
nota_fiscal.adicionar_produto_servico(
codigo=request.POST['codigo_produto'], # id do produto
descricao=request.POST['descricao_nota'],
ncm=request.POST['ncm'],
# cest='0100100', # NT2015/003
cfop='5102',
unidade_comercial='UN',
ean='SEM GTIN',
ean_tributavel='SEM GTIN',
quantidade_comercial=Decimal('1'), # 12 unidades
valor_unitario_comercial=Decimal(convert_currency_to_float(request.POST['valor_unitario'])), # preço unitário
valor_total_bruto=Decimal(convert_currency_to_float(request.POST['total'])), # preço total
unidade_tributavel='UN',
quantidade_tributavel=Decimal('1'),
valor_unitario_tributavel=Decimal(convert_currency_to_float(request.POST['valor_unitario'])),
ind_total=1,
# numero_pedido='12345', # xPed
# numero_item='123456', # nItemPed
icms_modalidade=request.user.empresa.icms_modalidade,
icms_origem=0,
icms_csosn=request.user.empresa.icms_csosn,
pis_modalidade=request.user.empresa.pis_modalidade,
cofins_modalidade=request.user.empresa.cofins_modalidade,
valor_tributos_aprox=convert_currency_to_float(request.POST['total_aproximado_tributos'])
)
# responsável técnico
nota_fiscal.adicionar_responsavel_tecnico(
cnpj='99999999999999',
contato='Fellipe Barata',
email='fellipetheophilo@gmail.com',
fone='21997741018'
)
# exemplo de nota fiscal referenciada (devolução/garantia)
# nfRef = NotaFiscalReferenciada(
# chave_acesso='99999999999999999999999999999999999999999999')
# nota_fiscal.notas_fiscais_referenciadas.append(nfRef)
# exemplo de grupo de pessoas autorizadas a baixar xml
# autxml_lista = ['99999999000199', '00000000040']
# for index, item in enumerate(autxml_lista, 1):
# nota_fiscal.adicionar_autorizados_baixar_xml(CPFCNPJ=item)
# serialização
serializador = SerializacaoXML(_fonte_dados, homologacao=homologacao)
nfe = serializador.exportar()
# assinatura
a1 = AssinaturaA1(certificado, senha)
xml = a1.assinar(nfe)
# envio
con = ComunicacaoSefaz(endereco.estado.lower(), certificado, senha, homologacao)
envio = con.autorizacao(modelo='nfe', nota_fiscal=xml)
# em caso de sucesso o retorno será o xml autorizado
# Ps: no modo sincrono, o retorno será o xml completo (<nfeProc> = <NFe> + <protNFe>)
# no modo async é preciso montar o nfeProc, juntando o retorno com a NFe
from lxml import etree
if envio[0] == 0:
print('Sucesso!')
print(etree.tostring(envio[1], encoding="unicode").replace('\n', '').replace('ns0:', '').replace(':ns0', ''))
# em caso de erro o retorno será o xml de resposta da SEFAZ + NF-e enviada
else:
print('Erro:')
print(envio[1].text) # resposta
print('Nota:')
print(etree.tostring(envio[2], encoding="unicode")) # nfe
return render(request, 'core/emitir_nota_fiscal.html', {'notafiscal_active': True})
@ftbarata a resposta curta é: você está passando um inteiro em algum lugar onde deveria estar enviando string ou coisa do tipo.
A resposta longa é: da forma que o seu código está estruturado, fica difícil até pra você que é o autor perceber este tipo de erro. Pelo seu código me parece que você é iniciante em python, vou deixar aqui algumas dicas. Divida seu código em pequenas funções, separadas por contextos, com métodos de 10/20 linhas ou menos. Escreva testes unitários para essas funções. Faça testes de FORMAÇÃO do xml, gere ele apenas assinado, teste o conteúdo no validador, assim você vai perceber qual campos preencher, qual podem geral algum tipo de conflito de interesses, etc.
Link do validador: https://www.sefaz.rs.gov.br/nfe/nfe-val.aspx
Fiz uma pequena refatoração do seu código para ter uma ideia do que estou dizendo:
from pynfe.utils.flags import CODIGOS_ESTADOS
@login_required(redirect_field_name=None)
def emissor_pynfe(request):
if request.method == 'GET':
return render(request, 'core/emitir_nota_fiscal.html',{'notafiscal_active':True})
else:
filial = request.user.empresa
certificado = filial.certificado.name
senha = filial.senha_certificado
homologacao = filial.homologacao
# emitente
emitente = _emitente(filial)
# cliente
cliente = _cliente(request)
natureza_operacao = request.POST['natureza_operacao'].capitalize().replace('_', ' ')
indicador_destino = CODIGOS_ESTADOS[endereco.estado.upper()]
numero_nf = filial.numero_inicial_nf + 1
filial.numero_inicial_nf = filial.numero_inicial_nf + 1
filial.save()
# Nota Fiscal
nota_fiscal = NotaFiscal(
emitente=emitente,
cliente=cliente,
uf=endereco.estado.upper(),
natureza_operacao=natureza_operacao, # venda, compra, transferência, devolução, etc
forma_pagamento=request.POST['forma_pagamento'], # 0=Pagamento à vista; 1=Pagamento a prazo; 2=Outros.
tipo_pagamento=request.POST['tipo_pagamento'],
modelo=request.POST['modelo'], # 55=NF-e; 65=NFC-e
serie='1',
numero_nf=numero_nf, # Número do Documento Fiscal.
data_emissao=datetime.now(),
data_saida_entrada=datetime.now(),
tipo_documento=request.POST['operacao'], # 0=entrada; 1=saida
municipio=request.POST['codigo_ibge_municipio'], # Código IBGE do Município
tipo_impressao_danfe=1, # 0=Sem geração de DANFE;1=DANFE normal, Retrato;2=DANFE normal Paisagem;3=DANFE Simplificado;4=DANFE NFC-e;
forma_emissao='1', # 1=Emissão normal (não em contingência);
cliente_final=1, # 0=Normal;1=Consumidor final;
indicador_destino=indicador_destino,
indicador_presencial=request.POST['presenca'],
finalidade_emissao=request.POST['finalidade'], # 1=NF-e normal;2=NF-e complementar;3=NF-e de ajuste;4=Devolução de mercadoria.
processo_emissao='0', # 0=Emissão de NF-e com aplicativo do contribuinte;
transporte_modalidade_frete=request.POST['modalidade_frete'],
informacoes_adicionais_interesse_fisco=request.POST['informacoes_adicionais'],
totais_tributos_aproximado=Decimal(convert_currency_to_float(request.POST['total_aproximado_tributos'])),
)
# Produto
_add_produto(nota_fiscal, filial, request)
# responsável técnico
_responsavel_tecnico(nota_fiscal)
# exemplo de nota fiscal referenciada (devolução/garantia)
# nfRef = NotaFiscalReferenciada(
# chave_acesso='99999999999999999999999999999999999999999999')
# nota_fiscal.notas_fiscais_referenciadas.append(nfRef)
# exemplo de grupo de pessoas autorizadas a baixar xml
# autxml_lista = ['99999999000199', '00000000040']
# for index, item in enumerate(autxml_lista, 1):
# nota_fiscal.adicionar_autorizados_baixar_xml(CPFCNPJ=item)
# serialização
serializador = SerializacaoXML(_fonte_dados, homologacao=homologacao)
nfe = serializador.exportar()
# assinatura
a1 = AssinaturaA1(certificado, senha)
xml = a1.assinar(nfe)
############
###### SALVE A SUA NOTA ANTES DE ENVIAR ######
# coloque um status enviada, aguardando autorização, etc, etc
# e depois atualize o status e xml
############
# envio
con = ComunicacaoSefaz(endereco.estado.lower(), certificado, senha, homologacao)
envio = con.autorizacao(modelo='nfe', nota_fiscal=xml)
# em caso de sucesso o retorno será o xml autorizado
# Ps: no modo sincrono, o retorno será o xml completo (<nfeProc> = <NFe> + <protNFe>)
# no modo async é preciso montar o nfeProc, juntando o retorno com a NFe
from lxml import etree
if envio[0] == 0:
print('Sucesso!')
print(etree.tostring(envio[1], encoding="unicode").replace('\n', '').replace('ns0:', '').replace(':ns0', ''))
# em caso de erro o retorno será o xml de resposta da SEFAZ + NF-e enviada
else:
print('Erro:')
print(envio[1].text) # resposta
print('Nota:')
print(etree.tostring(envio[2], encoding="unicode")) # nfe
return render(request, 'core/emitir_nota_fiscal.html', {'notafiscal_active': True})
def _emitente(filial):
if filial.inscricao_estadual:
inscricao_estadual = _apenas_numeros(filial.inscricao_estadual)
else:
inscricao_estadual = ''
if filial.inscricao_municipal:
inscricao_municipal = _apenas_numeros(filial.inscricao_municipal)
else:
inscricao_municipal = ''
# emitente
emitente = Emitente(
razao_social=filial.razao_social,
nome_fantasia=filial.nome_fantasia,
cnpj=filial.cnpj _apenas_numeros(), # cnpj apenas números
codigo_de_regime_tributario=filial.codigo_de_regime_tributario, # 1 para simples nacional ou 3 para normal
inscricao_estadual=inscricao_estadual, # numero de IE da empresa
inscricao_municipal=inscricao_municipal,
cnae_fiscal=filial.cnae_fiscal, # cnae apenas números
endereco_logradouro=filial.logradouro,
endereco_numero=filial.numero,
endereco_bairro=filial.bairro,
endereco_municipio=filial.cidade,
endereco_uf=filial.estado.upper(),
endereco_cep=filial.cep,
endereco_pais=CODIGO_BRASIL
)
return emitente
def _cliente(request):
if ClienteSistema.objects.all().filter(_apenas_numeros(cpf=request.POST['cpf_cnpj'])).exists():
cliente_sistema = ClienteSistema.objects.all().get(_apenas_numeros(cpf=request.POST['cpf_cnpj']))
nome = cliente_sistema.nome_completo
tipo_documento = 'CPF'
documento = cliente_sistema.cpf
else:
cliente_sistema = ClienteSistema.objects.all().get(_apenas_numeros(cnpj=request.POST['cpf_cnpj']))
nome = cliente_sistema.razao_social
tipo_documento = 'CNPJ'
documento = cliente_sistema.cnpj
endereco = Endereco.objects.all().filter(cliente=cliente_sistema)[0]
telefone = Telefone.objects.all().filter(cliente=cliente_sistema)[0]
# cliente
cliente = Cliente(
razao_social=nome,
tipo_documento=tipo_documento, # CPF ou CNPJ
email=cliente_sistema.email,
numero_documento=documento, # numero do cpf ou cnpj
indicador_ie=cliente_sistema.indicador_ie, # 9=Não contribuinte
endereco_logradouro=endereco.logradouro,
endereco_numero=endereco.numero,
endereco_complemento=endereco.complemento,
endereco_bairro=endereco.bairro,
endereco_municipio=endereco.municipio,
endereco_uf=endereco.estado,
endereco_cep=endereco.cep.replace('.','').replace('-',''),
endereco_pais=CODIGO_BRASIL,
endereco_telefone=telefone.numero.replace(' ','').replace('-','').replace('(','').replace(')','')
)
return cliente
def _add_produto(nota_fiscal, filial, request):
nota_fiscal.adicionar_produto_servico(
codigo=request.POST['codigo_produto'], # id do produto
descricao=request.POST['descricao_nota'],
ncm=request.POST['ncm'],
# cest='0100100', # NT2015/003
cfop='5102',
unidade_comercial='UN',
ean='SEM GTIN',
ean_tributavel='SEM GTIN',
quantidade_comercial=Decimal('1'), # 12 unidades
valor_unitario_comercial=Decimal(convert_currency_to_float(request.POST['valor_unitario'])), # preço unitário
valor_total_bruto=Decimal(convert_currency_to_float(request.POST['total'])), # preço total
unidade_tributavel='UN',
quantidade_tributavel=Decimal('1'),
valor_unitario_tributavel=Decimal(convert_currency_to_float(request.POST['valor_unitario'])),
ind_total=1,
# numero_pedido='12345', # xPed
# numero_item='123456', # nItemPed
icms_modalidade=filial.icms_modalidade,
icms_origem=0,
icms_csosn=filial.icms_csosn,
pis_modalidade=filial.pis_modalidade,
cofins_modalidade=filial.cofins_modalidade,
valor_tributos_aprox=convert_currency_to_float(request.POST['total_aproximado_tributos'])
)
def _responsavel_tecnico(nota_fiscal):
nota_fiscal.adicionar_responsavel_tecnico(
cnpj='99999999999999',
contato='Fellipe Barata',
email='fellipetheophilo@gmail.com',
fone='21997741018'
)
# pequeno exemplo, tem métodos melhores no pynfe utils
def _apenas_numeros(text):
return text.replace('.','').replace('-','').replace('/','')
Olá @juniortada , realmente sou iniciante em python. Na verdade sou analista de infra e faço algumas coisas em python. Bom, corrigi as entradas para ser int onde tem que ser int, e str onde tem que ser str e agora o erro mudou para:
'NotaFiscalProduto' object has no attribute 'inf_adicionais_produto'
nfe = serializador.exportar() …
/media/fellipe/slave/python_virtualenvs/izecar/lib/python3.7/site-packages/pynfe/processamento/serializacao.py, line 78, in exportar
raise e …
/media/fellipe/slave/python_virtualenvs/izecar/lib/python3.7/site-packages/pynfe/processamento/serializacao.py, line 71, in exportar
raiz.append(self._serializar_nota_fiscal(nf, retorna_string=False)) …
/media/fellipe/slave/python_virtualenvs/izecar/lib/python3.7/site-packages/pynfe/processamento/serializacao.py, line 650, in _serializar_nota_fiscal
det = self._serializar_produto_servico(item, modelo=nota_fiscal.modelo, retorna_string=False) …
/media/fellipe/slave/python_virtualenvs/izecar/lib/python3.7/site-packages/pynfe/processamento/serializacao.py, line 512, in _serializar_produto_servico
if produto_servico.inf_adicionais_produto:
Tem alguma dica sobre isso? Obrigado mais uma vez.
Durante a instanciação da classe Cliente(), ocorre esse erro de argumento inesperado para tipo_documento, numero_documento, endereco_logradouro e assim por diante.