Exemplo n.º 1
0
    def _construir_xml_status_pr(self, cabecalho, metodo, dados):
        u"""Mota o XML para o envio via SOAP"""

        raiz = etree.Element('{%s}Envelope' % NAMESPACE_SOAP,
                             nsmap={
                                 'xsi': NAMESPACE_XSI,
                                 'xsd': NAMESPACE_XSD,
                                 'soap': NAMESPACE_SOAP
                             })
        c = etree.SubElement(raiz, '{%s}Header' % NAMESPACE_SOAP)
        c.append(cabecalho)
        body = etree.SubElement(raiz, '{%s}Body' % NAMESPACE_SOAP)
        a = etree.SubElement(body,
                             'nfeDadosMsg',
                             xmlns=NAMESPACE_METODO + metodo)
        a.append(dados)
        return raiz
Exemplo n.º 2
0
    def status_servico(self, modelo):
        """
        Verifica status do servidor da receita.
        :param modelo: modelo é a string com tipo de serviço que deseja consultar, Ex: nfe ou nfce
        :return:
        """
        url = self._get_url(modelo, 'STATUS')
        # Monta XML do corpo da requisição
        raiz = etree.Element('consStatServ',
                             versao=VERSAO_PADRAO,
                             xmlns=NAMESPACE_NFE)
        etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()]
        etree.SubElement(raiz, 'xServ').text = 'STATUS'
        xml = self._construir_xml_soap('NFeStatusServico4', raiz)

        return self._post(url, xml)
Exemplo n.º 3
0
    def _serializar_transportadora(self,
                                   transportadora,
                                   tag_raiz='transporta',
                                   retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados da transportadora
        etree.SubElement(raiz,
                         transportadora.tipo_documento).text = so_numeros(
                             transportadora.numero_documento)
        etree.SubElement(raiz, 'xNome').text = transportadora.razao_social
        etree.SubElement(raiz, 'IE').text = transportadora.inscricao_estadual

        # Endereço
        etree.SubElement(raiz,
                         'xEnder').text = transportadora.endereco_logradouro
        etree.SubElement(raiz, 'cMun').text = transportadora.endereco_municipio
        etree.SubElement(raiz, 'xMun').text = obter_municipio_por_codigo(
            transportadora.endereco_municipio,
            transportadora.endereco_uf,
        )
        etree.SubElement(raiz, 'UF').text = transportadora.endereco_uf

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
Exemplo n.º 4
0
 def consulta_nota(self, modelo, chave):
     """
         Este método oferece a consulta da situação da NF-e/NFC-e na Base de Dados do Portal
         da Secretaria de Fazenda Estadual.
     :param modelo: Modelo da nota
     :param chave: Chave da nota
     :return:
     """
     # url do serviço
     url = self._get_url(modelo=modelo, consulta='CHAVE')
     # Monta XML do corpo da requisição
     raiz = etree.Element('consSitNFe', versao=VERSAO_PADRAO, xmlns=NAMESPACE_NFE)
     etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
     etree.SubElement(raiz, 'xServ').text = 'CONSULTAR'
     etree.SubElement(raiz, 'chNFe').text = chave
     # Monta XML para envio da requisição
     xml = self._construir_xml_soap('NFeConsultaProtocolo4', raiz)
     return self._post(url, xml)
Exemplo n.º 5
0
    def consulta_recibo(self, modelo, numero):
        """
            Este método oferece a consulta do resultado do processamento de um lote de NF-e.
            O aplicativo do Contribuinte deve ser construído de forma a aguardar um tempo mínimo de
            15 segundos entre o envio do Lote de NF-e para processamento e a consulta do resultado
            deste processamento, evitando a obtenção desnecessária do status de erro 105 - "Lote em
            Processamento".
        """
        # url do serviço
        url = self._get_url(modelo=modelo, consulta='RECIBO')
        # Monta XML do corpo da requisição
        raiz = etree.Element('consReciNFe', versao=VERSAO_PADRAO, xmlns=NAMESPACE_NFE)
        etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(raiz, 'nRec').text = numero
        # Monta XML para envio da requisição
        xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='NfeRetAutorizacao'), metodo='NfeRetAutorizacao', dados=raiz)

        return self._post(url, xml)
Exemplo n.º 6
0
 def cancelar(self, modelo, evento, idlote=1):
     """ Envia um evento de cancelamento de nota fiscal """
     # url do serviço
     url = self._get_url(modelo=modelo, consulta='EVENTOS')
     # Monta XML do corpo da requisição
     raiz = etree.Element('envEvento', versao='1.00', xmlns=NAMESPACE_NFE)
     etree.SubElement(raiz, 'idLote').text = str(idlote) # numero autoincremental gerado pelo sistema
     raiz.append(evento)
     xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='RecepcaoEvento'), metodo='RecepcaoEvento', dados=raiz)
     return self._post(url, xml)
Exemplo n.º 7
0
    def nfeInutilizacaoNF(self, raiz):
        data_hora = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')

        ret = etree.Element('retInutNFe')
        etree.SubElement(ret, 'versao').text = '1.00' # FIXME

        xml_dados = raiz.getroot().getchildren()[0].getchildren()[0].getchildren()[1].text

        xml = etree.tostring(ret, encoding='utf-8', xml_declaration=True)
        self.write(xml)
