|
1 |
| -# Copyright (C) 2023 KMEE Informatica LTDA |
2 |
| -# License AGPL-3 or later (http://www.gnu.org/licenses/agpl) |
| 1 | +from odoo import fields, models |
3 | 2 |
|
4 |
| -import logging |
5 |
| -import re |
6 |
| - |
7 |
| -from erpbrasil.transmissao import TransmissaoSOAP |
8 |
| -from nfelib.nfe.ws.edoc_legacy import NFeAdapter as edoc_nfe |
9 |
| -from requests import Session |
10 |
| - |
11 |
| -from odoo import _, api, fields, models |
12 |
| - |
13 |
| -from ..tools import utils |
14 |
| - |
15 |
| -_logger = logging.getLogger(__name__) |
| 3 | +from ..constants.dfe import ( |
| 4 | + OPERATION_TYPE, |
| 5 | + SITUACAO_NFE, |
| 6 | +) |
16 | 7 |
|
17 | 8 |
|
18 | 9 | class DFe(models.Model):
|
19 | 10 | _name = "l10n_br_fiscal.dfe"
|
20 | 11 | _inherit = ["mail.thread", "mail.activity.mixin"]
|
21 | 12 | _description = "Consult DF-e"
|
22 |
| - _order = "id desc" |
23 |
| - _rec_name = "display_name" |
24 | 13 |
|
25 |
| - display_name = fields.Char(compute="_compute_display_name") |
| 14 | + key = fields.Char(string="Access Key", size=44) |
| 15 | + |
| 16 | + serie = fields.Char(size=3, index=True) |
26 | 17 |
|
27 |
| - company_id = fields.Many2one(comodel_name="res.company", string="Company") |
| 18 | + number = fields.Float(string="Document Number", index=True, digits=(18, 0)) |
28 | 19 |
|
29 |
| - version = fields.Selection(related="company_id.dfe_version") |
| 20 | + emitter = fields.Char(size=60) |
30 | 21 |
|
31 |
| - environment = fields.Selection(related="company_id.dfe_environment") |
| 22 | + cnpj_cpf = fields.Char(string="CNPJ/CPF", size=18) |
32 | 23 |
|
33 |
| - last_nsu = fields.Char(string="Last NSU", size=25, default="0") |
| 24 | + nsu = fields.Char(string="NSU", size=25, index=True) |
34 | 25 |
|
35 |
| - last_query = fields.Datetime(string="Last query") |
| 26 | + operation_type = fields.Selection( |
| 27 | + selection=OPERATION_TYPE, |
| 28 | + ) |
| 29 | + |
| 30 | + document_value = fields.Float( |
| 31 | + string="Document Total Value", |
| 32 | + readonly=True, |
| 33 | + digits=(18, 2), |
| 34 | + ) |
| 35 | + |
| 36 | + ie = fields.Char(string="Inscrição estadual", size=18) |
| 37 | + |
| 38 | + partner_id = fields.Many2one( |
| 39 | + comodel_name="res.partner", |
| 40 | + string="Supplier (partner)", |
| 41 | + ) |
36 | 42 |
|
37 |
| - imported_document_ids = fields.One2many( |
38 |
| - comodel_name="l10n_br_fiscal.document", |
39 |
| - inverse_name="dfe_id", |
40 |
| - string="Imported Documents", |
| 43 | + company_id = fields.Many2one( |
| 44 | + comodel_name="res.company", |
| 45 | + string="Company", |
| 46 | + default=lambda self: self.env.company, |
| 47 | + readonly=True, |
41 | 48 | )
|
42 | 49 |
|
43 |
| - use_cron = fields.Boolean( |
44 |
| - default=False, |
45 |
| - string="Download new documents automatically", |
46 |
| - help="If activated, allows new manifestations to be automatically " |
47 |
| - "searched with a Cron", |
| 50 | + emission_datetime = fields.Datetime( |
| 51 | + string="Emission Date", |
| 52 | + index=True, |
| 53 | + default=fields.Datetime.now, |
48 | 54 | )
|
49 | 55 |
|
50 |
| - @api.depends("company_id.name", "last_nsu") |
51 |
| - def name_get(self): |
52 |
| - return self.mapped(lambda d: (d.id, f"{d.company_id.name} - NSU: {d.last_nsu}")) |
53 |
| - |
54 |
| - @api.model |
55 |
| - def _get_processor(self): |
56 |
| - certificado = self.env.company._get_br_ecertificate() |
57 |
| - session = Session() |
58 |
| - session.verify = False |
59 |
| - return edoc_nfe( |
60 |
| - TransmissaoSOAP(certificado, session), |
61 |
| - self.company_id.state_id.ibge_code, |
62 |
| - versao=self.version, |
63 |
| - ambiente=self.environment, |
64 |
| - ) |
65 |
| - |
66 |
| - @api.model |
67 |
| - def validate_distribution_response(self, result): |
68 |
| - valid = False |
69 |
| - message = result.resposta.xMotivo |
70 |
| - if result.retorno.status_code != 200: |
71 |
| - code = result.retorno.status_code |
72 |
| - elif result.resposta.cStat != "138": |
73 |
| - code = result.resposta.cStat |
74 |
| - else: |
75 |
| - valid = True |
76 |
| - |
77 |
| - if not valid: |
78 |
| - self.message_post( |
79 |
| - body=_( |
80 |
| - _( |
81 |
| - "Error validating document distribution:" |
82 |
| - "\n\n%(code)s - %(message)s", |
83 |
| - code=code, |
84 |
| - message=message, |
85 |
| - ) |
86 |
| - ) |
87 |
| - ) |
88 |
| - |
89 |
| - return valid |
90 |
| - |
91 |
| - @api.model |
92 |
| - def _document_distribution(self): |
93 |
| - maxNSU = "" |
94 |
| - while maxNSU != self.last_nsu: |
95 |
| - try: |
96 |
| - result = self._get_processor().consultar_distribuicao( |
97 |
| - cnpj_cpf=re.sub("[^0-9]", "", self.company_id.cnpj_cpf), |
98 |
| - ultimo_nsu=utils.format_nsu(self.last_nsu), |
99 |
| - ) |
100 |
| - except Exception as e: |
101 |
| - self.message_post( |
102 |
| - body=_("Error on searching documents.\n%(error)s", error=e) |
103 |
| - ) |
104 |
| - break |
105 |
| - |
106 |
| - self.write( |
107 |
| - { |
108 |
| - "last_nsu": result.resposta.ultNSU, |
109 |
| - "last_query": fields.Datetime.now(), |
110 |
| - } |
111 |
| - ) |
112 |
| - |
113 |
| - if not self.validate_distribution_response(result): |
114 |
| - break |
115 |
| - |
116 |
| - self._process_distribution(result) |
117 |
| - |
118 |
| - maxNSU = result.resposta.maxNSU |
119 |
| - |
120 |
| - @api.model |
121 |
| - def _process_distribution(self, result): |
122 |
| - """Method to process the distribution data.""" |
123 |
| - |
124 |
| - @api.model |
125 |
| - def _parse_xml_document(self, document): |
126 |
| - schema_type = document.schema.split("_")[0] |
127 |
| - method = "parse_%s" % schema_type |
128 |
| - if not hasattr(self, method): |
129 |
| - return |
130 |
| - |
131 |
| - xml = utils.parse_gzip_xml(document.valueOf_) |
132 |
| - return getattr(self, method)(xml) |
133 |
| - |
134 |
| - @api.model |
135 |
| - def _download_document(self, nfe_key): |
136 |
| - try: |
137 |
| - result = self._get_processor().consultar_distribuicao( |
138 |
| - chave=nfe_key, cnpj_cpf=re.sub("[^0-9]", "", self.company_id.cnpj_cpf) |
139 |
| - ) |
140 |
| - except Exception as e: |
141 |
| - self.message_post( |
142 |
| - body=_("Error on searching documents.\n%(error)s", error=e) |
143 |
| - ) |
144 |
| - return |
145 |
| - |
146 |
| - if not self.validate_distribution_response(result): |
147 |
| - return |
148 |
| - |
149 |
| - return result.resposta.loteDistDFeInt.docZip[0] |
150 |
| - |
151 |
| - @api.model |
152 |
| - def _cron_search_documents(self): |
153 |
| - self.search([("use_cron", "=", True)]).search_documents() |
154 |
| - |
155 |
| - def search_documents(self): |
156 |
| - for record in self: |
157 |
| - record._document_distribution() |
| 56 | + inclusion_datetime = fields.Datetime( |
| 57 | + string="Inclusion Date", |
| 58 | + index=True, |
| 59 | + default=fields.Datetime.now, |
| 60 | + ) |
| 61 | + |
| 62 | + inclusion_mode = fields.Char(size=255) |
| 63 | + |
| 64 | + document_state = fields.Selection( |
| 65 | + selection=SITUACAO_NFE, |
| 66 | + index=True, |
| 67 | + ) |
| 68 | + |
| 69 | + cfop_ids = fields.Many2many( |
| 70 | + comodel_name="l10n_br_fiscal.cfop", |
| 71 | + string="CFOPs", |
| 72 | + ) |
| 73 | + |
| 74 | + dfe_nfe_document_type = fields.Selection( |
| 75 | + selection=[ |
| 76 | + ("dfe_nfe_complete", "NF-e Completa"), |
| 77 | + ("dfe_nfe_summary", "Resumo da NF-e"), |
| 78 | + ("dfe_nfe_event", "Evento da NF-e"), |
| 79 | + ], |
| 80 | + string="DFe Document Type", |
| 81 | + ) |
| 82 | + |
| 83 | + dfe_monitor_id = fields.Many2one( |
| 84 | + comodel_name="l10n_br_fiscal.dfe_monitor", |
| 85 | + string="DFe Monitor", |
| 86 | + ) |
0 commit comments