nfelib - bindings Python para e ler e gerir XML de NF-e, NFS-e nacional, CT-e, MDF-e, BP-e
===
<p align="center">
<a href="https://akretion.com/pt-BR" >
<img src="https://raw.githubusercontent.com/akretion/nfelib/master/ext/nfelib.jpg"/>
</a>
</p>
<p align="center">
<a href="https://codecov.io/gh/akretion/nfelib" >
<img src="https://codecov.io/gh/akretion/nfelib/branch/master/graph/badge.svg?token=IqcCHJzhuw"/>
</a>
<a href="https://pypi.org/project/nfelib/"><img alt="PyPI" src="https://img.shields.io/pypi/v/nfelib"></a>
<a href="https://pepy.tech/project/nfelib"><img alt="Downloads" src="https://pepy.tech/badge/nfelib"></a>
</p>
## Porque escolher a nfelib
* **Simples e confiável**. As outras bibliotecas costumam ter dezenas de milhares de linhas de código feito tudo manualmente para fazer o que o nfelib faz tudo automaticamente com algumas linhas para gerir código com o [xsdata](https://xsdata.readthedocs.io/) a partir dos últimos pacotes xsd da Fazenda. O xsdata é uma biblioteca de databinding extremamente bem escrita e bem testada. A própria nfelib tem testes para ler e gerir todos documentos fiscais.
* **Completa**: já que gerir os bindings ficou trivial, a nfelib mantém atualizada todos os bindings para interagir com todos os serviços e eventos de NF-e, NFS-e nacional, CT-e, MDF-e, BP-e. Os testes detetam também quando sai uma nova versão de algum esquema.
## Instalação
```bash
pip install nfelib
```
## Como usar
**NF-e**
```python
>>> # Ler o XML de uma NF-e:
>>> from nfelib.nfe.bindings.v4_0.proc_nfe_v4_00 import NfeProc
>>> nfe_proc = NfeProc.from_path("nfelib/nfe/samples/v4_0/leiauteNFe/NFe35200159594315000157550010000000012062777161.xml")
>>> # (pode ser usado também o metodo from_xml(xml) )
>>>
>>> nfe_proc.NFe.infNFe.emit.CNPJ
'59594315000157'
>>> nfe_proc.NFe.infNFe.emit
Tnfe.InfNfe.Emit(CNPJ='59594315000157', CPF=None, xNome='Akretion LTDA', xFant='Akretion', enderEmit=TenderEmi(xLgr='Rua Paulo Dias', nro='586', xCpl=None, xBairro=None, cMun='3501152', xMun='Alumínio', UF=<TufEmi.SP: 'SP'>, CEP='18125000', cPais=<TenderEmiCPais.VALUE_1058: '1058'>, xPais=<TenderEmiXPais.BRASIL: 'Brasil'>, fone='2130109965'), IE='755338250133', IEST=None, IM=None, CNAE=None, CRT=<EmitCrt.VALUE_1: '1'>)
>>> nfe_proc.NFe.infNFe.emit.enderEmit.UF.value
'SP'
>>>
>>> # Serializar uma NF-e:
>>> nfe_proc.to_xml()
'<?xml version="1.0" encoding="UTF-8"?>\n<nfeProc xmlns="http://www.portalfiscal.inf.br/nfe" versao="4.00">\n <NFe>\n <infNFe versao="4.00" Id="35200159594315000157550010000000012062777161">\n <ide>\n <cUF>35</cUF>\n <cNF>06277716</cNF>\n <natOp>Venda</natOp>\n <mod>55</mod>\n <serie>1</serie>\n <nNF>1</nNF>\n <dhEmi>2020-01-01T12:00:00+01:00</dhEmi>\n <dhSaiEnt>2020-01-01T12:00:00+01:00</dhSaiEnt>\n <tpNF>1</tpNF>\n <idDest>1</idDest>\n [...]
>>>
>>> # Montar uma NFe do zero:
>>> from nfelib.nfe.bindings.v4_0.nfe_v4_00 import Nfe
>>> nfe=Nfe(infNFe=Nfe.InfNfe(emit=Nfe.InfNfe.Emit(xNome="Minha Empresa", CNPJ='59594315000157')))
>>> nfe
Nfe(infNFe=Tnfe.InfNfe(ide=None, emit=Tnfe.InfNfe.Emit(CNPJ='59594315000157', CPF=None, xNome='Minha Empresa', xFant=None, enderEmit=None, IE=None, IEST=None, IM=None, CNAE=None, CRT=None), avulsa=None, dest=None, retirada=None, entrega=None, autXML=[], det=[], total=None, transp=None, cobr=None, pag=None, infIntermed=None, infAdic=None, exporta=None, compra=None, cana=None, infRespTec=None, infSolicNFF=None, versao=None, Id=None), infNFeSupl=None, signature=None)
>>>
>>> # Validar o XML de uma nota:
>>> nfe.validate_xml()
["Element '{http://www.portalfiscal.inf.br/nfe}infNFe': The attribute 'versao' is required but missing.", "Element '{http://www.portalfiscal.inf.br/nfe}infNFe': The attribute 'Id' is required but missing." [...]
```
Assinar o XML de uma nota usando a lib [erpbrasil.assinatura](https://github.com/erpbrasil/erpbrasil.assinatura) (funciona com os outros documentos eletrônicos também)
```
>>> # Assinar o XML de uma nota:
>>> with open(path_to_your_pkcs12_certificate, "rb") as pkcs12_buffer:
pkcs12_data = pkcs12_buffer.read()
>>> signed_xml = nfe.sign_xml(xml, pkcs12_data, cert_password, nfe.NFe.infNFe.Id)
```
Imprimir o DANFE usando a lib [BrazilFiscalReport](https://github.com/Engenere/BrazilFiscalReport) ou a lib [erpbrasil.edoc.pdf](https://github.com/erpbrasil/erpbrasil.edoc.pdf) (futuramente BrazilFiscalReport deve imprimir o pdf de outros documentos eletrônicos também; erpbrasil.edoc.pdf é uma lib mais 'legacy')
```
>>> # Imprimir o pdf de uma nota usando BrazilFiscalReport:
>>> pdf_bytes = nfe.to_pdf()
>>> # Imprimir o pdf de uma nota usando erpbrasil.edoc.pdf:
>>> pdf_bytes = nfe.to_pdf(engine="erpbrasil.edoc.pdf")
>>> # Ou então para imprimir e assinar junto:
>>> pdf_bytes = nfe.to_pdf(
pkcs12_data=cert_data,
pkcs12_password=cert_password,
doc_id=nfe.NFe.infNFe.Id,
)
```
**NFS-e padrão nacional**
```python
>>> # Ler uma NFS-e:
>>>> from nfelib.nfse.bindings.v1_0.nfse_v1_00 import Nfse
>>> nfse = Nfse.from_path("alguma_nfse.xml")
>>>
>>> # Serializar uma NFS-e:
>>> nfse.to_xml()
>>> # Ler uma DPS:
>>>> from nfelib.nfse.bindings.v1_0.dps_v1_00 import Dps
>>> dps = Nfse.from_path("nfelib/nfse/samples/v1_0/GerarNFSeEnvio-env-loterps.xml")
>>>
>>> # Serializar uma DPS:
>>> dps.to_xml()
```
**MDF-e**
```python
>>> # Ler um MDF-e:
>>>> from nfelib.mdfe.bindings.v3_0.mdfe_v3_00 import Mdfe
>>> mdfe = Mdfe.from_path("nfelib/mdfe/samples/v3_0/ComPagtoPIX_41210780568835000181580010402005751006005791-procMDFe.xml")
>>>
>>> # Serializar um MDF-e:
>>> mdfe.to_xml()
```
**CT-e**
```python
>>> # Ler um CT-e:
>>>> from nfelib.cte.bindings.v4_0.cte_v4_00 import Cte
>>> cte = Cte.from_path("nfelib/cte/samples/v4_0/43120178408960000182570010000000041000000047-cte.xml")
>>>
>>> # Serializar um CT-e:
>>> cte.to_xml()
```
**BP-e**
```python
>>> # Ler um BP-e:
>>>> from nfelib.bpe.bindings.v1_0.bpe_v1_00 import Bpe
>>> bpe = Bpe.from_path("algum_bpe.xml")
>>>
>>> # Serializar um BP-e:
>>> bpe.to_xml()
```
## Desenvolvimento / testes
Para rodar os testes:
```bash
pytest
```
Para atualizar os bindings:
1. baixar o novo zip dos esquemas e atualizar a pasta ```nfelib/<nfe|nfse|cte|mdfe|bpe>/schemas/<versao>/```
2. gerir os bindings de um pacote de esquemas xsd, por examplo da NF-e:
```bash
xsdata generate nfelib/nfe/schemas/v4_0 --package nfelib.nfe.bindings.v4_0
```
Para gerir todos bindings com xsdata:
```bash
./script.sh
```
## Versões dos esquemas e pastas
A nfelib usa apenas 2 dígitos para caracterizar a versão. Isso foi decidido observando que a Fazenda nunca usa o terceiro dígito da versão e que a mudança do segundo dígito já caracteriza uma mudança maior. Nisso qualquer alteração de esquema que não mudar o primeiro nem o segundo dígito da versão do esquema vai na mesma pasta e se sobreponha a antiga versão, assumindo que é possível usar o mais novo esquema no lugar do antigo (por exemplo é possível ler uma NFe 4.00 pacote nº 9j (NT 2022.003 v.1.00b) com os bindings da versão nfe pacote nº 9k (NT 2023.001 v.1.20).
Pelo contrário, caso houver uma mudança maior afetando os 2 primeiros dígitos como NFe 3.0 e NFe 3.1 ou NFe 3.1 e NFe 4.0, será possível também suportar as várias versões ao mesmo tempo usando pastas diferentes. Assim seria possível por exemplo emitir a futura NFe 5.0 e ainda importar uma NFe 4.0.
Raw data
{
"_id": null,
"home_page": "https://github.com/akretion/nfelib",
"name": "nfelib",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "e-invoicing, ERP, Odoo, NFe, CTe, MDFe, BPe, NFSe",
"author": "Rapha\u00ebl Valyi",
"author_email": "Rapha\u00ebl Valyi <raphael.valyi@akretion.com.br>",
"download_url": "https://files.pythonhosted.org/packages/21/62/cdb783b3e38b5113a352cc2a9c71f49cb9da91bc962b56b4021786df4136/nfelib-2.1.1.tar.gz",
"platform": null,
"description": "nfelib - bindings Python para e ler e gerir XML de NF-e, NFS-e nacional, CT-e, MDF-e, BP-e\n===\n<p align=\"center\">\n<a href=\"https://akretion.com/pt-BR\" > \n <img src=\"https://raw.githubusercontent.com/akretion/nfelib/master/ext/nfelib.jpg\"/>\n</a>\n</p>\n\n<p align=\"center\">\n<a href=\"https://codecov.io/gh/akretion/nfelib\" > \n <img src=\"https://codecov.io/gh/akretion/nfelib/branch/master/graph/badge.svg?token=IqcCHJzhuw\"/>\n</a>\n<a href=\"https://pypi.org/project/nfelib/\"><img alt=\"PyPI\" src=\"https://img.shields.io/pypi/v/nfelib\"></a>\n<a href=\"https://pepy.tech/project/nfelib\"><img alt=\"Downloads\" src=\"https://pepy.tech/badge/nfelib\"></a>\n</p>\n\n\n## Porque escolher a nfelib\n\n* **Simples e confi\u00e1vel**. As outras bibliotecas costumam ter dezenas de milhares de linhas de c\u00f3digo feito tudo manualmente para fazer o que o nfelib faz tudo automaticamente com algumas linhas para gerir c\u00f3digo com o\u00a0[xsdata](https://xsdata.readthedocs.io/)\u00a0a partir dos \u00faltimos pacotes xsd da Fazenda. O xsdata \u00e9 uma biblioteca de databinding extremamente bem escrita e bem testada. A pr\u00f3pria nfelib tem testes para ler e gerir todos documentos fiscais.\n* **Completa**: j\u00e1 que gerir os bindings ficou trivial, a nfelib mant\u00e9m atualizada todos os bindings para interagir com todos os servi\u00e7os e eventos de NF-e, NFS-e nacional, CT-e, MDF-e, BP-e. Os testes detetam tamb\u00e9m quando sai uma nova vers\u00e3o de algum esquema.\n\n\n## Instala\u00e7\u00e3o\n\n```bash\npip install nfelib\n```\n\n## Como usar\n\n**NF-e**\n```python\n>>> # Ler o XML de uma NF-e:\n>>> from nfelib.nfe.bindings.v4_0.proc_nfe_v4_00 import NfeProc\n>>> nfe_proc = NfeProc.from_path(\"nfelib/nfe/samples/v4_0/leiauteNFe/NFe35200159594315000157550010000000012062777161.xml\")\n>>> # (pode ser usado tamb\u00e9m o metodo from_xml(xml) )\n>>>\n>>> nfe_proc.NFe.infNFe.emit.CNPJ\n'59594315000157'\n>>> nfe_proc.NFe.infNFe.emit\nTnfe.InfNfe.Emit(CNPJ='59594315000157', CPF=None, xNome='Akretion LTDA', xFant='Akretion', enderEmit=TenderEmi(xLgr='Rua Paulo Dias', nro='586', xCpl=None, xBairro=None, cMun='3501152', xMun='Alum\u00ednio', UF=<TufEmi.SP: 'SP'>, CEP='18125000', cPais=<TenderEmiCPais.VALUE_1058: '1058'>, xPais=<TenderEmiXPais.BRASIL: 'Brasil'>, fone='2130109965'), IE='755338250133', IEST=None, IM=None, CNAE=None, CRT=<EmitCrt.VALUE_1: '1'>)\n>>> nfe_proc.NFe.infNFe.emit.enderEmit.UF.value\n'SP'\n>>>\n>>> # Serializar uma NF-e:\n>>> nfe_proc.to_xml()\n'<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<nfeProc xmlns=\"http://www.portalfiscal.inf.br/nfe\" versao=\"4.00\">\\n <NFe>\\n <infNFe versao=\"4.00\" Id=\"35200159594315000157550010000000012062777161\">\\n <ide>\\n <cUF>35</cUF>\\n <cNF>06277716</cNF>\\n <natOp>Venda</natOp>\\n <mod>55</mod>\\n <serie>1</serie>\\n <nNF>1</nNF>\\n <dhEmi>2020-01-01T12:00:00+01:00</dhEmi>\\n <dhSaiEnt>2020-01-01T12:00:00+01:00</dhSaiEnt>\\n <tpNF>1</tpNF>\\n <idDest>1</idDest>\\n [...]\n>>>\n>>> # Montar uma NFe do zero:\n>>> from nfelib.nfe.bindings.v4_0.nfe_v4_00 import Nfe\n>>> nfe=Nfe(infNFe=Nfe.InfNfe(emit=Nfe.InfNfe.Emit(xNome=\"Minha Empresa\", CNPJ='59594315000157')))\n>>> nfe\nNfe(infNFe=Tnfe.InfNfe(ide=None, emit=Tnfe.InfNfe.Emit(CNPJ='59594315000157', CPF=None, xNome='Minha Empresa', xFant=None, enderEmit=None, IE=None, IEST=None, IM=None, CNAE=None, CRT=None), avulsa=None, dest=None, retirada=None, entrega=None, autXML=[], det=[], total=None, transp=None, cobr=None, pag=None, infIntermed=None, infAdic=None, exporta=None, compra=None, cana=None, infRespTec=None, infSolicNFF=None, versao=None, Id=None), infNFeSupl=None, signature=None)\n>>> \n>>> # Validar o XML de uma nota:\n>>> nfe.validate_xml()\n[\"Element '{http://www.portalfiscal.inf.br/nfe}infNFe': The attribute 'versao' is required but missing.\", \"Element '{http://www.portalfiscal.inf.br/nfe}infNFe': The attribute 'Id' is required but missing.\" [...]\n```\n\nAssinar o XML de uma nota usando a lib [erpbrasil.assinatura](https://github.com/erpbrasil/erpbrasil.assinatura) (funciona com os outros documentos eletr\u00f4nicos tamb\u00e9m)\n```\n>>> # Assinar o XML de uma nota:\n>>> with open(path_to_your_pkcs12_certificate, \"rb\") as pkcs12_buffer:\n pkcs12_data = pkcs12_buffer.read()\n>>> signed_xml = nfe.sign_xml(xml, pkcs12_data, cert_password, nfe.NFe.infNFe.Id)\n```\n\nImprimir o DANFE usando a lib [BrazilFiscalReport](https://github.com/Engenere/BrazilFiscalReport) ou a lib [erpbrasil.edoc.pdf](https://github.com/erpbrasil/erpbrasil.edoc.pdf) (futuramente BrazilFiscalReport deve imprimir o pdf de outros documentos eletr\u00f4nicos tamb\u00e9m; erpbrasil.edoc.pdf \u00e9 uma lib mais 'legacy')\n```\n>>> # Imprimir o pdf de uma nota usando BrazilFiscalReport:\n>>> pdf_bytes = nfe.to_pdf()\n>>> # Imprimir o pdf de uma nota usando erpbrasil.edoc.pdf:\n>>> pdf_bytes = nfe.to_pdf(engine=\"erpbrasil.edoc.pdf\")\n>>> # Ou ent\u00e3o para imprimir e assinar junto:\n>>> pdf_bytes = nfe.to_pdf(\n pkcs12_data=cert_data,\n pkcs12_password=cert_password,\n doc_id=nfe.NFe.infNFe.Id,\n )\n```\n\n**NFS-e padr\u00e3o nacional**\n```python\n>>> # Ler uma NFS-e:\n>>>> from nfelib.nfse.bindings.v1_0.nfse_v1_00 import Nfse\n>>> nfse = Nfse.from_path(\"alguma_nfse.xml\")\n>>>\n>>> # Serializar uma NFS-e:\n>>> nfse.to_xml()\n>>> # Ler uma DPS:\n>>>> from nfelib.nfse.bindings.v1_0.dps_v1_00 import Dps\n>>> dps = Nfse.from_path(\"nfelib/nfse/samples/v1_0/GerarNFSeEnvio-env-loterps.xml\")\n>>>\n>>> # Serializar uma DPS:\n>>> dps.to_xml()\n```\n\n**MDF-e**\n```python\n>>> # Ler um MDF-e:\n>>>> from nfelib.mdfe.bindings.v3_0.mdfe_v3_00 import Mdfe\n>>> mdfe = Mdfe.from_path(\"nfelib/mdfe/samples/v3_0/ComPagtoPIX_41210780568835000181580010402005751006005791-procMDFe.xml\")\n>>>\n>>> # Serializar um MDF-e:\n>>> mdfe.to_xml()\n```\n\n**CT-e**\n```python\n>>> # Ler um CT-e:\n>>>> from nfelib.cte.bindings.v4_0.cte_v4_00 import Cte\n>>> cte = Cte.from_path(\"nfelib/cte/samples/v4_0/43120178408960000182570010000000041000000047-cte.xml\")\n>>>\n>>> # Serializar um CT-e:\n>>> cte.to_xml()\n```\n\n**BP-e**\n```python\n>>> # Ler um BP-e:\n>>>> from nfelib.bpe.bindings.v1_0.bpe_v1_00 import Bpe\n>>> bpe = Bpe.from_path(\"algum_bpe.xml\")\n>>>\n>>> # Serializar um BP-e:\n>>> bpe.to_xml()\n```\n\n\n## Desenvolvimento / testes\n\nPara rodar os testes:\n\n```bash\npytest\n```\n\nPara atualizar os bindings:\n\n1. baixar o novo zip dos esquemas e atualizar a pasta ```nfelib/<nfe|nfse|cte|mdfe|bpe>/schemas/<versao>/```\n2. gerir os bindings de um pacote de esquemas xsd, por examplo da NF-e:\n\n ```bash\n xsdata generate nfelib/nfe/schemas/v4_0 --package nfelib.nfe.bindings.v4_0\n ```\n\nPara gerir todos bindings com xsdata:\n\n```bash\n./script.sh\n```\n\n## Vers\u00f5es dos esquemas e pastas\n\nA nfelib usa apenas 2 d\u00edgitos para caracterizar a vers\u00e3o. Isso foi decidido observando que a Fazenda nunca usa o terceiro d\u00edgito da vers\u00e3o e que a mudan\u00e7a do segundo d\u00edgito j\u00e1 caracteriza uma mudan\u00e7a maior. Nisso qualquer altera\u00e7\u00e3o de esquema que n\u00e3o mudar o primeiro nem o segundo d\u00edgito da vers\u00e3o do esquema vai na mesma pasta e se sobreponha a antiga vers\u00e3o, assumindo que \u00e9 poss\u00edvel usar o mais novo esquema no lugar do antigo (por exemplo \u00e9 poss\u00edvel ler uma NFe 4.00 pacote n\u00ba 9j (NT 2022.003 v.1.00b) com os bindings da vers\u00e3o nfe pacote n\u00ba 9k (NT 2023.001 v.1.20).\n\nPelo contr\u00e1rio, caso houver uma mudan\u00e7a maior afetando os 2 primeiros d\u00edgitos como NFe 3.0 e NFe 3.1 ou NFe 3.1 e NFe 4.0, ser\u00e1 poss\u00edvel tamb\u00e9m suportar as v\u00e1rias vers\u00f5es ao mesmo tempo usando pastas diferentes. Assim seria poss\u00edvel por exemplo emitir a futura NFe 5.0 e ainda importar uma NFe 4.0.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "nfelib: electronic invoicing library for Brazil",
"version": "2.1.1",
"project_urls": {
"Changelog": "https://nfelib.readthedocs.io/en/latest/changelog/",
"Documentation": "https://nfelib.readthedocs.io/",
"Homepage": "https://github.com/akretion/nfelib",
"Source": "https://github.com/akretion/nfelib"
},
"split_keywords": [
"e-invoicing",
" erp",
" odoo",
" nfe",
" cte",
" mdfe",
" bpe",
" nfse"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "11cee21077bdceecf41bdb75118af7d876130b14e375f5f8af8a8d0b46193f2f",
"md5": "1022102d8072704d2f692ff3e0b41f84",
"sha256": "4f0fe023a0242118ca876e686a8223addd923df6cf397f643437de714fc49d04"
},
"downloads": -1,
"filename": "nfelib-2.1.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "1022102d8072704d2f692ff3e0b41f84",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 845553,
"upload_time": "2024-06-29T23:46:14",
"upload_time_iso_8601": "2024-06-29T23:46:14.439050Z",
"url": "https://files.pythonhosted.org/packages/11/ce/e21077bdceecf41bdb75118af7d876130b14e375f5f8af8a8d0b46193f2f/nfelib-2.1.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2162cdb783b3e38b5113a352cc2a9c71f49cb9da91bc962b56b4021786df4136",
"md5": "c8d7f241db5a1ab08e48dc5f2857ad99",
"sha256": "053c21629f229aa3f36c7479a0b47e7a41bb921c783d55e05fc4054d1367df15"
},
"downloads": -1,
"filename": "nfelib-2.1.1.tar.gz",
"has_sig": false,
"md5_digest": "c8d7f241db5a1ab08e48dc5f2857ad99",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 540469,
"upload_time": "2024-06-29T23:46:16",
"upload_time_iso_8601": "2024-06-29T23:46:16.557083Z",
"url": "https://files.pythonhosted.org/packages/21/62/cdb783b3e38b5113a352cc2a9c71f49cb9da91bc962b56b4021786df4136/nfelib-2.1.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-29 23:46:16",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "akretion",
"github_project": "nfelib",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "nfelib"
}