Exemplo n.º 8
0
    def consulta_distribuicao(self,
                              cnpj=None,
                              cpf=None,
                              chave=None,
                              nsu=0,
                              consulta_nsu=False):
        """ 
            O XML do pedido de distribuição suporta três tipos de consultas que são definidas de acordo com a tag
            informada no XML. As tags são distNSU, consNSU e consChNFe.
            a) distNSU – Distribuição de Conjunto de DF-e a Partir do NSU Informado
            b) consNSU – Consulta DF-e Vinculado ao NSU Informado
            c) consChNFe – Consulta de NF-e por Chave de Acesso Informada 
        :param cnpj: CNPJ do interessado
        :param cpf: CPF do interessado
        :param chave: Chave da NF-e a ser consultada
        :param nsu: Ultimo nsu ou nsu específico para ser consultado.
        :return: 
        """
        # url
        url = self._get_url_an(consulta='DISTRIBUICAO')
        # Monta XML para envio da requisição
        raiz = etree.Element('distDFeInt', versao='1.01', xmlns=NAMESPACE_NFE)
        etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
        if self.uf:
            etree.SubElement(
                raiz, 'cUFAutor').text = CODIGOS_ESTADOS[self.uf.upper()]
        if cnpj:
            etree.SubElement(raiz, 'CNPJ').text = cnpj
        else:
            etree.SubElement(raiz, 'CPF').text = cpf
        if not chave and not consulta_nsu:
            distNSU = etree.SubElement(raiz, 'distNSU')
            etree.SubElement(distNSU, 'ultNSU').text = str(nsu).zfill(15)
        if chave:
            consChNFe = etree.SubElement(raiz, 'consChNFe')
            etree.SubElement(consChNFe, 'chNFe').text = chave
        if consulta_nsu:
            nsu_tag = etree.SubElement(raiz, 'consNSU')
            etree.SubElement(nsu_tag, 'NSU').text = nsu
        #Monta XML para envio da requisição
        xml = self._construir_xml_soap('NFeDistribuicaoDFe', raiz)

        return self._post(url, xml)
Exemplo n.º 9
0
    def nfeStatusServicoNF2(self, raiz):
        data_hora = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S')

        ret = etree.Element('retConsStatServ')
        etree.SubElement(ret, 'versao').text = '1.00'  # FIXME
        etree.SubElement(ret, 'tbAmb').text = '2'  # Homologação
        etree.SubElement(ret, 'verAplic').text = self.sigla_servidor
        etree.SubElement(ret, 'cStat').text = '1'  # FIXME
        etree.SubElement(
            ret, 'xMotivo').text = 'Servico em funcionamento normal'  # FIXME
        etree.SubElement(ret,
                         'cUF').text = CODIGOS_ESTADOS[self.sigla_servidor]
        etree.SubElement(ret, 'dhRecbto').text = data_hora
        etree.SubElement(ret, 'tMed').text = '10'
        etree.SubElement(ret, 'dhRetorno').text = data_hora
        etree.SubElement(ret, 'xObs').text = 'Nenhuma informacao adicional'

        xml = etree.tostring(ret, encoding='utf-8', xml_declaration=True)
        self.write(xml)
Exemplo n.º 10
0
    def download(self, cnpj, chave):
        """
            Metodo para download de NFe por parte de destinatário.
            O certificado digital deve ser o mesmo do destinatário da Nfe.
            NT 2012/002
        """
        # url do serviço
        url = self._get_url_AN(consulta='DOWNLOAD')
        # Monta XML do corpo da requisição
        raiz = etree.Element('downloadNFe', versao='1.00', xmlns=NAMESPACE_NFE)
        etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(raiz, 'xServ').text = 'DOWNLOAD NFE'
        etree.SubElement(raiz, 'CNPJ').text = str(cnpj)
        etree.SubElement(raiz, 'chNFe').text = str(chave)

        # Monta XML para envio da requisição
        xml = self._construir_xml_soap('NfeDownloadNF', raiz)

        return self._post(url, xml)
Exemplo n.º 11
0
    def status_servico(self, modelo):
        """ Verifica status do servidor da receita. """
        """ modelo é a string com tipo de serviço que deseja consultar
            Ex: nfe ou nfce 
        """
        url = self._get_url(modelo=modelo, consulta='STATUS')

        # Monta XML do corpo da requisição
        raiz = etree.Element('consStatServ',
                             versao=VERSAO_PADRAO,
                             xmlns=NAMESPACE_NFE)
        etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()]
        etree.SubElement(raiz, 'xServ').text = 'STATUS'
        # Monta XML para envio da requisição
        xml = self._construir_xml_status_pr(
            cabecalho=self._cabecalho_soap(metodo='NfeStatusServico2'),
            metodo='NfeStatusServico2',
            dados=raiz)
        # Chama método que efetua a requisição POST no servidor SOAP
        return self._post(url, xml)
Exemplo n.º 12
0
 def _construir_xml_soap(self, metodo, dados, cabecalho=False):
     """Mota o XML para o envio via SOAP"""
     raiz = etree.Element('{%s}Envelope' % NAMESPACE_SOAP,
                          nsmap={
                              'xsi': NAMESPACE_XSI,
                              'xsd': NAMESPACE_XSD,
                              'soap': NAMESPACE_SOAP
                          })
     body = etree.SubElement(raiz, '{%s}Body' % NAMESPACE_SOAP)
     ## distribuição tem um corpo de xml diferente
     if metodo == 'NFeDistribuicaoDFe':
         x = etree.SubElement(body,
                              'nfeDistDFeInteresse',
                              xmlns=NAMESPACE_METODO + metodo)
         a = etree.SubElement(x, 'nfeDadosMsg')
     else:
         a = etree.SubElement(body,
                              'nfeDadosMsg',
                              xmlns=NAMESPACE_METODO + metodo)
     a.append(dados)
     return raiz
