Compare commits

...

34 Commits
master ... 3.10

Author SHA1 Message Date
Leonardo e41b565c75 Fix setup to pip 10 8 years ago
Leonardo 561fbe8345
Merge pull request #30 from MrLucasCardoso/3.10 8 years ago
Lucas Cardoso 329411db6a
Merge branch '3.10' into 3.10 8 years ago
Junior Tada baabaf3ffc Add CSOSN 500 (cobrado anteriormente por ST) 8 years ago
Junior Tada 450dd0db2e Add marca e numeração para volume opcional 8 years ago
Junior Tada ee6d31532d removido espaço na declaração da tag 8 years ago
Junior Tada 4ecc626cac Add xPed obrigatoriedade licitação Copel 8 years ago
Junior Tada 34a36c7fb5 Corrigido lista antes do elif 8 years ago
Junior Tada 157bb228ed Movido novas urls para branch master (4.00) 8 years ago
Junior Tada 260f604e1f Merge branch '3.10' of https://github.com/leotada/PyNFe into 3.10 8 years ago
Junior Tada 0fb661433b Add MA SVAN e atualizado url webservice 4.00 8 years ago
Lucas Cardoso ad556b6b85 Atualizando comentario 8 years ago
Lucas Cardoso 76ef0dcb8b Corrigindo conflito, adicionando PI ao SVRS e formatando dois campos para duas casas decimais 8 years ago
Lucas Cardoso cd5243c724 gitigonre 8 years ago
Leonardo ce80ed4ed6 mensagem de erro ao carregar certificado 8 years ago
Junior Tada 8517673731 Corrigido version 3.10 8 years ago
Junior Tada e162cd43e7 Add RJ SVRS NFC-e 8 years ago
Junior Tada cb7339775e Atualizado url qrcode nfc-e RJ 8 years ago
Junior Tada 936570ed77 Corrigido erro http nfce SE 8 years ago
Junior Tada 94146bf8e3 Merge branch '3.10' of https://github.com/leotada/PyNFe into 3.10 8 years ago
Junior Tada 4dbee6311b Correção url qrcode nfce SE 8 years ago
Junior Tada 1c47f76418 Corrigido tag tranp nfce 3.10 8 years ago
Junior Tada 5f6d9c6412 Comentado codigo da versão 4.00 no branch 3.10 8 years ago
Junior Tada d775b901ee Removido pagamento para 3.10 8 years ago
Junior Tada 8f7f81ce0f Corrigido erro de format percentual de redução 8 years ago
Junior Tada fe41cd6be7 Corrigido indpag versão 3.10 8 years ago
Junior Tada 23c6f26f63 Comentado tag 4.00 na versão 3.10 II 8 years ago
Junior Tada 3fe5fd600a Comentado tag 4.00 na versão 3.10 8 years ago
Junior Tada fb085acef1 Erro variavel local fora do lugar 8 years ago
Junior Tada 82e662cc72 Merge branch '3.10' of https://github.com/leotada/PyNFe into 3.10 8 years ago
Junior Tada db5d17babf Conversão String para CST 8 years ago
Leonardo eff5a7d49e dados de nfe 4.0 8 years ago
Junior Tada 51db784d08 ICMS CST 00, 10 e 20 8 years ago
Leonardo 2f8162e6b3 Update README.md 8 years ago
  1. 1
      .gitignore
  2. 2
      README.md
  3. 2
      pynfe/__init__.py
  4. 5
      pynfe/entidades/certificado.py
  5. 14
      pynfe/entidades/notafiscal.py
  6. 21
      pynfe/processamento/comunicacao.py
  7. 330
      pynfe/processamento/serializacao.py
  8. 8
      pynfe/utils/webservices.py
  9. 5
      setup.py

1
.gitignore

