-
Notifications
You must be signed in to change notification settings - Fork 141
/
Copy pathutils.py
105 lines (86 loc) · 3.4 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# -*- coding: utf-8 -*-
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import re
from datetime import date, datetime
import lxml.etree as ET
class ChaveNFe(object):
def __init__(self, **kwargs):
self.cnpj = kwargs.pop("cnpj", "")
self.estado = kwargs.pop("estado", "")
self.emissao = kwargs.pop("emissao", "")
self.modelo = kwargs.pop("modelo", "")
self.serie = kwargs.pop("serie", "")
self.numero = kwargs.pop("numero", "")
self.tipo = kwargs.pop("tipo", "")
self.codigo = kwargs.pop("codigo", "")
def validar(self):
assert self.cnpj != "", "CNPJ necessário para criar chave NF-e"
assert self.estado != "", "Estado necessário para criar chave NF-e"
assert self.emissao != "", "Emissão necessário para criar chave NF-e"
assert self.modelo != "", "Modelo necessário para criar chave NF-e"
assert self.serie != "", "Série necessária para criar chave NF-e"
assert self.numero != "", "Número necessário para criar chave NF-e"
assert self.tipo != "", "Tipo necessário para criar chave NF-e"
assert self.codigo != "", "Código necessário para criar chave NF-e"
def date_tostring(data):
assert isinstance(data, date), "Objeto date requerido"
return data.strftime("%d-%m-%y")
def datetime_tostring(data):
assert isinstance(data, datetime), "Objeto datetime requerido"
return data.strftime("%d-%m-%y %H:%M:%S")
def gerar_chave(obj_chave, prefix=None):
assert isinstance(obj_chave, ChaveNFe), "Objeto deve ser do tipo ChaveNFe"
obj_chave.validar()
chave_parcial = "%s%s%s%s%s%s%d%s" % (
obj_chave.estado,
obj_chave.emissao,
obj_chave.cnpj,
obj_chave.modelo,
obj_chave.serie.zfill(3),
str(obj_chave.numero).zfill(9),
obj_chave.tipo,
obj_chave.codigo,
)
chave_parcial = re.sub("[^0-9]", "", chave_parcial)
soma = 0
contador = 2
for c in reversed(chave_parcial):
soma += int(c) * contador
contador += 1
if contador == 10:
contador = 2
dv = (11 - soma % 11) if (soma % 11 != 0 and soma % 11 != 1) else 0
if prefix:
return prefix + chave_parcial + str(dv)
return chave_parcial + str(dv)
def _find_node(xml, node):
for item in xml.iterchildren("*"):
if node in item.tag:
return item
else:
item = _find_node(item, node)
if item is not None:
return item
return None
def gerar_nfeproc(envio, recibo):
NSMAP = {None: "http://www.portalfiscal.inf.br/nfe"}
root = ET.Element("nfeProc", versao="4.00", nsmap=NSMAP)
parser = ET.XMLParser(encoding="utf-8")
docEnvio = ET.fromstring(envio.encode("utf-8"), parser=parser)
docRecibo = ET.fromstring(recibo.encode("utf-8"), parser=parser)
nfe = _find_node(docEnvio, "NFe")
protocolo = _find_node(docRecibo, "protNFe")
if nfe is None or protocolo is None:
return b""
root.append(nfe)
root.append(protocolo)
return ET.tostring(root)
def gerar_nfeproc_cancel(nfe_proc, cancelamento):
docEnvio = ET.fromstring(nfe_proc)
docCancel = ET.fromstring(cancelamento)
ev_cancelamento = _find_node(docCancel, "retEvento")
if ev_cancelamento is None:
return b""
docEnvio.append(ev_cancelamento)
return ET.tostring(docEnvio)