Exemplo n.º 13
0
    def consulta_notas_cnpj(self, cnpj, nsu=0):
        """
            “Serviço de Consulta da Relação de Documentos Destinados” para um determinado CNPJ de destinatário informado na NF-e. 
        """
        # url do serviço
        url = self._get_url(modelo='nfe', consulta='DESTINADAS')
        # Monta XML do corpo da requisição
        raiz = etree.Element('consNFeDest', versao='1.01', xmlns=NAMESPACE_NFE)
        etree.SubElement(raiz, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(raiz, 'xServ').text = 'CONSULTAR NFE DEST'
        etree.SubElement(raiz, 'CNPJ').text = cnpj
        # Indicador de NF-e consultada:
        # 0=Todas as NF-e;
        # 1=Somente as NF-e que ainda não tiveram manifestação do destinatário (Desconhecimento da operação, Operação não Realizada ou Confirmação da Operação);
        # 2=Idem anterior, incluindo as NF-e que também não tiveram a Ciência da Operação.
        etree.SubElement(raiz, 'indNFe').text = '0'
        # Indicador do Emissor da NF-e:
        # 0=Todos os Emitentes / Remetentes;
        # 1=Somente as NF-e emitidas por emissores / remetentes que não tenham o mesmo CNPJ-Base do destinatário (para excluir as notas fiscais de transferência entre filiais).
        etree.SubElement(raiz, 'indEmi').text = '0'
        # Último NSU recebido pela Empresa. Caso seja informado com zero, ou com um NSU muito antigo, a consulta retornará unicamente as notas fiscais que tenham sido recepcionadas nos últimos 15 dias.
        etree.SubElement(raiz, 'ultNSU').text = str(nsu)

        # Monta XML para envio da requisição
        xml = self._construir_xml_status_pr(
            cabecalho=self._cabecalho_soap(metodo='NfeConsultaDest'),
            metodo='NfeConsultaDest',
            dados=raiz)

        return self._post(url, xml)
Exemplo n.º 14
0
    def consultar_cadastro(self, modelo, ie, cnpj):
        # RS implementa um método diferente na consulta de cadastro
        if self.uf.upper() == 'RS':
            url = NFE['RS']['CADASTRO']
        elif self.uf.upper() == 'SVRS':
            url = NFE['SVRS']['CADASTRO']
        elif self.uf.upper() == 'SVC-RS':
            url = NFE['SVC-RS']['CADASTRO']
        else:
            url = self._get_url(modelo=modelo, consulta='CADASTRO')

        raiz = etree.Element('ConsCad', versao=VERSAO_PADRAO, xmlns=NAMESPACE_NFE)
        info = etree.SubElement(raiz, 'infCons')
        etree.SubElement(info, 'xServ').text = 'CONS-CAD'
        etree.SubElement(info, 'UF').text = self.uf.upper()
        etree.SubElement(info, 'IE').text = ie
        etree.SubElement(info, 'CNPJ').text = cnpj
        #etree.SubElement(info, 'CPF').text = cpf
        # Monta XML para envio da requisição
        xml = self._construir_xml_status_pr(cabecalho=self._cabecalho_soap(metodo='CadConsultaCadastro2'), metodo='CadConsultaCadastro2', dados=raiz)
        # Chama método que efetua a requisição POST no servidor SOAP
        return self._post(url, xml)
Exemplo n.º 15
0
    def consulta_cadastro(self, modelo, cnpj):
        # UF que utilizam a SVRS - Sefaz Virtual do RS: Para serviço de Consulta Cadastro: AC, RN, PB, SC
        lista_svrs = ['AC', 'RN', 'PB', 'SC']
        # RS implementa um método diferente na consulta de cadastro
        if self.uf.upper() == 'RS':
            url = NFE['RS']['CADASTRO']
        elif self.uf.upper() in lista_svrs:
            url = NFE['SVRS']['CADASTRO']
        elif self.uf.upper() == 'SVC-RS':
            url = NFE['SVC-RS']['CADASTRO']
        else:
            url = self._get_url(modelo=modelo, consulta='CADASTRO')

        raiz = etree.Element('ConsCad', versao='2.00', xmlns=NAMESPACE_NFE)
        info = etree.SubElement(raiz, 'infCons')
        etree.SubElement(info, 'xServ').text = 'CONS-CAD'
        etree.SubElement(info, 'UF').text = self.uf.upper()
        etree.SubElement(info, 'CNPJ').text = cnpj
        #etree.SubElement(info, 'CPF').text = cpf
        # Monta XML para envio da requisição
        xml = self._construir_xml_soap('CadConsultaCadastro4', raiz)
        # Chama método que efetua a requisição POST no servidor SOAP
        return self._post(url, xml)
Exemplo n.º 16
0
    def _cabecalho(self, retorna_string=True):
        """ Monta o XML do cabeçalho da requisição wsdl
            Namespaces padrão homologação (Ginfes) """

        xml_declaration='<?xml version="1.0" encoding="UTF-8"?>'
        # cabecalho = '<ns2:cabecalho versao="3" xmlns:ns2="http://www.ginfes.com.br/cabecalho_v03.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><versaoDados>3</versaoDados></ns2:cabecalho>'
         # cabecalho
        raiz = etree.Element('{%s}cabecalho'%self._namespace, nsmap={'ns2':self._namespace, 'xsi':NAMESPACE_XSI}, versao=self._versao)
        etree.SubElement(raiz, 'versaoDados').text = self._versao

        if retorna_string:
            cabecalho = etree.tostring(raiz, encoding='unicode', pretty_print=False).replace('\n','')
            cabecalho = xml_declaration + cabecalho
            return cabecalho
        else:
            return raiz
Exemplo n.º 17
0
    def _cabecalho2(self, retorna_string=True):
        """ Monta o XML do cabeçalho da requisição wsdl
            Namespaces que funcionaram em produção (Ginfes)"""

        xml_declaration = '<?xml version="1.0" encoding="UTF-8"?>'

        # cabecalho
        raiz = etree.Element('cabecalho', xmlns=self._namespace, versao=self._versao)
        etree.SubElement(raiz, 'versaoDados').text = self._versao

        if retorna_string:
            cabecalho = etree.tostring(raiz, encoding='unicode', pretty_print=False).replace('\n', '')
            cabecalho = xml_declaration + cabecalho
            return cabecalho
        else:
            return raiz
Exemplo n.º 18
0
 def evento(self, modelo, evento, idlote=1):
     """ Envia um evento de nota fiscal (cancelamento e carta de correção)"""
     # url do serviço
     try:
         # manifestacao url é do AN
         if evento[0][5].text.startswith('2'):
             url = self._get_url_AN(consulta='EVENTOS')
         else:
             url = self._get_url(modelo=modelo, consulta='EVENTOS')
     except Exception:
         url = self._get_url(modelo=modelo, consulta='EVENTOS')
     # Monta XML do corpo da requisição
     raiz = etree.Element('envEvento', versao='1.00', xmlns=NAMESPACE_NFE)
     etree.SubElement(raiz, 'idLote').text = str(
         idlote)  # numero autoincremental gerado pelo sistema
     raiz.append(evento)
     xml = self._construir_xml_soap('NFeRecepcaoEvento4', raiz)
     return self._post(url, xml)
Exemplo n.º 19
0
    def _serializar_entrega_retirada(self, entrega_retirada, tag_raiz='entrega', retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados da entrega/retirada
        etree.SubElement(raiz, entrega_retirada.tipo_documento).text = so_numeros(entrega_retirada.numero_documento)

        # Endereço
        etree.SubElement(raiz, 'xLgr').text = entrega_retirada.endereco_logradouro
        etree.SubElement(raiz, 'nro').text = entrega_retirada.endereco_numero
        etree.SubElement(raiz, 'xCpl').text = entrega_retirada.endereco_complemento
        etree.SubElement(raiz, 'xBairro').text = entrega_retirada.endereco_bairro
        etree.SubElement(raiz, 'cMun').text = entrega_retirada.endereco_municipio
        etree.SubElement(raiz, 'xMun').text = obter_municipio_por_codigo(
                entrega_retirada.endereco_municipio, entrega_retirada.endereco_uf,
                )
        etree.SubElement(raiz, 'UF').text = entrega_retirada.endereco_uf

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemplo n.º 20
0
    def _cabecalho_soap(self, metodo):
        """Monta o XML do cabeçalho da requisição SOAP"""

        raiz = etree.Element('nfeCabecMsg', xmlns=NAMESPACE_METODO + metodo)
        if metodo == 'RecepcaoEvento':
            etree.SubElement(raiz, 'versaoDados').text = '1.00'
        elif metodo == 'NfeConsultaDest':
            etree.SubElement(raiz, 'versaoDados').text = '1.01'
        elif metodo == 'NfeDownloadNF':
            etree.SubElement(raiz, 'versaoDados').text = '1.00'
        elif metodo == 'CadConsultaCadastro2':
            etree.SubElement(raiz, 'versaoDados').text = '2.00'
        else:
            etree.SubElement(raiz, 'versaoDados').text = VERSAO_PADRAO
        etree.SubElement(raiz, 'cUF').text = CODIGOS_ESTADOS[self.uf.upper()]
        return raiz
Exemplo n.º 21
0
def construir_xml_soap(self, metodo, dados, cabecalho=False):
    NAMESPACE_MDFE = "http://www.portalfiscal.inf.br/mdfe/wsdl/MDFeRecepcao"
    """Mota o XML para o envio via SOAP"""
    raiz = etree.Element('{%s}Envelope' % NAMESPACE_SOAP,
                         nsmap={
                             'xsi': NAMESPACE_XSI,
                             'xsd': NAMESPACE_XSD,
                             'soap12': NAMESPACE_SOAP
                         })
    header = etree.SubElement(raiz, '{%s}Header' % NAMESPACE_SOAP)
    body = etree.SubElement(raiz, '{%s}Body' % NAMESPACE_SOAP)
    #cbcMsg = etree.SubElement(header, 'mdfeCabecMsg', xmlns=NAMESPACE_MDFE)
    # distribuição tem um corpo de xml diferente
    if metodo == 'NFeDistribuicaoDFe':
        print("OPS!!")
        #xml = etree.SubElement(body, 'nfeDistDFeInteresse', xmlns=NAMESPACE_METODO+metodo)
        #a = etree.SubElement(x, 'mdfeCabecMsg')
    else:
        idmdfe = "MDFe22554575125155451212132"
        mdfeCabec = etree.SubElement(header,
                                     'mdfeCabecMsg',
                                     xmlns=NAMESPACE_MDFE)
        etree.SubElement(mdfeCabec, 'cUF').text = "22"
        etree.SubElement(mdfeCabec, 'versaoDados').text = "3.00"
        a = etree.SubElement(body, 'mdfeDadosMsg', xmlns=NAMESPACE_MDFE)
        #envimdfe = etree.SubElement(a, 'enviMDFe')
        mdfe = a

        #a = etree.SubElement(body, 'mdfeDadosMsg', xmlns=NAMESPACE_METODO+metodo)
        NAMESPACE_METODO2 = 'http://www.portalfiscal.inf.br/'
    mdfe.append(dados)
    envimdfe = mdfe.find("enviMDFe")
    idLote = etree.Element('idLote')
    root = etree.Element('MDFe')
    idLote.text = "1"
    envimdfe.insert(0, idLote)
    envimdfe.insert(1, root)
    #ide = envimdfe.find("ide")
    #ide, emit, infModal, infDoc, tot
    root.insert(0, envimdfe.find("ide"))
    root.insert(1, envimdfe.find("emit"))
    root.insert(2, envimdfe.find("infModal"))
    root.insert(3, envimdfe.find("infDoc"))
    root.insert(4, envimdfe.find("tot"))
    return raiz
Exemplo n.º 22
0
    def assinar(self, xml, retorna_string=False):
        # busca tag que tem id(reference_uri), logo nao importa se tem namespace
        reference = xml.find(".//*[@Id]").attrib['Id']
        #print('Referencia: ',reference)
        # retira acentos
        xml_str = remover_acentos(
            etree.tostring(xml, encoding="unicode", pretty_print=False))
        xml = etree.fromstring(xml_str)

        signer = XMLSigner(
            method=signxml.methods.enveloped,
            signature_algorithm="rsa-sha1",
            digest_algorithm='sha1',
            c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')

        ns = {None: signer.namespaces['ds']}
        signer.namespaces = ns
        #print('Chave......: ',self.key)
        #print('*',200)
        #print('Certificado: ',self.cert)
        ref_uri = ('#%s' % reference) if reference else None
        signed_root = signer.sign(xml,
                                  key=self.key,
                                  cert=self.cert,
                                  reference_uri=ref_uri)

        ns = {'ns': NAMESPACE_SIG}
        # coloca o certificado na tag X509Data/X509Certificate
        tagX509Data = signed_root.find('.//ns:X509Data', namespaces=ns)
        etree.SubElement(tagX509Data, 'X509Certificate').text = self.cert
        #print('Assinatura: ',etree.tostring(signed_root, encoding="unicode", pretty_print=False) )
        if retorna_string:
            return etree.tostring(signed_root,
                                  encoding="unicode",
                                  pretty_print=False)
        else:
            return signed_root
Exemplo n.º 23
0
    def _serializar_produto_servico(self,
                                    produto_servico,
                                    tag_raiz='det',
                                    retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Produto
        prod = etree.SubElement(raiz, 'prod')
        etree.SubElement(prod, 'cProd').text = str(produto_servico.codigo)
        etree.SubElement(prod, 'cEAN').text = produto_servico.ean
        etree.SubElement(prod, 'xProd').text = produto_servico.descricao
        etree.SubElement(prod, 'CFOP').text = produto_servico.cfop
        etree.SubElement(prod, 'uCom').text = produto_servico.unidade_comercial
        etree.SubElement(prod, 'qCom').text = str(
            produto_servico.quantidade_comercial or 0)
        etree.SubElement(prod, 'vUnCom').text = str(
            produto_servico.valor_unitario_comercial or 0)
        etree.SubElement(prod,
                         'vProd').text = str(produto_servico.valor_total_bruto
                                             or 0)
        etree.SubElement(prod,
                         'cEANTrib').text = produto_servico.ean_tributavel
        etree.SubElement(prod,
                         'uTrib').text = produto_servico.unidade_tributavel
        etree.SubElement(prod, 'qTrib').text = str(
            produto_servico.quantidade_tributavel)
        etree.SubElement(prod, 'vUnTrib').text = str(
            produto_servico.valor_unitario_tributavel)

        # Imposto
        imposto = etree.SubElement(raiz, 'imposto')

        icms = etree.SubElement(imposto, 'ICMS')
        icms_item = etree.SubElement(
            icms, 'ICMS' + produto_servico.icms_situacao_tributaria)
        etree.SubElement(icms_item,
                         'orig').text = str(produto_servico.icms_origem)
        etree.SubElement(icms_item,
                         'CST').text = produto_servico.icms_situacao_tributaria
        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)

        pis = etree.SubElement(imposto, 'PIS')
        pis_item = etree.SubElement(pis, 'PISAliq')
        etree.SubElement(pis_item, 'CST').text = str(
            produto_servico.pis_situacao_tributaria)
        etree.SubElement(pis_item, 'vBC').text = str(
            produto_servico.pis_valor_base_calculo)
        etree.SubElement(pis_item, 'pPIS').text = str(
            produto_servico.pis_aliquota_percentual)
        etree.SubElement(pis_item,
                         'vPIS').text = str(produto_servico.pis_valor)

        cofins = etree.SubElement(imposto, 'COFINS')
        cofins_item = etree.SubElement(cofins, 'COFINSAliq')
        etree.SubElement(cofins_item, 'CST').text = str(
            produto_servico.cofins_situacao_tributaria)
        etree.SubElement(cofins_item, 'vBC').text = str(
            produto_servico.cofins_valor_base_calculo)
        etree.SubElement(cofins_item, 'pCOFINS').text = str(
            produto_servico.cofins_aliquota_percentual)
        etree.SubElement(cofins_item,
                         'vCOFINS').text = str(produto_servico.cofins_valor)

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
Exemplo n.º 24
0
    def inutilizacao(self, modelo, cnpj, numero_inicial, numero_final, justificativa='', ano=None, serie='1'):
        """
        Serviço destinado ao atendimento de solicitações de inutilização de numeração.
        :param modelo: Modelo da nota
        :param cnpj: CNPJda empresa
        :param numero_inicial: Número inicial
        :param numero_final: Número final
        :param justificativa: Justificativa
        :param ano: Ano
        :param serie:  Série
        :return:
        """

        # url do servico
        url = self._get_url(modelo=modelo, consulta='INUTILIZACAO')

        # Valores default
        ano = str(ano or datetime.date.today().year)[-2:]
        uf = CODIGOS_ESTADOS[self.uf.upper()]
        cnpj = so_numeros(cnpj)

        # Identificador da TAG a ser assinada formada com Código da UF + Ano (2 posições) +
        #  CNPJ + modelo + série + nro inicial e nro final precedida do literal “ID”
        id_unico = 'ID%(uf)s%(ano)s%(cnpj)s%(modelo)s%(serie)s%(num_ini)s%(num_fin)s' % {
            'uf': uf,
            'ano': ano,
            'cnpj': cnpj,
            'modelo': '55' if modelo == 'nfe' else '65',  # 55=NF-e; 65=NFC-e;
            'serie': serie.zfill(3),
            'num_ini': str(numero_inicial).zfill(9),
            'num_fin': str(numero_final).zfill(9),
        }

        # Monta XML do corpo da requisição # FIXME
        raiz = etree.Element('inutNFe', versao=VERSAO_PADRAO, xmlns=NAMESPACE_NFE)
        inf_inut = etree.SubElement(raiz, 'infInut', Id=id_unico)
        etree.SubElement(inf_inut, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(inf_inut, 'xServ').text = 'INUTILIZAR'
        etree.SubElement(inf_inut, 'cUF').text = uf
        etree.SubElement(inf_inut, 'ano').text = ano
        etree.SubElement(inf_inut, 'CNPJ').text = cnpj
        etree.SubElement(inf_inut, 'mod').text = '55' if modelo == 'nfe' else '65'  # 55=NF-e; 65=NFC-e
        etree.SubElement(inf_inut, 'serie').text = serie
        etree.SubElement(inf_inut, 'nNFIni').text = str(numero_inicial)
        etree.SubElement(inf_inut, 'nNFFin').text = str(numero_final)
        etree.SubElement(inf_inut, 'xJust').text = justificativa

        # assinatura
        a1 = AssinaturaA1(self.certificado, self.certificado_senha)
        xml = a1.assinar(raiz)

        # Monta XML para envio da requisição
        xml = self._construir_xml_soap('NFeInutilizacao4', xml)
        # Faz request no Servidor da Sefaz e retorna resposta
        return self._post(url, xml)
Exemplo n.º 25
0
    def autorizacao(self, modelo, nota_fiscal, id_lote=1, ind_sinc=1):
        """
        Método para realizar autorização da nota de acordo com o modelo
        :param modelo: Modelo
        :param nota_fiscal: XML assinado
        :param id_lote: Id do lote - numero autoincremental gerado pelo sistema
        :param ind_sinc: Indicador de sincrono e assincrono, 0 para assincrono, 1 para sincrono
        :return:  Uma tupla que em caso de sucesso, retorna xml com nfe e protocolo de autorização. Caso contrário,
        envia todo o soap de resposta da Sefaz para decisão do usuário.
        """
        # url do serviço
        url = self._get_url(modelo=modelo, consulta='AUTORIZACAO')

        # Monta XML do corpo da requisição
        raiz = etree.Element('enviNFe', xmlns=NAMESPACE_NFE, versao=VERSAO_PADRAO)
        etree.SubElement(raiz, 'idLote').text = str(id_lote)  # numero autoincremental gerado pelo sistema
        etree.SubElement(raiz, 'indSinc').text = str(ind_sinc)  # 0 para assincrono, 1 para sincrono
        raiz.append(nota_fiscal)

        # Monta XML para envio da requisição
        xml = self._construir_xml_soap('NFeAutorizacao4', raiz)
        # Faz request no Servidor da Sefaz
        retorno = self._post(url, xml)

        # Em caso de sucesso, retorna xml com nfe e protocolo de autorização.
        # Caso contrário, envia todo o soap de resposta da Sefaz para decisão do usuário.
        if retorno.status_code == 200:
            # namespace
            ns = {'ns': NAMESPACE_NFE}
            # Procuta status no xml
            try:
                prot = etree.fromstring(retorno.text)
            except ValueError:
                # em SP retorno.text apresenta erro
                prot = etree.fromstring(retorno.content)
            if ind_sinc == 1:
                try:
                    # Protocolo com envio OK
                    try:
                        inf_prot = prot[0][0]  # root protNFe
                    except IndexError:
                        # Estados como GO vem com a tag header
                        inf_prot = prot[1][0]
                        
                    lote_status = inf_prot.xpath("ns:retEnviNFe/ns:cStat", namespaces=ns)[0].text
                    # Lote processado
                    if lote_status == '104':
                        prot_nfe = inf_prot.xpath("ns:retEnviNFe/ns:protNFe", namespaces=ns)[0]
                        status = prot_nfe.xpath('ns:infProt/ns:cStat', namespaces=ns)[0].text
                        # autorizado usa da NF-e 
                        # retorna xml final (protNFe+NFe)
                        if status == '100':
                            raiz = etree.Element('nfeProc', xmlns=NAMESPACE_NFE, versao=VERSAO_PADRAO)
                            raiz.append(nota_fiscal)
                            raiz.append(prot_nfe)
                            return 0, raiz
                except IndexError:
                    # Protocolo com algum erro no Envio
                    return 1, retorno, nota_fiscal
            else:
                # Retorna id do protocolo para posterior consulta em caso de sucesso.
                rec = prot[0][0]
                status = rec.xpath("ns:retEnviNFe/ns:cStat", namespaces=ns)[0].text
                # Lote Recebido com Sucesso!
                if status == '103':
                    nrec = rec.xpath("ns:retEnviNFe/ns:infRec/ns:nRec", namespaces=ns)[0].text
                    return 0, nrec, nota_fiscal
        return 1, retorno, nota_fiscal
Exemplo n.º 26
0
    def _serializar_evento(self,
                           evento,
                           tag_raiz='evento',
                           retorna_string=False):

        # timezone Brasília -03:00
        tz = time.strftime("%z")
        tz = "{}:{}".format(tz[:-2], tz[-2:])
        #import ipdb
        #ipdb.set_trace()
        raiz = etree.Element(tag_raiz, versao='1.00', xmlns=NAMESPACE_NFE)
        e = etree.SubElement(raiz, 'infEvento', Id=evento.identificador)
        etree.SubElement(e, 'cOrgao').text = CODIGOS_ESTADOS[evento.uf.upper()]
        etree.SubElement(e, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(
            e, 'CNPJ').text = evento.cnpj  # Empresas somente terão CNPJ
        #etree.SubElement(evento, 'CPF').text = ''
        etree.SubElement(e, 'chNFe').text = evento.chave
        etree.SubElement(
            e, 'dhEvento'
        ).text = evento.data_emissao.strftime('%Y-%m-%dT%H:%M:%S') + tz
        etree.SubElement(e, 'tpEvento').text = evento.tp_evento
        etree.SubElement(e, 'nSeqEvento').text = str(evento.n_seq_evento)
        etree.SubElement(e, 'verEvento').text = '1.00'
        det = etree.SubElement(e, 'detEvento', versao='1.00')
        etree.SubElement(det, 'descEvento').text = evento.descricao
        etree.SubElement(det, 'nProt').text = evento.protocolo
        etree.SubElement(det, 'xJust').text = evento.justificativa

        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemplo n.º 27
0
    def inutilizar_faixa_numeracao(self,
                                   numero_inicial,
                                   numero_final,
                                   emitente,
                                   certificado,
                                   senha,
                                   ano=None,
                                   serie='1',
                                   justificativa=''):
        post = '/nfeweb/services/nfestatusservico.asmx'
        metodo = 'NfeInutilizacao2'

        # Valores default
        ano = str(ano or datetime.date.today().year)[-2:]
        uf = CODIGOS_ESTADOS[emitente.endereco_uf]
        cnpj = so_numeros(emitente.cnpj)

        # Identificador da TAG a ser assinada formada com Código da UF + Ano (2 posições) +
        #  CNPJ + modelo + série + nro inicial e nro final precedida do literal “ID”
        id_unico = 'ID%(uf)s%(ano)s%(cnpj)s%(modelo)s%(serie)s%(num_ini)s%(num_fin)s' % {
            'uf': uf,
            'ano': ano,
            'cnpj': cnpj,
            'modelo': '55',
            'serie': serie.zfill(3),
            'num_ini': str(numero_inicial).zfill(9),
            'num_fin': str(numero_final).zfill(9),
        }

        # Monta XML do corpo da requisição # FIXME
        raiz = etree.Element('inutNFe',
                             xmlns="http://www.portalfiscal.inf.br/nfe",
                             versao="1.07")
        inf_inut = etree.SubElement(raiz, 'infInut', Id=id_unico)
        etree.SubElement(inf_inut, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(inf_inut, 'xServ').text = 'INUTILIZAR'
        etree.SubElement(inf_inut, 'cUF').text = uf
        etree.SubElement(inf_inut, 'ano').text = ano
        etree.SubElement(inf_inut, 'CNPJ').text = emitente.cnpj
        etree.SubElement(inf_inut, 'mod').text = '55'
        etree.SubElement(inf_inut, 'serie').text = serie
        etree.SubElement(inf_inut, 'nNFIni').text = str(numero_inicial)
        etree.SubElement(inf_inut, 'nNFFin').text = str(numero_final)
        etree.SubElement(inf_inut, 'xJust').text = justificativa
        #dados = etree.tostring(raiz, encoding='utf-8', xml_declaration=True)

        # Efetua assinatura
        assinatura = self._assinatura(certificado, senha)
        dados = assinatura.assinar_etree(etree.ElementTree(raiz),
                                         retorna_xml=True)

        # Monta XML para envio da requisição
        xml = self._construir_xml_soap(
            metodo='nfeRecepcao2',  # XXX
            tag_metodo='nfeInutilizacaoNF',  # XXX
            cabecalho=self._cabecalho_soap(),
            dados=dados,
        )

        # Chama método que efetua a requisição POST no servidor SOAP
        retorno = self._post(post, xml, self._post_header())

        # Transforma o retorno em etree # TODO
        #retorno = etree.parse(StringIO(retorno))

        return retorno
Exemplo n.º 28
0
    def _serializar_emitente(self,
                             emitente,
                             tag_raiz='emit',
                             retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados do emitente
        etree.SubElement(raiz, 'CNPJ').text = so_numeros(emitente.cnpj)
        etree.SubElement(raiz, 'xNome').text = emitente.razao_social
        etree.SubElement(raiz, 'xFant').text = emitente.nome_fantasia
        # Endereço
        endereco = etree.SubElement(raiz, 'enderEmit')
        etree.SubElement(endereco, 'xLgr').text = emitente.endereco_logradouro
        etree.SubElement(endereco, 'nro').text = emitente.endereco_numero
        if emitente.endereco_complemento:
            etree.SubElement(endereco,
                             'xCpl').text = emitente.endereco_complemento
        etree.SubElement(endereco, 'xBairro').text = emitente.endereco_bairro
        etree.SubElement(endereco, 'cMun').text = obter_codigo_por_municipio(
            emitente.endereco_municipio, emitente.endereco_uf)
        etree.SubElement(endereco, 'xMun').text = emitente.endereco_municipio
        etree.SubElement(endereco, 'UF').text = emitente.endereco_uf
        etree.SubElement(endereco,
                         'CEP').text = so_numeros(emitente.endereco_cep)
        etree.SubElement(endereco, 'cPais').text = emitente.endereco_pais
        etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(
            emitente.endereco_pais)
        if emitente.endereco_telefone:
            etree.SubElement(endereco,
                             'fone').text = emitente.endereco_telefone
        etree.SubElement(raiz, 'IE').text = emitente.inscricao_estadual
        # Apenas NF-e
        if emitente.inscricao_estadual_subst_tributaria:
            etree.SubElement(
                raiz,
                'IEST').text = emitente.inscricao_estadual_subst_tributaria
        # Inscricao Municipal
        if emitente.inscricao_municipal:
            etree.SubElement(raiz, 'IM').text = emitente.inscricao_municipal
            # Campo Opcional. Pode ser informado quando a Inscrição Municipal (id:C19) for informada.
            if emitente.cnae_fiscal:
                etree.SubElement(raiz, 'CNAE').text = emitente.cnae_fiscal
        etree.SubElement(raiz,
                         'CRT').text = emitente.codigo_de_regime_tributario
        if retorna_string:
            return etree.tostring(raiz, encoding="unicode", pretty_print=True)
        else:
            return raiz
Exemplo n.º 29
0
    def _serializar_notas_fiscal(self,
                                 nota_fiscal,
                                 tag_raiz='infNFe',
                                 retorna_string=True):
        raiz = etree.Element(tag_raiz, versao=self._versao)

        # Dados da Nota Fiscal
        ide = etree.SubElement(raiz, 'ide')
        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
        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
        etree.SubElement(ide, 'nNF').text = str(nota_fiscal.numero_nf)
        etree.SubElement(
            ide, 'dEmi').text = nota_fiscal.data_emissao.strftime('%Y-%m-%d')
        etree.SubElement(
            ide, 'dSaiEnt').text = nota_fiscal.data_saida_entrada.strftime(
                '%Y-%m-%d')
        etree.SubElement(ide, 'tpNF').text = str(nota_fiscal.tipo_documento)
        etree.SubElement(ide, 'cMunFG').text = nota_fiscal.municipio
        etree.SubElement(ide,
                         'tpImp').text = str(nota_fiscal.tipo_impressao_danfe)
        etree.SubElement(ide, 'tpEmis').text = str(nota_fiscal.forma_emissao)
        etree.SubElement(ide,
                         'cDV').text = nota_fiscal.dv_codigo_numerico_aleatorio
        etree.SubElement(ide, 'tpAmb').text = str(self._ambiente)
        etree.SubElement(ide,
                         'finNFe').text = str(nota_fiscal.finalidade_emissao)
        etree.SubElement(ide,
                         'procEmi').text = str(nota_fiscal.processo_emissao)
        etree.SubElement(
            ide,
            'verProc').text = '%s %s' % (self._nome_aplicacao,
                                         nota_fiscal.versao_processo_emissao)

        # Emitente
        raiz.append(
            self._serializar_emitente(nota_fiscal.emitente,
                                      retorna_string=False))

        # Destinatário
        raiz.append(
            self._serializar_cliente(nota_fiscal.cliente,
                                     retorna_string=False))

        # Retirada
        if nota_fiscal.retirada:
            raiz.append(
                self._serializar_entrega_retirada(
                    nota_fiscal.retirada,
                    retorna_string=False,
                    tag_raiz='retirada',
                ))

        # Entrega
        if nota_fiscal.entrega:
            raiz.append(
                self._serializar_entrega_retirada(
                    nota_fiscal.entrega,
                    retorna_string=False,
                    tag_raiz='entrega',
                ))

        # Itens
        for num, item in enumerate(nota_fiscal.produtos_e_servicos):
            det = self._serializar_produto_servico(item, retorna_string=False)
            det.attrib['nItem'] = str(num + 1)

            raiz.append(det)

        # Totais
        total = etree.SubElement(raiz, 'total')
        icms_total = etree.SubElement(total, 'ICMSTot')
        etree.SubElement(icms_total, 'vBC').text = str(
            nota_fiscal.totais_icms_base_calculo)
        etree.SubElement(icms_total,
                         'vICMS').text = str(nota_fiscal.totais_icms_total)
        etree.SubElement(icms_total, 'vBCST').text = str(
            nota_fiscal.totais_icms_st_base_calculo)
        etree.SubElement(icms_total,
                         'vST').text = str(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, 'vFrete').text = str(
            nota_fiscal.totais_icms_total_frete)
        etree.SubElement(icms_total, 'vSeg').text = str(
            nota_fiscal.totais_icms_total_seguro)
        etree.SubElement(icms_total, 'vDesc').text = str(
            nota_fiscal.totais_icms_total_desconto)
        etree.SubElement(icms_total,
                         'vII').text = str(nota_fiscal.totais_icms_total_ii)
        etree.SubElement(icms_total,
                         'vIPI').text = str(nota_fiscal.totais_icms_total_ipi)
        etree.SubElement(icms_total,
                         'vPIS').text = str(nota_fiscal.totais_icms_pis)
        etree.SubElement(icms_total,
                         'vCOFINS').text = str(nota_fiscal.totais_icms_cofins)
        etree.SubElement(icms_total, 'vOutro').text = str(
            nota_fiscal.totais_icms_outras_despesas_acessorias)
        etree.SubElement(icms_total,
                         'vNF').text = str(nota_fiscal.totais_icms_total_nota)

        # Transporte
        transp = etree.SubElement(raiz, 'transp')
        etree.SubElement(transp, 'modFrete').text = str(
            nota_fiscal.transporte_modalidade_frete)

        # Transportadora
        transp.append(
            self._serializar_transportadora(
                nota_fiscal.transporte_transportadora,
                retorna_string=False,
            ))

        # Veículo
        veiculo = etree.SubElement(transp, 'veicTransp')
        etree.SubElement(veiculo,
                         'placa').text = nota_fiscal.transporte_veiculo_placa
        etree.SubElement(veiculo,
                         'UF').text = nota_fiscal.transporte_veiculo_uf
        etree.SubElement(veiculo,
                         'RNTC').text = nota_fiscal.transporte_veiculo_rntc

        # Reboque
        reboque = etree.SubElement(transp, 'reboque')
        etree.SubElement(reboque,
                         'placa').text = nota_fiscal.transporte_reboque_placa
        etree.SubElement(reboque,
                         'UF').text = nota_fiscal.transporte_reboque_uf
        etree.SubElement(reboque,
                         'RNTC').text = nota_fiscal.transporte_reboque_rntc

        # Volumes
        for volume in nota_fiscal.transporte_volumes:
            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
            etree.SubElement(vol, 'pesoL').text = str(volume.peso_liquido)
            etree.SubElement(vol, 'pesoB').text = str(volume.peso_bruto)

            # Lacres
            lacres = etree.SubElement(vol, 'lacres')
            for lacre in volume.lacres:
                etree.SubElement(lacres, 'nLacre').text = lacre.numero_lacre

        # Informações adicionais
        info_ad = etree.SubElement(raiz, 'infAdic')
        etree.SubElement(
            info_ad, 'infAdFisco'
        ).text = nota_fiscal.informacoes_adicionais_interesse_fisco
        etree.SubElement(
            info_ad, 'infCpl'
        ).text = nota_fiscal.informacoes_complementares_interesse_contribuinte

        # 'Id' da tag raiz
        # Ex.: NFe35080599999090910270550010000000011518005123
        raiz.attrib['Id'] = nota_fiscal.identificador_unico

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz
Exemplo n.º 30
0
    def _serializar_emitente(self,
                             emitente,
                             tag_raiz='emit',
                             retorna_string=True):
        raiz = etree.Element(tag_raiz)

        # Dados do emitente
        etree.SubElement(raiz, 'CNPJ').text = so_numeros(emitente.cnpj)
        etree.SubElement(raiz, 'xNome').text = emitente.razao_social
        etree.SubElement(raiz, 'xFant').text = emitente.nome_fantasia
        etree.SubElement(raiz, 'IE').text = emitente.inscricao_estadual

        # Endereço
        endereco = etree.SubElement(raiz, 'enderEmit')
        etree.SubElement(endereco, 'xLgr').text = emitente.endereco_logradouro
        etree.SubElement(endereco, 'nro').text = emitente.endereco_numero
        etree.SubElement(endereco, 'xCpl').text = emitente.endereco_complemento
        etree.SubElement(endereco, 'xBairro').text = emitente.endereco_bairro
        etree.SubElement(endereco, 'cMun').text = emitente.endereco_municipio
        etree.SubElement(endereco, 'xMun').text = obter_municipio_por_codigo(
            emitente.endereco_municipio,
            emitente.endereco_uf,
        )
        etree.SubElement(endereco, 'UF').text = emitente.endereco_uf
        etree.SubElement(endereco,
                         'CEP').text = so_numeros(emitente.endereco_cep)
        etree.SubElement(endereco, 'cPais').text = emitente.endereco_pais
        etree.SubElement(endereco, 'xPais').text = obter_pais_por_codigo(
            emitente.endereco_pais)
        etree.SubElement(endereco, 'fone').text = emitente.endereco_telefone

        if retorna_string:
            return etree.tostring(raiz, pretty_print=True)
        else:
            return raiz