@ -74,3 +74,4 @@ target/
db.*
TODO*
.idea/*

2
README.md

@ -1,5 +1,5 @@
Atenção este repositório já esta em desenvolvimento para a versão 4.00, para a versão 3.10 utilize a última release, [0.3](https://github.com/leotada/PyNFe/releases/tag/0.3).
Atenção este repositório já esta em desenvolvimento para a versão 4.00, para a versão 3.10 utilize a última [release](https://github.com/leotada/PyNFe/releases).
-----------
Visão Geral

2
pynfe/__init__.py

@ -1,5 +1,5 @@
def get_version():
return '0.2'
return '0.3.10'
__version__ = get_version()
__author__ = 'Marinho Brandao, Junior Tada, Leonardo Tada'

5
pynfe/entidades/certificado.py

@ -36,7 +36,10 @@ class CertificadoA1(Certificado):
o caminho dos arquivos, senao retorna o objeto. Apos o uso devem ser excluidos com o metodo excluir."""
# Carrega o arquivo .pfx, erro pode ocorrer se a senha estiver errada ou formato invalido.
pkcs12 = crypto.load_pkcs12(open(self.caminho_arquivo, "rb").read(), senha)
try:
pkcs12 = crypto.load_pkcs12(open(self.caminho_arquivo, "rb").read(), senha)
except Exception as e:
raise Exception('Falha ao carregar certificado digital A1. Verifique local e senha.')
if caminho:
cert = crypto.dump_certificate(crypto.FILETYPE_PEM, pkcs12.get_certificate())

14
pynfe/entidades/notafiscal.py

@ -522,7 +522,7 @@ class NotaFiscalProduto(Entidade):
numero_pedido = str()
# - Item do Pedido de Compra
numero_do_item = str()
numero_item = str()
# - Produto especifico (seleciona de lista) - NF_PRODUTOS_ESPECIFICOS
produto_especifico = str()
@ -530,7 +530,7 @@ class NotaFiscalProduto(Entidade):
# - Tributos
# - ICMS
# - Situacao tributaria (obrigatorio - seleciona de lista) - ICMS_TIPOS_TRIBUTACAO
icms_situacao_tributaria = str()
icms_modalidade = str()
# - Origem (obrigatorio - seleciona de lista) - ICMS_ORIGENS
icms_origem = int()
@ -559,9 +559,17 @@ class NotaFiscalProduto(Entidade):
icms_motivo_desoneracao = int()
# - ICMS ST
# - Modalidade de determinacao da BC ICMS ST (seleciona de lista) - ICMS_MODALIDADES
# - Modalidade de determinacao da BC ICMS ST
# 0=Preço tabelado ou máximo sugerido;
# 1=Lista Negativa (valor);
# 2=Lista Positiva (valor);
# 3=Lista Neutra (valor);
# 4=Margem Valor Agregado (%);
# 5=Pauta (valor);
icms_st_modalidade_determinacao_bc = str()
# - Percentual da margem de valor Adicionado do ICMS ST
icms_st_percentual_adicional = Decimal()
# - Percentual reducao da BC ICMS ST
icms_st_percentual_reducao_bc = Decimal()

21
pynfe/processamento/comunicacao.py

@ -216,7 +216,7 @@ class ComunicacaoSefaz(Comunicacao):
:param cnpj: CNPJ da empresa
:return:
"""
# UF que utilizam a SVRS - Sefaz Virtual do RS: Para serviço de Consulta Cadastro: AC, RN, PB, SC
# UF que utilizam a SVRS - Sefaz Virtual do RS: Para serviço de Consulta Cadastro: AC, RN, PB, SC, PI
lista_svrs = ['AC', 'RN', 'PB', 'SC', 'PI']
# RS implementa um método diferente na consulta de cadastro
@ -418,7 +418,8 @@ class ComunicacaoSefaz(Comunicacao):
raise Exception('Modelo não encontrado! Defina modelo="nfe" ou "nfce"')
# Estados que utilizam outros ambientes
else:
lista_svrs = ['AC', 'RN', 'PB', 'SC', 'SE', 'PI']
lista_svrs = ['AC', 'RN', 'PB', 'SC', 'SE', 'RJ', 'PI']
lista_svan = ['MA','PA']
if self.uf.upper() in lista_svrs:
if self._ambiente == 1:
ambiente = 'HTTPS'
@ -432,6 +433,21 @@ class ComunicacaoSefaz(Comunicacao):
self.url = NFCE['SVRS'][ambiente] + NFCE['SVRS'][consulta]
else:
raise Exception('Modelo não encontrado! Defina modelo="nfe" ou "nfce"')
elif self.uf.upper() in lista_svan:
if self._ambiente == 1:
ambiente = 'HTTPS'
else:
ambiente = 'HOMOLOGACAO'
if modelo == 'nfe':
# nfe Ex: https://nfe.fazenda.pr.gov.br/nfe/NFeStatusServico3
self.url = NFE['SVAN'][ambiente] + NFE['SVAN'][consulta]
elif modelo == 'nfce':
# nfce Ex: https://homologacao.nfce.fazenda.pr.gov.br/nfce/NFeStatusServico3
self.url = NFCE['SVAN'][ambiente] + NFCE['SVAN'][consulta]
else:
raise Exception('Modelo não encontrado! Defina modelo="nfe" ou "nfce"')
else:
raise Exception('UF com URL não definida!')
return self.url
def _get_url_uf(self, modelo, consulta):
@ -549,6 +565,7 @@ class ComunicacaoSefaz(Comunicacao):
# result.encoding = 'utf-8'
# return result
print(url)
print(xml)
# Faz o request com o servidor
result = requests.post(url, xml, headers=self._post_header(), cert=chave_cert, verify=False, timeout=120)
result.encoding = 'utf-8'

330
pynfe/processamento/serializacao.py

@ -240,6 +240,14 @@ class SerializacaoXML(Serializacao):
"""
etree.SubElement(prod, 'indTot').text = str(produto_servico.ind_total)
""" Informação de interesse do emissor para controle do B2B.(v2.0) """
# Número do Pedido de Compra. Tam 1-15
if produto_servico.numero_pedido:
etree.SubElement(prod, 'xPed').text = str(produto_servico.numero_pedido)
# Item do Pedido de Compra. Tam 6
if produto_servico.numero_item:
etree.SubElement(prod, 'nItemPed').text = str(produto_servico.numero_item)
# Imposto
imposto = etree.SubElement(raiz, 'imposto')
@ -250,7 +258,7 @@ class SerializacaoXML(Serializacao):
### ICMS
icms = etree.SubElement(imposto, 'ICMS')
icms_csosn = ('102', '103', '300', '400')
icms_csosn = ('102', '103', '300', '400', '500')
if produto_servico.icms_modalidade in icms_csosn:
icms_item = etree.SubElement(icms, 'ICMSSN'+produto_servico.icms_modalidade)
etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem)
@ -270,17 +278,50 @@ class SerializacaoXML(Serializacao):
etree.SubElement(icms_item, 'vBCSTDest').text = '' # Informar o valor da BC do ICMS ST da UF destino
etree.SubElement(icms_item, 'vICMSSTDest').text = '' # Informar o valor do ICMS ST da UF destino
else:
# FIXME
### OUTROS TIPOS DE ICMS
### OUTROS TIPOS DE ICMS (00,10,20)
icms_item = etree.SubElement(icms, 'ICMS'+produto_servico.icms_modalidade)
etree.SubElement(icms_item, 'orig').text = str(produto_servico.icms_origem)
etree.SubElement(icms_item, 'CST').text = str(produto_servico.icms_modalidade)
etree.SubElement(icms_item, 'modBC').text = str(produto_servico.icms_modalidade_determinacao_bc)
etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo)
etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota)
etree.SubElement(icms_item, 'vICMS').text = str(produto_servico.icms_valor)
# 00=Tributada integralmente.
if produto_servico.icms_modalidade == '00':
etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS
etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) # Alíquota do imposto
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
# 10=Tributada e com cobrança do ICMS por substituição tributária
elif produto_servico.icms_modalidade == '10':
etree.SubElement(icms_item, 'vBC').text = str(produto_servico.icms_valor_base_calculo) # Valor da BC do ICMS
etree.SubElement(icms_item, 'pICMS').text = str(produto_servico.icms_aliquota) # Alíquota do imposto
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
# Modalidade de determinação da BC do ICMS ST
# 0=Preço tabelado ou máximo sugerido; 1=Lista Negativa (valor);2=Lista Positiva (valor);3=Lista Neutra (valor);4=Margem Valor Agregado (%);5=Pauta (valor);
etree.SubElement(icms_item, 'modBCST').text = str(produto_servico.icms_st_modalidade_determinacao_bc)
etree.SubElement(icms_item, 'pMVAST').text = str(produto_servico.icms_st_percentual_adicional) # Percentual da margem de valor Adicionado do ICMS ST
etree.SubElement(icms_item, 'pRedBCST').text = str(produto_servico.icms_st_percentual_reducao_bc) # APercentual da Redução de BC do ICMS ST
etree.SubElement(icms_item, 'vBCST ').text = str(produto_servico.icms_st_valor_base_calculo)
etree.SubElement(icms_item, 'pICMSST ').text = str(produto_servico.icms_st_aliquota)
etree.SubElement(icms_item, 'vICMSST ').text = str(produto_servico.icms_st_valor)
# 20=Com redução de base de cálculo
elif produto_servico.icms_modalidade == '20':
etree.SubElement(icms_item, 'pRedBC').text = '{:.4f}'.format(produto_servico.icms_percentual_reducao_bc) # Percentual da Redução de BC
etree.SubElement(icms_item, 'vBC').text = '{:.2f}'.format(produto_servico.icms_valor_base_calculo or 0) # Valor da BC do ICMS
etree.SubElement(icms_item, 'pICMS').text = '{:.4f}'.format(produto_servico.icms_aliquota) # Alíquota do imposto
etree.SubElement(icms_item, 'vICMS').text = '{:.2f}'.format(produto_servico.icms_valor or 0) # Valor do ICMS
# Impostos não implementados
else:
raise NotImplementedError
# ipi
# ipi = etree.SubElement(imposto, 'IPI')
# etree.SubElement(ipi, 'clEnq') = produto_servico.ipi_classe_enquadramento # Preenchimento conforme Atos Normativos editados pela Receita Federal (Observação 2)
# ipint = etree.SubElement(ipi, 'IPINT')
# # 01=Entrada tributada com alíquota zero 02=Entrada isenta 03=Entrada não-tributada 04=Entrada imune 05=Entrada com suspensão
# # 51=Saída tributada com alíquota zero 52=Saída isenta 53=Saída não-tributada 54=Saída imune 55=Saída com suspensão
# etree.SubElement(ipint, 'CST') = produto_servico.ipi_codigo_enquadramento
# apenas nfe
pisnt = ('04','05','06','07','08','09')
if modelo == 55:
## PIS
pisnt = ('04','05','06','07','08','09')
pis = etree.SubElement(imposto, 'PIS')
if produto_servico.pis_modalidade in pisnt:
pis_item = etree.SubElement(pis, 'PISNT')
@ -378,6 +419,7 @@ class SerializacaoXML(Serializacao):
etree.SubElement(ide, 'cUF').text = CODIGOS_ESTADOS[nota_fiscal.uf]
etree.SubElement(ide, 'cNF').text = nota_fiscal.codigo_numerico_aleatorio
etree.SubElement(ide, 'natOp').text = nota_fiscal.natureza_operacao
# Removido na NF-e 4.00
etree.SubElement(ide, 'indPag').text = str(nota_fiscal.forma_pagamento)
etree.SubElement(ide, 'mod').text = str(nota_fiscal.modelo)
etree.SubElement(ide, 'serie').text = nota_fiscal.serie
@ -481,9 +523,19 @@ class SerializacaoXML(Serializacao):
etree.SubElement(icms_total, 'vBC').text = '{:.2f}'.format(nota_fiscal.totais_icms_base_calculo)
etree.SubElement(icms_total, 'vICMS').text = '{:.2f}'.format(nota_fiscal.totais_icms_total)
etree.SubElement(icms_total, 'vICMSDeson').text = '{:.2f}'.format(nota_fiscal.totais_icms_desonerado) # Valor Total do ICMS desonerado
#if nota_fiscal.totais_fcp:
# etree.SubElement(icms_total, 'vFCP').text = '{:.2f}'.format(nota_fiscal.totais_fcp)
#if nota_fiscal.totais_fcp_destino:
# etree.SubElement(icms_total, 'vFCPUFDest').text = '{:.2f}'.format(nota_fiscal.totais_fcp_destino)
#if nota_fiscal.totais_icms_inter_destino:
# etree.SubElement(icms_total, 'vICMSUFDest').text = '{:.2f}'.format(nota_fiscal.totais_icms_inter_destino)
#if nota_fiscal.totais_icms_inter_remetente:
# etree.SubElement(icms_total, 'vICMSUFRemet').text = '{:.2f}'.format(nota_fiscal.totais_icms_remetente)
etree.SubElement(icms_total, 'vBCST').text = '{:.2f}'.format(nota_fiscal.totais_icms_st_base_calculo)
etree.SubElement(icms_total, 'vST').text = '{:.2f}'.format(nota_fiscal.totais_icms_st_total)
etree.SubElement(icms_total, 'vProd').text = str(nota_fiscal.totais_icms_total_produtos_e_servicos)
# etree.SubElement(icms_total, 'vFCPST').text = '{:.2f}'.format(nota_fiscal.totais_fcp_st)
# etree.SubElement(icms_total, 'vFCPSTRet').text = '{:.2f}'.format(nota_fiscal.totais_fcp_st_ret)
etree.SubElement(icms_total, 'vProd').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_produtos_e_servicos)
etree.SubElement(icms_total, 'vFrete').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_frete)
etree.SubElement(icms_total, 'vSeg').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_seguro)
etree.SubElement(icms_total, 'vDesc').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_desconto)
@ -491,21 +543,20 @@ class SerializacaoXML(Serializacao):
# Tributos
etree.SubElement(icms_total, 'vII').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ii)
etree.SubElement(icms_total, 'vIPI').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ipi)
# etree.SubElement(icms_total, 'vIPIDevol').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_ipi_dev)
etree.SubElement(icms_total, 'vPIS').text = '{:.2f}'.format(nota_fiscal.totais_icms_pis)
etree.SubElement(icms_total, 'vCOFINS').text = '{:.2f}'.format(nota_fiscal.totais_icms_cofins)
etree.SubElement(icms_total, 'vOutro').text = '{:.2f}'.format(nota_fiscal.totais_icms_outras_despesas_acessorias)
etree.SubElement(icms_total, 'vNF').text = str(nota_fiscal.totais_icms_total_nota)
etree.SubElement(icms_total, 'vNF').text = '{:.2f}'.format(nota_fiscal.totais_icms_total_nota)
if nota_fiscal.totais_tributos_aproximado:
etree.SubElement(icms_total, 'vTotTrib').text = '{:.2f}'.format(nota_fiscal.totais_tributos_aproximado)
# Apenas NF-e
if nota_fiscal.modelo == 55:
# Transporte
transp = etree.SubElement(raiz, 'transp')
etree.SubElement(transp, 'modFrete').text = str(nota_fiscal.transporte_modalidade_frete)
# Transportadora
if nota_fiscal.transporte_transportadora:
transp.append(self._serializar_transportadora(
@ -537,8 +588,10 @@ class SerializacaoXML(Serializacao):
vol = etree.SubElement(transp, 'vol')
etree.SubElement(vol, 'qVol').text = str(volume.quantidade)
etree.SubElement(vol, 'esp').text = volume.especie
etree.SubElement(vol, 'marca').text = volume.marca
etree.SubElement(vol, 'nVol').text = volume.numeracao
if volume.marca:
etree.SubElement(vol, 'marca').text = volume.marca
if volume.numeracao:
etree.SubElement(vol, 'nVol').text = volume.numeracao
etree.SubElement(vol, 'pesoL').text = str(volume.peso_liquido)
etree.SubElement(vol, 'pesoB').text = str(volume.peso_bruto)
@ -658,22 +711,32 @@ class SerializacaoQrcode(object):
url = url + '&cHashQRCode=' + url_hash.upper()
if uf.upper() == 'PR':
# url_chave - Texto com a URL de consulta por chave de acesso a ser impressa no DANFE NFC-e.
# Informar a URL da “Consulta por chave de acesso da NFC-e”.
# A mesma URL que deve estar informada no DANFE NFC-e para consulta por chave de acesso
lista_uf_padrao = ['PR', 'CE', 'RS', 'RJ', 'RO']
if uf.upper() in lista_uf_padrao:
qrcode = NFCE[uf.upper()]['QR'] + url
# url_chave = NFCE[uf.upper()]['URL']
elif uf.upper() == 'SP':
if tpamb == '1':
qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['QR'] + url
# url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.' + NFCE[uf.upper()]['URL'] + url
else:
qrcode = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['QR'] + url
# url_chave = NFCE[uf.upper()]['HTTPS'] + 'www.homologacao.' + NFCE[uf.upper()]['URL'] + url
# AC, AM, RR, PA, SE
else:
if tpamb == '1':
qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url
# url_chave = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['URL'] + url
else:
qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url
# url_chave = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['URL'] + url
# adicionta tag infNFeSupl com qrcode
info = etree.Element('infNFeSupl')
etree.SubElement(info, 'qrCode').text = '<![CDATA['+ qrcode.strip() + ']]>'
# etree.SubElement(info, 'urlChave').text = url_chave
nfe.insert(1, info)
# correção da tag qrCode, retira caracteres pois e CDATA
tnfe = etree.tostring(nfe, encoding='unicode')
@ -747,240 +810,3 @@ class SerializacaoNfse(object):
return SerializacaoBetha().cancelar(nfse)
else:
raise Exception('Autorizador não suportado para cancelamento!')
class SerializacaoPipes(Serializacao):
"""Serialização utilizada pela SEFAZ-SP para a importação de notas."""
def exportar(self, destino, **kwargs):
pass
def _serializar_emitente(self, emitente, retorna_string=True):
cod_municipio, municipio = obter_municipio_e_codigo(
dict(codigo=emitente.endereco_cod_municipio,
municipio=emitente.endereco_municipio),
emitente.endereco_uf
)
serial_emitente_list = [
'\nC',
emitente.razao_social,
emitente.nome_fantasia,
emitente.inscricao_estadual,
emitente.inscricao_estadual_subst_tributaria,
emitente.inscricao_municipal,
emitente.cnae_fiscal,
emitente.codigo_de_regime_tributario,
'\nC02',
emitente.cnpj,
'\nC05',
emitente.endereco_logradouro,
emitente.endereco_numero,
emitente.endereco_complemento,
emitente.endereco_bairro,
cod_municipio,
municipio,
obter_uf_por_codigo(emitente.endereco_uf),
emitente.endereco_cep.replace('-',''),
emitente.endereco_pais,
obter_pais_por_codigo(emitente.endereco_pais),
emitente.endereco_telefone,
]
if retorna_string:
return '|'.join(map(str,serial_emitente_list))
return serial_emitente_list
def _serializar_cliente(self, cliente, retorna_string=True):
cod_municipio, municipio = obter_municipio_e_codigo(
dict(codigo=cliente.endereco_cod_municipio,
municipio=cliente.endereco_municipio),
cliente.endereco_uf
)
serial_data = [
'\nE',
cliente.razao_social,
'2', # indIEDest
cliente.inscricao_estadual,
cliente.inscricao_suframa,
'', # IM
cliente.email,
'\nE02' if cliente.tipo_documento == 'CNPJ' else '\nE03',
cliente.numero_documento,
'\nE05',
cliente.endereco_logradouro,
cliente.endereco_numero,
cliente.endereco_complemento,
cliente.endereco_bairro,
cod_municipio,
municipio,
obter_uf_por_codigo(cliente.endereco_uf),
cliente.endereco_cep.replace('-',''),
cliente.endereco_pais,
obter_pais_por_codigo(cliente.endereco_pais),
cliente.endereco_telefone
]
if retorna_string:
return '|'.join(map(str,serial_data))
return serial_data
def _serializar_produto_servico(self, produto_servico, retorna_string=True):
serial_data = [
'\nI',
produto_servico.codigo,
produto_servico.ean,
produto_servico.descricao,
produto_servico.ncm,
produto_servico.ex_tipi,
produto_servico.cfop,
produto_servico.unidade_comercial,
formatar_decimal(produto_servico.quantidade_comercial),
formatar_decimal(produto_servico.valor_unitario_comercial),
formatar_decimal(produto_servico.valor_total_bruto),
produto_servico.ean_tributavel,
produto_servico.unidade_tributavel,
formatar_decimal(produto_servico.quantidade_tributavel),
formatar_decimal(produto_servico.valor_unitario_tributavel),
formatar_decimal(produto_servico.total_frete) if produto_servico.total_frete else '',
formatar_decimal(produto_servico.total_seguro) if produto_servico.total_seguro else '',
formatar_decimal(produto_servico.desconto) if produto_servico.desconto else '',
formatar_decimal(produto_servico.outras_despesas_acessorias) if produto_servico.outras_despesas_acessorias else '',
produto_servico.compoe_valor_total,
produto_servico.numero_pedido,
produto_servico.numero_do_item,
'', # nFCI
'\nM', #IMPOSTOS
'\nN', #ICMS
'\nN06',
produto_servico.icms_origem,
produto_servico.icms_modalidade_determinacao_bc,
produto_servico.icms_valor if produto_servico.icms_valor else '',
produto_servico.icms_motivo_desoneracao if produto_servico.icms_valor else '',
'\nQ', #PIS
'\nQ02',
produto_servico.pis_tipo_calculo,
formatar_decimal(produto_servico.pis_valor_base_calculo),
formatar_decimal(produto_servico.pis_aliquota_percentual),
formatar_decimal(produto_servico.pis_valor),
'\nS', #COFINS
'\nS02',
produto_servico.cofins_situacao_tributaria,
formatar_decimal(produto_servico.cofins_valor_base_calculo),
formatar_decimal(produto_servico.cofins_aliquota_percentual),
formatar_decimal(produto_servico.cofins_valor)
]
if retorna_string:
return '|'.join(map(str, serial_data))
return serial_data
def _serializar_nota_fiscal(self, nota_fiscal, retorna_string=True):
cod_municipio, municipio = obter_municipio_e_codigo(
dict(codigo='',
municipio=nota_fiscal.municipio),
nota_fiscal.uf
)
if nota_fiscal.emitente.endereco_uf == nota_fiscal.cliente.endereco_uf:
id_dest = '1'
else:
id_dest = '2'
tz = time.strftime("%z")
tz = "{}:{}".format(tz[:-2], tz[-2:])
serial_data = [
'A',
'3.10',
nota_fiscal.identificador_unico,
'\nB',
CODIGOS_ESTADOS.get(nota_fiscal.uf, nota_fiscal.uf),
nota_fiscal.codigo_numerico_aleatorio,
nota_fiscal.natureza_operacao,
nota_fiscal.forma_pagamento,
nota_fiscal.modelo,
nota_fiscal.serie,
nota_fiscal.numero_nf,
nota_fiscal.data_emissao.strftime('%Y-%m-%dT%H:%M:%S') + tz,
nota_fiscal.data_saida_entrada.strftime('%Y-%m-%dT%H:%M:%S') + tz,
nota_fiscal.tipo_documento,
id_dest, # idDest
cod_municipio,
nota_fiscal.tipo_impressao_danfe,
nota_fiscal.forma_emissao,
nota_fiscal.dv_codigo_numerico_aleatorio,
self._ambiente,
nota_fiscal.finalidade_emissao,
nota_fiscal.cliente_final, # indFinal
nota_fiscal.indicador_presencial, # indPres
nota_fiscal.processo_emissao,
'%s %s' % (self._nome_aplicacao,
nota_fiscal.versao_processo_emissao),
'', # dhCont - Data e Hora da entrada em contingência
'', # xJust - Justificativa da entrada em contingência
]
serial_data += self._serializar_emitente(nota_fiscal.emitente,
retorna_string=False)
serial_data += self._serializar_cliente(nota_fiscal.cliente,
retorna_string=False)
# Produtos e serviços
produtos_servicos = enumerate(nota_fiscal.produtos_e_servicos, start=1)
for num, produto_servico in produtos_servicos:
num_produto = [
'\nH',
num, # Número do produto na lista
''
'' # End Pipe
]
serial_data += num_produto
serial_data += self._serializar_produto_servico(produto_servico,
retorna_string=False)
serial_data += [
'\nW', #Valores totais NFe,
'\nW02',
formatar_decimal(nota_fiscal.totais_icms_base_calculo),
formatar_decimal(nota_fiscal.totais_icms_total),
'', # ICMSDeson
formatar_decimal(nota_fiscal.totais_icms_st_base_calculo),
formatar_decimal(nota_fiscal.totais_icms_st_total),
formatar_decimal(nota_fiscal.totais_icms_total_produtos_e_servicos),
formatar_decimal(nota_fiscal.totais_icms_total_frete),
formatar_decimal(nota_fiscal.totais_icms_total_seguro),
formatar_decimal(nota_fiscal.totais_icms_total_desconto),
formatar_decimal(nota_fiscal.totais_icms_total_ii),
formatar_decimal(nota_fiscal.totais_icms_total_ipi),
formatar_decimal(nota_fiscal.totais_icms_pis),
formatar_decimal(nota_fiscal.totais_icms_cofins),
formatar_decimal(nota_fiscal.totais_icms_outras_despesas_acessorias),
formatar_decimal(nota_fiscal.totais_icms_total_nota),
'', # vTotTrib
'\nX',
nota_fiscal.transporte_modalidade_frete,
'\nZ',
nota_fiscal.informacoes_adicionais_interesse_fisco,
nota_fiscal.informacoes_complementares_interesse_contribuinte,
'' # End Pipe
]
if retorna_string:
try:
return '|'.join(map(remover_acentos, serial_data))
except TypeError as err:
enum_args = '\n'.join(
map(
lambda x: str(x[0]) + ' ' + str(x[1]),
enumerate(serial_data)
)
)
message = err.message + '\n' + enum_args
raise TypeError(message)
return serial_data

8
pynfe/utils/webservices.py

@ -122,9 +122,9 @@ NFCE = {
'QR': ''
},
'SE': {
'QR': 'nfe.se.gov.br/portal/consultarNFCe.jsp?',
'HTTPS': 'https://www.',
'HOMOLOGACAO': 'http://www.hom.'
'QR': 'se.gov.br/portal/consultarNFCe.jsp?',
'HTTPS': 'http://www.nfce.',
'HOMOLOGACAO': 'http://www.hom.nfe.'
},
'BA': {
'STATUS': '',
@ -160,7 +160,7 @@ NFCE = {
'CHAVE': '',
'INUTILIZACAO': '',
'EVENTOS': '',
'QR': ''
'QR': 'http://www4.fazenda.rj.gov.br/consultaNFCe/QRCode?'
},
'SP': {
'STATUS': 'nfce.fazenda.sp.gov.br/ws/nfestatusservico2.asmx',

5
setup.py

@ -1,6 +1,9 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
from pip.req import parse_requirements as parse
try: # for pip >= 10
from pip._internal.req import parse_requirements as parse
except ImportError: # for pip <= 9.0.3
from pip.req import parse_requirements as parse
requirements = lambda f: [str(i.req) for i in parse(f, session=False)]

Loading…
Cancel
Save