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
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
def gerar_qrcode(self, token, csc, xml, return_qr=False): """ Classe para gerar url do qrcode da NFC-e """ # Procura atributos no xml ns = {'ns':'http://www.portalfiscal.inf.br/nfe'} sig = {'sig':'http://www.w3.org/2000/09/xmldsig#'} # Tag Raiz NFe Ex: <NFe> nfe = xml chave = nfe[0].attrib['Id'].replace('NFe','') data = nfe.xpath('ns:infNFe/ns:ide/ns:dhEmi/text()', namespaces=ns)[0].encode() tpamb = nfe.xpath('ns:infNFe/ns:ide/ns:tpAmb/text()', namespaces=ns)[0] cuf = nfe.xpath('ns:infNFe/ns:ide/ns:cUF/text()', namespaces=ns)[0] uf = [key for key, value in CODIGOS_ESTADOS.items() if value == cuf][0] # tenta encontrar a tag cpf try: cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CPF/text()', namespaces=ns)[0] except IndexError: # em caso de erro tenta procurar a tag cnpj try: cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CNPJ/text()', namespaces=ns)[0] except IndexError: cpf = None total = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vNF/text()', namespaces=ns)[0] icms = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vICMS/text()', namespaces=ns)[0] digest = nfe.xpath('sig:Signature/sig:SignedInfo/sig:Reference/sig:DigestValue/text()', namespaces=sig)[0].encode() data = base64.b16encode(data).decode() digest = base64.b16encode(digest).decode() if cpf is None: url = 'chNFe={}&nVersao={}&tpAmb={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format( chave, VERSAO_QRCODE, tpamb, data.lower(), total, icms, digest.lower(), token) else: url = 'chNFe={}&nVersao={}&tpAmb={}&cDest={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format( chave, VERSAO_QRCODE, tpamb, cpf, data.lower(), total, icms, digest.lower(), token) url_hash = hashlib.sha1(url.encode()+csc.encode()).digest() url_hash = base64.b16encode(url_hash).decode() url = url + '&cHashQRCode=' + url_hash.upper() # 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, 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') etree.tostring(nfe.find(".//qrCode"), encoding='unicode') \ .replace('\n','').replace('<','<').replace('>','>').replace('amp;','') nfe = etree.fromstring(tnfe) # retorna nfe com o qrcode incluido NT2015/002 e qrcode if return_qr: return nfe, qrcode.strip() # retorna apenas nfe com o qrcode incluido NT2015/002 else: return nfe
def gerar_qrcode(self, token, csc, xml, return_qr=False): """ Classe para gerar url do qrcode da NFC-e """ try: # Procura atributos no xml ns = {'ns':'http://www.portalfiscal.inf.br/nfe'} sig = {'sig':'http://www.w3.org/2000/09/xmldsig#'} # Tag Raiz NFe Ex: <NFe> nfe = xml chave = nfe[0].attrib['Id'].replace('NFe','') data = nfe.xpath('ns:infNFe/ns:ide/ns:dhEmi/text()', namespaces=ns)[0].encode() tpamb = nfe.xpath('ns:infNFe/ns:ide/ns:tpAmb/text()', namespaces=ns)[0] cuf = nfe.xpath('ns:infNFe/ns:ide/ns:cUF/text()', namespaces=ns)[0] uf = [key for key, value in CODIGOS_ESTADOS.items() if value == cuf][0] # tenta encontrar a tag cpf try: cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CPF/text()', namespaces=ns)[0] except IndexError: # em caso de erro tenta procurar a tag cnpj try: cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CNPJ/text()', namespaces=ns)[0] except IndexError: cpf = None cpf = None total = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vNF/text()', namespaces=ns)[0] icms = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vICMS/text()', namespaces=ns)[0] digest = nfe.xpath('sig:Signature/sig:SignedInfo/sig:Reference/sig:DigestValue/text()', namespaces=sig)[0].encode() data = base64.b16encode(data).decode() digest = base64.b16encode(digest).decode() if cpf is None: url = 'chNFe={}&nVersao={}&tpAmb={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format( chave, VERSAO_QRCODE, tpamb, data.lower(), total, icms, digest.lower(), token) else: url = 'chNFe={}&nVersao={}&tpAmb={}&cDest={}&dhEmi={}&vNF={}&vICMS={}&digVal={}&cIdToken={}'.format( chave, VERSAO_QRCODE, tpamb, cpf, data.lower(), total, icms, digest.lower(), token) url_hash = hashlib.sha1(url.encode()+csc.encode()).digest() url_hash = base64.b16encode(url_hash).decode() url = url + '&cHashQRCode=' + url_hash.upper() if uf.upper() == 'PR': qrcode = NFCE[uf.upper()]['QR'] + url else: if tpamb == '1': qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url else: qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url # adicionta tag infNFeSupl com qrcode info = etree.Element('infNFeSupl') etree.SubElement(info, 'qrCode').text = '<![CDATA['+ qrcode.strip() + ']]>' nfe.insert(1, info) # retorna nfe com o qrcode incluido NT2015/002 e qrcode if return_qr: return nfe, qrcode.strip() # retorna apenas nfe com o qrcode incluido NT2015/002 else: return nfe except Exception as e: raise e
def gerar_qrcode(self, token, csc, xml, return_qr=False, online=True): """ Classe para gerar url do qrcode da NFC-e """ # Procura atributos no xml ns = {'ns':NAMESPACE_NFE} sig = {'sig':NAMESPACE_SIG} # Tag Raiz NFe Ex: <NFe> nfe = xml chave = nfe[0].attrib['Id'].replace('NFe','') data = nfe.xpath('ns:infNFe/ns:ide/ns:dhEmi/text()', namespaces=ns)[0].encode() tpamb = nfe.xpath('ns:infNFe/ns:ide/ns:tpAmb/text()', namespaces=ns)[0] cuf = nfe.xpath('ns:infNFe/ns:ide/ns:cUF/text()', namespaces=ns)[0] uf = [key for key, value in CODIGOS_ESTADOS.items() if value == cuf][0] # tenta encontrar a tag cpf try: cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CPF/text()', namespaces=ns)[0] except IndexError: # em caso de erro tenta procurar a tag cnpj try: cpf = nfe.xpath('ns:infNFe/ns:dest/ns:CNPJ/text()', namespaces=ns)[0] except IndexError: cpf = None total = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vNF/text()', namespaces=ns)[0] # icms = nfe.xpath('ns:infNFe/ns:total/ns:ICMSTot/ns:vICMS/text()', namespaces=ns)[0] digest = nfe.xpath('sig:Signature/sig:SignedInfo/sig:Reference/sig:DigestValue/text()', namespaces=sig)[0].encode() lista_dia = re.findall("-\d{2}", str(data)) dia = str(lista_dia[1]) dia = dia[1:] replacements = {'0': ''} token = re.sub('([0])', lambda m: replacements[m.group()], token) #VERSAO_QRCODE =2 if online: #versão online url = '{}|{}|{}|{}'.format(chave,VERSAO_QRCODE, tpamb, token) else: #versão offline digest = digest.lower() digest = digest.hex() url = '{}|{}|{}|{}|{}|{}|{}'.format( chave,VERSAO_QRCODE,tpamb,dia,total,digest,token ) url_complementar = url + csc url_hash = hashlib.sha1(url_complementar.encode()).digest() url_hash = base64.b16encode(url_hash).decode() url = 'p={}|{}'.format(url, url_hash) # 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', 'DF'] 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'] 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'] # BA tem comportamento distindo para qrcode e url elif uf.upper() == 'BA': if tpamb == '1': qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url else: qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url url_chave = url_chave = NFCE[uf.upper()]['URL'] # AC, AM, RR, PA, else: if tpamb == '1': qrcode = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['QR'] + url url_chave = NFCE[uf.upper()]['HTTPS'] + NFCE[uf.upper()]['URL'] else: qrcode = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['QR'] + url url_chave = NFCE[uf.upper()]['HOMOLOGACAO'] + NFCE[uf.upper()]['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') etree.tostring(nfe.find(".//qrCode"), encoding='unicode') \ .replace('\n','').replace('<','<').replace('>','>').replace('amp;','') nfe = etree.fromstring(tnfe) # retorna nfe com o qrcode incluido NT2015/002 e qrcode if return_qr: return nfe, qrcode.strip() # retorna apenas nfe com o qrcode incluido NT2015/002 else: return nfe
def _serializar_nota_fiscal(self, nota_fiscal, retorna_string=True): cod_municipio, municipio = obter_municipio_e_codigo( nota_fiscal.municipio, nota_fiscal.uf ) serial_data = [ 'A', '2.00', # Versão da NFe | notasfiscal.modelo está em int() 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-%d'), nota_fiscal.data_saida_entrada.strftime('%Y-%m-%d'), nota_fiscal.hora_saida_entrada.strftime('%H:%M:%S'), nota_fiscal.tipo_documento, 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.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), 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), '\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(safe_str, 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