Пример #1
0
    def _prepare_eletronic_invoice_values(self):
        if self.model not in ('nfe', 'nfce'):
            return

        tz = timezone(self.env.user.tz or 'America/Sao_Paulo')
        dt_emissao = datetime.now(tz).replace(microsecond=0).isoformat()
        dt_saida = fields.Datetime.from_string(self.data_entrada_saida)
        if dt_saida:
            dt_saida = tz.localize(dt_saida).replace(microsecond=0).isoformat()
        else:
            dt_saida = dt_emissao

        ide = {
            'cUF':
            self.company_id.state_id.l10n_br_ibge_code,
            'cNF':
            "%08d" % self.numero_controle,
            'natOp':
            self.natureza_operacao,
            'mod':
            '55' if self.model == 'nfe' else '65',
            'serie':
            self.serie_documento,
            'nNF':
            self.numero,
            'dhEmi':
            dt_emissao,
            'dhSaiEnt':
            dt_saida,
            'tpNF':
            '0' if self.tipo_operacao == 'entrada' else '1',
            'idDest':
            self.ind_dest or 1,
            'cMunFG':
            "%s%s" % (self.company_id.state_id.l10n_br_ibge_code,
                      self.company_id.city_id.l10n_br_ibge_code),
            # Formato de Impressão do DANFE - 1 - Danfe Retrato, 4 - Danfe NFCe
            'tpImp':
            '1' if self.model == 'nfe' else '4',
            'tpEmis':
            int(self.tipo_emissao),
            'tpAmb':
            2 if self.ambiente == 'homologacao' else 1,
            'finNFe':
            self.finalidade_emissao,
            'indFinal':
            self.ind_final or '1',
            'indPres':
            self.ind_pres or '1',
            'procEmi':
            0,
            'verProc':
            'Odoo 11 - Trustcode',
        }
        # Documentos Relacionados
        documentos = []
        for doc in self.related_document_ids:
            data = fields.Datetime.from_string(doc.date)
            if doc.document_type == 'nfe':
                documentos.append({'refNFe': doc.access_key})
            elif doc.document_type == 'nf':
                documentos.append({
                    'refNF': {
                        'cUF': doc.state_id.l10n_br_ibge_code,
                        'AAMM': data.strftime("%y%m"),
                        'CNPJ': re.sub('[^0-9]', '', doc.cnpj_cpf),
                        'mod': doc.fiscal_document_id.code,
                        'serie': doc.serie,
                        'nNF': doc.internal_number,
                    }
                })

            elif doc.document_type == 'cte':
                documentos.append({'refCTe': doc.access_key})
            elif doc.document_type == 'nfrural':
                cnpj_cpf = re.sub('[^0-9]', '', doc.cnpj_cpf)
                documentos.append({
                    'refNFP': {
                        'cUF': doc.state_id.l10n_br_ibge_code,
                        'AAMM': data.strftime("%y%m"),
                        'CNPJ': cnpj_cpf if len(cnpj_cpf) == 14 else '',
                        'CPF': cnpj_cpf if len(cnpj_cpf) == 11 else '',
                        'IE': doc.inscr_est,
                        'mod': doc.fiscal_document_id.code,
                        'serie': doc.serie,
                        'nNF': doc.internal_number,
                    }
                })
            elif doc.document_type == 'cf':
                documentos.append({
                    'refECF': {
                        'mod': doc.fiscal_document_id.code,
                        'nECF': doc.serie,
                        'nCOO': doc.internal_number,
                    }
                })

        ide['NFref'] = documentos
        emit = {
            'tipo': self.company_id.partner_id.company_type,
            'cnpj_cpf': re.sub('[^0-9]', '', self.company_id.l10n_br_cnpj_cpf),
            'xNome': self.company_id.l10n_br_legal_name,
            'xFant': self.company_id.name,
            'enderEmit': {
                'xLgr':
                self.company_id.street,
                'nro':
                self.company_id.l10n_br_number,
                'xCpl':
                self.company_id.street2 or '',
                'xBairro':
                self.company_id.l10n_br_district,
                'cMun':
                '%s%s' %
                (self.company_id.partner_id.state_id.l10n_br_ibge_code,
                 self.company_id.partner_id.city_id.l10n_br_ibge_code),
                'xMun':
                self.company_id.city_id.name,
                'UF':
                self.company_id.state_id.code,
                'CEP':
                re.sub('[^0-9]', '', self.company_id.zip),
                'cPais':
                self.company_id.country_id.l10n_br_ibge_code,
                'xPais':
                self.company_id.country_id.name,
                'fone':
                re.sub('[^0-9]', '', self.company_id.phone or '')
            },
            'IE': re.sub('[^0-9]', '', self.company_id.l10n_br_inscr_est),
            'IEST': re.sub('[^0-9]', '', self.iest or ''),
            'CRT': self.cod_regime_tributario,
        }
        if self.company_id.l10n_br_cnae_main_id and self.company_id.l10n_br_inscr_mun:
            emit['IM'] = re.sub('[^0-9]', '', self.company_id.l10n_br_inscr_mun
                                or '')
            emit['CNAE'] = re.sub(
                '[^0-9]', '', self.company_id.l10n_br_cnae_main_id.code or '')
        dest = None
        exporta = None
        if self.commercial_partner_id:
            partner = self.commercial_partner_id
            dest = {
                'tipo': partner.company_type,
                'cnpj_cpf': re.sub('[^0-9]', '', partner.l10n_br_cnpj_cpf
                                   or ''),
                'xNome': partner.l10n_br_legal_name or partner.name,
                'enderDest': {
                    'xLgr':
                    partner.street,
                    'nro':
                    partner.l10n_br_number,
                    'xCpl':
                    partner.street2 or '',
                    'xBairro':
                    partner.l10n_br_district,
                    'cMun':
                    '%s%s' % (partner.state_id.l10n_br_ibge_code,
                              partner.city_id.l10n_br_ibge_code),
                    'xMun':
                    partner.city_id.name,
                    'UF':
                    partner.state_id.code,
                    'CEP':
                    re.sub('[^0-9]', '', partner.zip or ''),
                    'cPais': (partner.country_id.l10n_br_ibge_code or '')[-4:],
                    'xPais':
                    partner.country_id.name,
                    'fone':
                    re.sub('[^0-9]', '', partner.phone or '')
                },
                'indIEDest': self.ind_ie_dest,
                'IE': re.sub('[^0-9]', '', partner.l10n_br_inscr_est or ''),
                'ISUF': partner.l10n_br_suframa or '',
            }
            if self.model == 'nfce':
                dest.update({
                    'CPF':
                    re.sub('[^0-9]', '', partner.l10n_br_cnpj_cpf or '')
                })

            if self.ambiente == 'homologacao':
                dest['xNome'] = \
                    u'NF-E EMITIDA EM AMBIENTE DE HOMOLOGACAO -\
 SEM VALOR FISCAL'

            if partner.country_id.id != self.company_id.country_id.id:
                dest['idEstrangeiro'] = re.sub('[^0-9]', '',
                                               partner.l10n_br_cnpj_cpf or '')
                dest['enderDest']['UF'] = 'EX'
                dest['enderDest']['xMun'] = 'Exterior'
                dest['enderDest']['cMun'] = '9999999'
                dest['enderDest']['CEP'] = ''
                exporta = {
                    'UFSaidaPais': self.uf_saida_pais_id.code or '',
                    'xLocExporta': self.local_embarque or '',
                    'xLocDespacho': self.local_despacho or '',
                }

        autorizados = []
        if self.company_id.l10n_br_accountant_id:
            autorizados.append({
                'CNPJ':
                re.sub('[^0-9]', '',
                       self.company_id.l10n_br_accountant_id.l10n_br_cnpj_cpf)
            })

        eletronic_items = []
        for item in self.document_line_ids:
            eletronic_items.append(
                self._prepare_eletronic_invoice_item(item, self))
        total = {
            # ICMS
            'vBC': "%.02f" % self.valor_bc_icms,
            'vICMS': "%.02f" % self.valor_icms,
            'vICMSDeson': '0.00',
            'vFCP': '0.00',  # TODO Implementar aqui
            'vBCST': "%.02f" % self.valor_bc_icmsst,
            'vST': "%.02f" % self.valor_icmsst,
            'vFCPST': '0.00',
            'vFCPSTRet': '0.00',
            'vProd':
            "%.02f" % sum(self.document_line_ids.mapped("valor_bruto")),
            'vFrete': "%.02f" % self.valor_frete,
            'vSeg': "%.02f" % self.valor_seguro,
            'vDesc': "%.02f" % self.valor_desconto,
            'vII': "%.02f" % self.valor_ii,
            'vIPI': "%.02f" % self.valor_ipi,
            'vIPIDevol': '0.00',
            'vPIS': "%.02f" % self.pis_valor,
            'vCOFINS': "%.02f" % self.cofins_valor,
            'vOutro': "%.02f" % self.valor_despesas,
            'vNF': "%.02f" % self.valor_final,
            'vFCPUFDest': "%.02f" % self.valor_icms_fcp_uf_dest,
            'vICMSUFDest': "%.02f" % self.valor_icms_uf_dest,
            'vICMSUFRemet': "%.02f" % self.valor_icms_uf_remet,
            'vTotTrib': "%.02f" % self.valor_estimado_tributos,
        }
        if self.valor_servicos > 0.0:
            issqn_total = {
                'vServ':
                "%.02f" % self.valor_servicos if self.valor_servicos else "",
                'vBC':
                "%.02f" %
                self.iss_base_calculo if self.iss_base_calculo else "",
                'vISS':
                "%.02f" % self.iss_valor if self.iss_valor else "",
                'vPIS':
                "%.02f" % self.pis_valor if self.pis_valor else "",
                'vCOFINS':
                "%.02f" % self.cofins_valor if self.cofins_valor else "",
                'dCompet':
                dt_emissao[:10],
                'vDeducao':
                "",
                'vOutro':
                "",
                'vISSRet':
                "%.02f" %
                self.iss_valor_retencao if self.iss_valor_retencao else '',
            }
            tributos_retidos = {
                'vRetPIS':
                "%.02f" %
                self.iss_valor_retencao if self.iss_valor_retencao else '',
                'vRetCOFINS':
                "%.02f" % self.cofins_valor_retencao
                if self.cofins_valor_retencao else '',
                'vRetCSLL':
                "%.02f" %
                self.csll_valor_retencao if self.csll_valor_retencao else '',
                'vBCIRRF':
                "%.02f" %
                self.irrf_base_calculo if self.irrf_valor_retencao else '',
                'vIRRF':
                "%.02f" %
                self.irrf_valor_retencao if self.irrf_valor_retencao else '',
                'vBCRetPrev':
                "%.02f" %
                self.inss_base_calculo if self.inss_valor_retencao else '',
                'vRetPrev':
                "%.02f" %
                self.inss_valor_retencao if self.inss_valor_retencao else '',
            }
        if self.transportadora_id.street:
            end_transp = "%s - %s, %s" % (
                self.transportadora_id.street,
                self.transportadora_id.l10n_br_number
                or '', self.transportadora_id.l10n_br_district or '')
        else:
            end_transp = ''
        transp = {
            'modFrete': self.modalidade_frete,
            'transporta': {
                'xNome':
                self.transportadora_id.l10n_br_legal_name
                or self.transportadora_id.name or '',
                'IE':
                re.sub('[^0-9]', '', self.transportadora_id.l10n_br_inscr_est
                       or ''),
                'xEnder':
                end_transp if self.transportadora_id else '',
                'xMun':
                self.transportadora_id.city_id.name or '',
                'UF':
                self.transportadora_id.state_id.code or ''
            },
            'veicTransp': {
                'placa': self.placa_veiculo or '',
                'UF': self.uf_veiculo or '',
                'RNTC': self.rntc or '',
            }
        }
        cnpj_cpf = re.sub('[^0-9]', '', self.transportadora_id.l10n_br_cnpj_cpf
                          or '')
        if self.transportadora_id.is_company:
            transp['transporta']['CNPJ'] = cnpj_cpf
        else:
            transp['transporta']['CPF'] = cnpj_cpf

        reboques = []
        for item in self.reboque_ids:
            reboques.append({
                'placa': item.placa_veiculo or '',
                'UF': item.uf_veiculo or '',
                'RNTC': item.rntc or '',
                'vagao': item.vagao or '',
                'balsa': item.balsa or '',
            })
        transp['reboque'] = reboques
        volumes = []
        for item in self.volume_ids:
            volumes.append({
                'qVol':
                item.quantidade_volumes or '',
                'esp':
                item.especie or '',
                'marca':
                item.marca or '',
                'nVol':
                item.numeracao or '',
                'pesoL':
                "%.03f" % item.peso_liquido if item.peso_liquido else '',
                'pesoB':
                "%.03f" % item.peso_bruto if item.peso_bruto else '',
            })
        transp['vol'] = volumes

        duplicatas = []
        for dup in self.duplicata_ids:
            vencimento = fields.Datetime.from_string(dup.data_vencimento)
            duplicatas.append({
                'nDup': dup.numero_duplicata,
                'dVenc': vencimento.strftime('%Y-%m-%d'),
                'vDup': "%.02f" % dup.valor
            })
        cobr = {
            'fat': {
                'nFat': self.numero_fatura or '',
                'vOrig':
                "%.02f" % (self.fatura_liquido + self.fatura_desconto),
                'vDesc': "%.02f" % self.fatura_desconto,
                'vLiq': "%.02f" % self.fatura_liquido,
            },
            'dup': duplicatas
        }
        pag = {
            'indPag': '0',  # TODO colocar a prazo se tiver mais de uma parcela
            'tPag': '90',  # TODO Verificar esse campo aqui
            'vPag': '0.00',
        }
        infAdic = {
            'infCpl': self.informacoes_complementares or '',
            'infAdFisco': self.informacoes_legais or '',
        }
        compras = {
            'xNEmp': self.nota_empenho or '',
            'xPed': self.pedido_compra or '',
            'xCont': self.contrato_compra or '',
        }

        responsavel_tecnico = self.company_id.l10n_br_responsavel_tecnico_id
        infRespTec = {}

        if responsavel_tecnico:
            cnpj = re.sub('[^0-9]', '', responsavel_tecnico.l10n_br_cnpj_cpf)
            fone = re.sub('[^0-9]', '', responsavel_tecnico.phone or '')
            infRespTec = {
                'CNPJ': cnpj or '',
                'xContato': responsavel_tecnico.child_ids[0].name or '',
                'email': responsavel_tecnico.email or '',
                'fone': fone,
                'idCSRT': self.company_id.l10n_br_id_token_csrt or '',
                'hashCSRT': self._get_hash_csrt() or '',
            }

        vals = {
            'Id': '',
            'ide': ide,
            'emit': emit,
            'dest': dest,
            'autXML': autorizados,
            'detalhes': eletronic_items,
            'total': total,
            'pag': [pag],
            'transp': transp,
            'infAdic': infAdic,
            'exporta': exporta,
            'compra': compras,
            'infRespTec': infRespTec,
        }
        if self.valor_servicos > 0.0:
            vals.update({
                'ISSQNtot': issqn_total,
                'retTrib': tributos_retidos,
            })
        if len(duplicatas) > 0 and\
                self.fiscal_position_id.finalidade_emissao not in ('2', '4'):
            vals['cobr'] = cobr
            pag['tPag'] = '01' if pag['tPag'] == '90' else pag['tPag']
            pag['vPag'] = "%.02f" % self.valor_final

        if self.model == 'nfce':
            vals['pag'][0]['tPag'] = self.metodo_pagamento
            vals['pag'][0]['vPag'] = "%.02f" % self.valor_pago
            vals['pag'][0]['vTroco'] = "%.02f" % self.troco or '0.00'

            chave_nfe = self.chave_nfe
            ambiente = 1 if self.ambiente == 'producao' else 2
            estado = self.company_id.state_id.l10n_br_ibge_code

            cid_token = int(self.company_id.l10n_br_id_token_csc)
            csc = self.company_id.l10n_br_csc

            c_hash_QR_code = "{0}|2|{1}|{2}{3}".format(chave_nfe, ambiente,
                                                       int(cid_token), csc)
            c_hash_QR_code = hashlib.sha1(c_hash_QR_code.encode()).hexdigest()

            QR_code_url = "p={0}|2|{1}|{2}|{3}".format(chave_nfe, ambiente,
                                                       int(cid_token),
                                                       c_hash_QR_code)
            qr_code_server = url_qrcode(estado, str(ambiente))
            vals['qrCode'] = qr_code_server + QR_code_url
            vals['urlChave'] = url_qrcode_exibicao(estado, str(ambiente))
        return vals
