예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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('&lt;','<').replace('&gt;','>').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
예제 #4
0
    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
예제 #5
0
    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('&lt;','<').replace('&gt;','>').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
예제 #6
0
    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