Пример #2
0
def gerar_qrcode(id_csc: int, csc: str, xml_send: str, cert = False) -> str:
    xml = etree.fromstring(xml_send)
    signature = xml.find(
        ".//{http://www.w3.org/2000/09/xmldsig#}Signature")
    id = xml.find(
        ".//{http://www.portalfiscal.inf.br/nfe}infNFe").get('Id')
    if id is None:
        raise Exception("XML Invalido - Sem o ID")

    chave = id.replace('NFe', '')
    emit_uf = chave[:2]

    tp_amb = xml.find(".//{http://www.portalfiscal.inf.br/nfe}tpAmb")
    if tp_amb is None:
        raise Exception("XML Invalido - Sem o tipo de ambiente")

    dh_emi = xml.find(".//{http://www.portalfiscal.inf.br/nfe}dhEmi")
    if dh_emi is None:
        raise Exception("XML Invalido - Sem data de Emissao")
    dh_emi = dh_emi.text.split("-")[2].split("T")[0]

    tp_emis = xml.find(".//{http://www.portalfiscal.inf.br/nfe}tpEmis")
    if tp_emis is None:
        raise Exception("XML Invalido - Sem tipo de emissao")

    v_nf = xml.find(".//{http://www.portalfiscal.inf.br/nfe}vNF")
    if v_nf is None:
        raise Exception("XML Invalido - Sem o valor da NFe")

    url_qrcode_str = url_qrcode(
        estado=emit_uf,
        ambiente=tp_amb.text)
    url_qrcode_exibicao_str = url_qrcode_exibicao(
        estado=emit_uf,
        ambiente=tp_amb.text)

    if tp_emis != 1:
        if signature is None:
            if cert is not False:
                signer = Assinatura(certificado.pfx, certificado.password)
                xml_send = signer.assina_xml(xmlElem_send, id)
            else:
                raise Exception("XML Invalido - Sem assinatura e não "
                                "foi enviado o certificado nos parametros")
        digest_value = xml.find(
            ".//{http://www.w3.org/2000/09/xmldsig#}DigestValue")
        c_hash_qr_code = \
            "{ch_acesso}|{versao}|{tp_amb}|{dh_emi}|" \
            "{v_nf}|{dig_val}|{id_csc}|{csc}".format(
                ch_acesso=chave,
                versao=2,
                tp_amb=tp_amb.text,
                dh_emi=dh_emi,
                v_nf=float(v_nf.text),
                dig_val=digest_value.text,
                id_csc=int(id_csc),
                csc=csc
            )
        c_hash_qr_code = hashlib.sha1(c_hash_qr_code.encode()). \
            hexdigest()
        qr_code_url = 'p={ch_acesso}|{versao}|{tp_amb}|{dh_emi}|" \
                                "{v_nf}|{dig_val}|{id_csc}|{hash}'.format(
            ch_acesso=chave,
            versao=2,
            tp_amb=tp_amb.text,
            dh_emi=dh_emi,
            v_nf=float(v_nf.text),
            dig_val=digest_value.text,
            id_csc=int(id_csc),
            hash=c_hash_qr_code
        )
        qrcode = url_qrcode_str + qr_code_url
        url_consulta = url_qrcode_exibicao_str

        qrCode = xml.find(
            './/{http://www.portalfiscal.inf.br/nfe}qrCode').text = \
            qrcode
        urlChave = xml.find(
            './/{http://www.portalfiscal.inf.br/nfe}urlChave').text = \
            url_consulta
    else:
        c_hash_qr_code = \
        "{ch_acesso}|{versao}|{tp_amb}|{id_csc}|{csc}".format(
            ch_acesso=chave,
            versao=2,
            tp_amb=tp_amb.text,
            id_csc=int(id_csc),
            csc=csc
        )
        c_hash_qr_code = hashlib.sha1(c_hash_qr_code.encode()).hexdigest()

        qr_code_url = "p={ch_acesso}|{versao}|{tp_amb}|{id_csc}|" \
                      "{hash}".\
            format(
                ch_acesso=chave,
                versao=2,
                tp_amb=tp_amb.text,
                id_csc=int(id_csc),
                hash=c_hash_qr_code
            )
        qrcode = url_qrcode_str + qr_code_url
        url_consulta = url_qrcode_exibicao_str
        qrCode = xml.find(
            './/{http://www.portalfiscal.inf.br/nfe}qrCode').text = \
            qrcode
        urlChave = xml.find(
            './/{http://www.portalfiscal.inf.br/nfe}urlChave').text = \
            url_consulta
    return etree.tostring(xml)