odoo-addon-l10n-br-fiscal 16.0.1.18.2.1__py3-none-any.whl → 16.0.2.0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of odoo-addon-l10n-br-fiscal might be problematic. Click here for more details.

Files changed (42) hide show
  1. odoo/addons/l10n_br_fiscal/README.rst +1 -1
  2. odoo/addons/l10n_br_fiscal/__manifest__.py +2 -12
  3. odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +72 -820
  4. odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +72 -0
  5. odoo/addons/l10n_br_fiscal/migrations/16.0.2.0.0/pre-migration.py +25 -0
  6. odoo/addons/l10n_br_fiscal/models/__init__.py +0 -3
  7. odoo/addons/l10n_br_fiscal/models/document.py +62 -20
  8. odoo/addons/l10n_br_fiscal/models/invalidate_number.py +0 -44
  9. odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +0 -5
  10. odoo/addons/l10n_br_fiscal/static/description/index.html +1 -1
  11. odoo/addons/l10n_br_fiscal/tests/__init__.py +0 -1
  12. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +0 -48
  13. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +0 -2
  14. odoo/addons/l10n_br_fiscal/tests/test_subsequent_operation.py +2 -1
  15. odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +0 -21
  16. odoo/addons/l10n_br_fiscal/views/document_view.xml +3 -69
  17. odoo/addons/l10n_br_fiscal/views/invalidate_number_view.xml +2 -7
  18. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +0 -34
  19. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +0 -19
  20. odoo/addons/l10n_br_fiscal/wizards/__init__.py +0 -6
  21. odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +0 -5
  22. odoo/addons/l10n_br_fiscal/wizards/document_status_wizard.py +2 -0
  23. {odoo_addon_l10n_br_fiscal-16.0.1.18.2.1.dist-info → odoo_addon_l10n_br_fiscal-16.0.2.0.0.2.dist-info}/METADATA +3 -3
  24. {odoo_addon_l10n_br_fiscal-16.0.1.18.2.1.dist-info → odoo_addon_l10n_br_fiscal-16.0.2.0.0.2.dist-info}/RECORD +26 -41
  25. odoo/addons/l10n_br_fiscal/models/document_eletronic.py +0 -233
  26. odoo/addons/l10n_br_fiscal/models/document_event.py +0 -392
  27. odoo/addons/l10n_br_fiscal/models/document_workflow.py +0 -402
  28. odoo/addons/l10n_br_fiscal/tests/test_workflow.py +0 -118
  29. odoo/addons/l10n_br_fiscal/views/document_event_report.xml +0 -15
  30. odoo/addons/l10n_br_fiscal/views/document_event_template.xml +0 -114
  31. odoo/addons/l10n_br_fiscal/views/document_event_view.xml +0 -68
  32. odoo/addons/l10n_br_fiscal/wizards/document_cancel_wizard.py +0 -20
  33. odoo/addons/l10n_br_fiscal/wizards/document_cancel_wizard.xml +0 -30
  34. odoo/addons/l10n_br_fiscal/wizards/document_correction_wizard.py +0 -17
  35. odoo/addons/l10n_br_fiscal/wizards/document_correction_wizard.xml +0 -30
  36. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +0 -132
  37. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.xml +0 -44
  38. odoo/addons/l10n_br_fiscal/wizards/document_status_wizard.xml +0 -58
  39. odoo/addons/l10n_br_fiscal/wizards/invalidate_number_wizard.py +0 -29
  40. odoo/addons/l10n_br_fiscal/wizards/invalidate_number_wizard.xml +0 -30
  41. {odoo_addon_l10n_br_fiscal-16.0.1.18.2.1.dist-info → odoo_addon_l10n_br_fiscal-16.0.2.0.0.2.dist-info}/WHEEL +0 -0
  42. {odoo_addon_l10n_br_fiscal-16.0.1.18.2.1.dist-info → odoo_addon_l10n_br_fiscal-16.0.2.0.0.2.dist-info}/top_level.txt +0 -0
@@ -1,233 +0,0 @@
1
- # Copyright (C) 2019 Renato Lima - Akretion
2
- # Copyright (C) 2019 KMEE INFORMATICA LTDA
3
- # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
4
-
5
- from odoo import _, api, fields, models
6
- from odoo.exceptions import UserError, ValidationError
7
-
8
- from ..constants.fiscal import (
9
- DOCUMENT_ISSUER,
10
- DOCUMENT_ISSUER_COMPANY,
11
- PROCESSADOR_NENHUM,
12
- SITUACAO_EDOC_AUTORIZADA,
13
- )
14
-
15
-
16
- def filter_processador(record):
17
- if record.document_electronic and record.processador_edoc == PROCESSADOR_NENHUM:
18
- return True
19
- return False
20
-
21
-
22
- class DocumentEletronic(models.AbstractModel):
23
- _name = "l10n_br_fiscal.document.electronic"
24
- _description = "Fiscal Eletronic Document"
25
- _inherit = "l10n_br_fiscal.document.workflow"
26
-
27
- issuer = fields.Selection(
28
- selection=DOCUMENT_ISSUER,
29
- default=DOCUMENT_ISSUER_COMPANY,
30
- )
31
-
32
- status_code = fields.Char(
33
- copy=False,
34
- )
35
-
36
- status_name = fields.Char(
37
- copy=False,
38
- )
39
-
40
- status_description = fields.Char(
41
- compute="_compute_status_description",
42
- copy=False,
43
- )
44
-
45
- # Authorization Event Related Fields
46
- authorization_event_id = fields.Many2one(
47
- comodel_name="l10n_br_fiscal.event",
48
- string="Authorization Event",
49
- readonly=True,
50
- copy=False,
51
- )
52
-
53
- authorization_date = fields.Datetime(
54
- related="authorization_event_id.protocol_date",
55
- string="Authorization Protocol Date",
56
- readonly=True,
57
- )
58
-
59
- authorization_protocol = fields.Char(
60
- related="authorization_event_id.protocol_number",
61
- string="Authorization Protocol Number",
62
- readonly=True,
63
- )
64
-
65
- send_file_id = fields.Many2one(
66
- comodel_name="ir.attachment",
67
- related="authorization_event_id.file_request_id",
68
- string="Send Document File XML",
69
- ondelete="restrict",
70
- readonly=True,
71
- )
72
-
73
- authorization_file_id = fields.Many2one(
74
- comodel_name="ir.attachment",
75
- related="authorization_event_id.file_response_id",
76
- string="Authorization File XML",
77
- ondelete="restrict",
78
- readonly=True,
79
- )
80
-
81
- # Cancel Event Related Fields
82
- cancel_event_id = fields.Many2one(
83
- comodel_name="l10n_br_fiscal.event",
84
- string="Cancel Event",
85
- copy=False,
86
- )
87
-
88
- cancel_date = fields.Datetime(
89
- related="cancel_event_id.protocol_date",
90
- string="Cancel Protocol Date",
91
- readonly=True,
92
- )
93
-
94
- cancel_protocol_number = fields.Char(
95
- related="cancel_event_id.protocol_number",
96
- string="Cancel Protocol Protocol",
97
- readonly=True,
98
- )
99
-
100
- cancel_file_id = fields.Many2one(
101
- comodel_name="ir.attachment",
102
- related="cancel_event_id.file_response_id",
103
- string="Cancel File XML",
104
- ondelete="restrict",
105
- readonly=True,
106
- )
107
-
108
- # Invalidate Event Related Fields
109
- invalidate_event_id = fields.Many2one(
110
- comodel_name="l10n_br_fiscal.event",
111
- string="Invalidate Event",
112
- copy=False,
113
- )
114
-
115
- invalidate_date = fields.Datetime(
116
- related="invalidate_event_id.protocol_date",
117
- string="Invalidate Protocol Date",
118
- readonly=True,
119
- )
120
-
121
- invalidate_protocol_number = fields.Char(
122
- related="invalidate_event_id.protocol_number",
123
- string="Invalidate Protocol Number",
124
- readonly=True,
125
- )
126
-
127
- invalidate_file_id = fields.Many2one(
128
- comodel_name="ir.attachment",
129
- related="invalidate_event_id.file_response_id",
130
- string="Invalidate File XML",
131
- ondelete="restrict",
132
- readonly=True,
133
- )
134
-
135
- document_version = fields.Char(string="Version", default="4.00", readonly=True)
136
-
137
- is_edoc_printed = fields.Boolean(string="Is Printed?", readonly=True)
138
-
139
- file_report_id = fields.Many2one(
140
- comodel_name="ir.attachment",
141
- string="Document Report",
142
- ondelete="restrict",
143
- readonly=True,
144
- copy=False,
145
- )
146
-
147
- @api.depends("status_code", "status_name")
148
- def _compute_status_description(self):
149
- for record in self:
150
- if record.status_code:
151
- record.status_description = "{} - {}".format(
152
- record.status_code or "",
153
- record.status_name or "",
154
- )
155
- else:
156
- record.status_description = False
157
-
158
- def _eletronic_document_send(self):
159
- """Implement this method in your transmission module,
160
- to send the electronic document and use the method _change_state
161
- to update the state of the transmited document,
162
-
163
- def _eletronic_document_send(self):
164
- super()._document_send()
165
- for record in self.filtered(myfilter):
166
- Do your transmission stuff
167
- [...]
168
- Change the state of the document
169
- """
170
- for record in self.filtered(filter_processador):
171
- record._change_state(SITUACAO_EDOC_AUTORIZADA)
172
-
173
- def _document_send(self):
174
- no_electronic = self.filtered(
175
- lambda d: not d.document_electronic
176
- or not d.issuer == DOCUMENT_ISSUER_COMPANY
177
- )
178
- no_electronic._no_eletronic_document_send()
179
- electronic = self - no_electronic
180
- electronic._eletronic_document_send()
181
-
182
- def serialize(self):
183
- edocs = []
184
- self._serialize(edocs)
185
- return edocs
186
-
187
- def _serialize(self, edocs):
188
- return edocs
189
-
190
- def _target_new_tab(self, attachment_id):
191
- if attachment_id:
192
- return {
193
- "type": "ir.actions.act_url",
194
- "url": f"/web/content/{attachment_id.id}/{attachment_id.name}",
195
- "target": "new",
196
- }
197
-
198
- def view_xml(self):
199
- self.ensure_one()
200
- xml_file = self.authorization_file_id or self.send_file_id
201
- if not xml_file:
202
- self._document_export()
203
- xml_file = self.authorization_file_id or self.send_file_id
204
- if not xml_file:
205
- raise UserError(_("No XML file generated!"))
206
- return self._target_new_tab(xml_file)
207
-
208
- def make_pdf(self):
209
- pass
210
-
211
- def view_pdf(self):
212
- self.ensure_one()
213
- if not self.file_report_id or not self.authorization_file_id:
214
- self.make_pdf()
215
- if not self.file_report_id:
216
- raise UserError(_("No PDF file generated!"))
217
- return self._target_new_tab(self.file_report_id)
218
-
219
- def _document_status(self):
220
- """Retorna o status do documento em texto e se necessário,
221
- atualiza o status do documento"""
222
- return
223
-
224
- @api.constrains("issuer")
225
- def _check_issuer(self):
226
- for record in self.filtered(lambda d: d.document_electronic):
227
- if not record.issuer:
228
- raise ValidationError(
229
- _(
230
- "The field 'Issuer' is required for brazilian electronic "
231
- "documents!"
232
- )
233
- )
@@ -1,392 +0,0 @@
1
- # Copyright (C) 2009 - TODAY Renato Lima - Akretion
2
- # Copyright (C) 2014 KMEE - www.kmee.com.br
3
- # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
4
-
5
- import base64
6
- import logging
7
- import os
8
-
9
- from odoo import _, api, fields, models
10
- from odoo.exceptions import UserError
11
-
12
- from ..constants.fiscal import EVENT_ENVIRONMENT
13
- from ..tools import build_edoc_path
14
-
15
- _logger = logging.getLogger(__name__)
16
-
17
- FILE_SUFIX_EVENT = {
18
- "0": "env",
19
- "1": "con-rec",
20
- "2": "can",
21
- "3": "inu",
22
- "4": "con-edoc",
23
- "5": "con-status",
24
- "6": "con-cad",
25
- "7": "dpec-rec",
26
- "8": "dpec-con",
27
- "9": "rec-eve",
28
- "10": "dow",
29
- "11": "con-dest",
30
- "12": "dist-dfe",
31
- "13": "man",
32
- "14": "cce",
33
- }
34
-
35
-
36
- class Event(models.Model):
37
- _name = "l10n_br_fiscal.event"
38
- _description = "Fiscal Event"
39
-
40
- @api.depends("document_id.name", "invalidate_number_id.name")
41
- def _compute_display_name(self):
42
- for record in self:
43
- if record.document_id:
44
- names = [
45
- _("Fiscal Document"),
46
- record.document_id.name,
47
- ]
48
- record.display_name = " / ".join(filter(None, names))
49
- elif record.invalidate_number_id:
50
- names = [
51
- _("Invalidate Number"),
52
- record.invalidate_number_id.name,
53
- ]
54
- record.display_name = " / ".join(filter(None, names))
55
- else:
56
- record.display_name = ""
57
-
58
- create_date = fields.Datetime(
59
- readonly=True,
60
- index=True,
61
- default=fields.Datetime.now,
62
- )
63
-
64
- write_date = fields.Datetime(
65
- readonly=True,
66
- index=True,
67
- )
68
-
69
- type = fields.Selection(
70
- selection=[
71
- ("-1", "Exception"),
72
- ("0", "Autorização de Uso"),
73
- ("1", "Consulta Recibo"),
74
- ("2", "Cancelamento"),
75
- ("3", "Inutilização"),
76
- ("4", "Consulta NFE"),
77
- ("5", "Consulta Situação"),
78
- ("6", "Consulta Cadastro"),
79
- ("7", "DPEC Recepção"),
80
- ("8", "DPEC Consulta"),
81
- ("9", "Recepção Evento"),
82
- ("10", "Download"),
83
- ("11", "Consulta Destinadas"),
84
- ("12", "Distribuição DFe"),
85
- ("13", "Manifestação"),
86
- ("14", "Carta de Correção"),
87
- ],
88
- string="Service",
89
- )
90
-
91
- origin = fields.Char(
92
- string="Source Document",
93
- readonly=True,
94
- help="Document reference that generated this event.",
95
- )
96
-
97
- document_id = fields.Many2one(
98
- comodel_name="l10n_br_fiscal.document",
99
- string="Fiscal Document",
100
- index=True,
101
- )
102
-
103
- document_type_id = fields.Many2one(
104
- comodel_name="l10n_br_fiscal.document.type",
105
- string="Fiscal Document Type",
106
- index=True,
107
- required=True,
108
- )
109
-
110
- document_serie_id = fields.Many2one(
111
- comodel_name="l10n_br_fiscal.document.serie",
112
- required=True,
113
- )
114
-
115
- document_number = fields.Char(
116
- required=True,
117
- )
118
-
119
- partner_id = fields.Many2one(
120
- comodel_name="res.partner",
121
- string="Partner",
122
- index=True,
123
- )
124
-
125
- invalidate_number_id = fields.Many2one(
126
- comodel_name="l10n_br_fiscal.invalidate.number",
127
- string="Invalidate Number",
128
- index=True,
129
- )
130
-
131
- company_id = fields.Many2one(
132
- comodel_name="res.company",
133
- string="Company",
134
- index=True,
135
- required=True,
136
- )
137
-
138
- sequence = fields.Char(
139
- help="Fiscal Document Event Sequence",
140
- )
141
-
142
- justification = fields.Char()
143
-
144
- display_name = fields.Char(
145
- string="name",
146
- compute="_compute_display_name",
147
- store=True,
148
- )
149
-
150
- file_request_id = fields.Many2one(
151
- comodel_name="ir.attachment",
152
- string="XML",
153
- copy=False,
154
- readonly=True,
155
- )
156
-
157
- file_response_id = fields.Many2one(
158
- comodel_name="ir.attachment",
159
- string="XML Response",
160
- copy=False,
161
- readonly=True,
162
- )
163
-
164
- file_path = fields.Char(
165
- readonly=True,
166
- )
167
-
168
- status_code = fields.Char(
169
- readonly=True,
170
- )
171
-
172
- response = fields.Char(
173
- string="Response Message",
174
- readonly=True,
175
- )
176
-
177
- message = fields.Char(
178
- readonly=True,
179
- )
180
-
181
- protocol_date = fields.Datetime(
182
- readonly=True,
183
- index=True,
184
- )
185
-
186
- protocol_number = fields.Char()
187
-
188
- lot_receipt_number = fields.Char(
189
- help=(
190
- "In asynchronous processing, a lot receipt number is generated, "
191
- "which is used for later consultation."
192
- ),
193
- )
194
-
195
- state = fields.Selection(
196
- selection=[
197
- ("draft", _("Draft")),
198
- ("send", _("Sending")),
199
- ("wait", _("Waiting Response")),
200
- ("done", _("Response received")),
201
- ],
202
- string="Status",
203
- readonly=True,
204
- index=True,
205
- default="draft",
206
- )
207
-
208
- environment = fields.Selection(
209
- selection=EVENT_ENVIRONMENT,
210
- )
211
-
212
- @api.constrains("justification")
213
- def _check_justification(self):
214
- if len(self.justification) < 15:
215
- raise UserError(_("Justification must be at least 15 characters."))
216
- return True
217
-
218
- def _save_event_2disk(self, arquivo, file_name):
219
- self.ensure_one()
220
- tipo_documento = self.document_type_id.prefix
221
- serie = self.document_serie_id.code
222
- numero = self.document_number
223
-
224
- if self.document_id:
225
- ano = self.document_id.document_date.strftime("%Y")
226
- mes = self.document_id.document_date.strftime("%m")
227
- elif self.invalidate_number_id:
228
- ano = self.invalidate_number_id.date.strftime("%Y")
229
- mes = self.invalidate_number_id.date.strftime("%m")
230
-
231
- save_dir = build_edoc_path(
232
- ambiente=self.environment,
233
- company_id=self.company_id,
234
- tipo_documento=tipo_documento,
235
- ano=ano,
236
- mes=mes,
237
- serie=serie,
238
- numero=numero,
239
- )
240
- file_path = os.path.join(save_dir, file_name)
241
- try:
242
- if not os.path.exists(save_dir):
243
- os.makedirs(save_dir)
244
- f = open(file_path, "w")
245
- except OSError as e:
246
- raise UserError(
247
- _("Erro!"),
248
- _(
249
- """Não foi possível salvar o arquivo
250
- em disco, verifique as permissões de escrita
251
- e o caminho da pasta"""
252
- ),
253
- ) from e
254
- else:
255
- f.write(arquivo)
256
- f.close()
257
- return save_dir
258
-
259
- def _compute_file_name(self):
260
- self.ensure_one()
261
- if (
262
- self.document_id
263
- and self.document_id.document_key
264
- and self.document_id.document_electronic
265
- and self.document_id.document_type_id
266
- and self.document_id.document_type_id.prefix
267
- ):
268
- file_name = (
269
- self.document_id.document_type_id.prefix + self.document_id.document_key
270
- )
271
- else:
272
- file_name = self.document_number
273
- return file_name
274
-
275
- def _save_event_file(
276
- self, file, file_extension, authorization=False, rejected=False
277
- ):
278
- self.ensure_one()
279
- file_name = self._compute_file_name()
280
-
281
- if authorization:
282
- file_name += "-proc"
283
- if rejected:
284
- file_name += "-rej"
285
-
286
- if self.type:
287
- file_name += "-" + FILE_SUFIX_EVENT[self.type]
288
-
289
- if self.sequence:
290
- file_name += "-" + str(self.sequence)
291
- if file_extension:
292
- file_name += "." + file_extension
293
-
294
- if self.company_id.document_save_disk:
295
- file_path = self._save_event_2disk(file, file_name)
296
- self.file_path = file_path
297
-
298
- attachment_id = self.env["ir.attachment"].create(
299
- {
300
- "name": file_name,
301
- "res_model": self._name,
302
- "res_id": self.id,
303
- "datas": base64.b64encode(file.encode("utf-8")),
304
- "mimetype": "application/" + file_extension,
305
- "type": "binary",
306
- }
307
- )
308
-
309
- if authorization:
310
- # Não deletamos um aquivo de autorização já
311
- # Existente por segurança
312
- self.file_response_id = False
313
- self.file_response_id = attachment_id
314
- else:
315
- self.file_request_id.unlink()
316
- self.file_request_id = attachment_id
317
- return attachment_id
318
-
319
- def set_done(
320
- self, status_code, response, protocol_date, protocol_number, file_response_xml
321
- ):
322
- if file_response_xml:
323
- self._save_event_file(file_response_xml, "xml", authorization=True)
324
- self.write(
325
- {
326
- "state": "done",
327
- "status_code": status_code,
328
- "response": response,
329
- "protocol_date": protocol_date,
330
- "protocol_number": protocol_number,
331
- }
332
- )
333
-
334
- def create_event_save_xml(
335
- self,
336
- company_id,
337
- environment,
338
- event_type,
339
- xml_file,
340
- document_id=False,
341
- invalidate_number_id=False,
342
- sequence=False,
343
- justification=False,
344
- ):
345
- vals = {
346
- "company_id": company_id.id,
347
- "environment": environment,
348
- "type": event_type,
349
- }
350
- if sequence:
351
- vals["sequence"] = sequence
352
- if document_id:
353
- #
354
- # Aplicado para envio, cancelamento, carta de correcao
355
- # e outras operações em que o documento esta presente.
356
- #
357
- vals["document_id"] = document_id.id
358
- vals["document_type_id"] = document_id.document_type_id.id
359
- vals["document_serie_id"] = document_id.document_serie_id.id
360
-
361
- if document_id.rps_number:
362
- vals["document_number"] = document_id.rps_number
363
- if document_id.document_number:
364
- vals["document_number"] += "-" + document_id.document_number
365
- else:
366
- vals["document_number"] = document_id.document_number
367
-
368
- if invalidate_number_id:
369
- #
370
- # Aplicado para inutilização
371
- #
372
- vals["invalidate_number_id"] = invalidate_number_id.id
373
- vals["document_type_id"] = invalidate_number_id.document_type_id.id
374
- vals["document_serie_id"] = invalidate_number_id.document_serie_id.id
375
- if invalidate_number_id.number_end != invalidate_number_id.number_start:
376
- vals["document_number"] = (
377
- str(invalidate_number_id.number_start)
378
- + "-"
379
- + str(invalidate_number_id.number_end)
380
- )
381
- else:
382
- vals["document_number"] = invalidate_number_id.number_start
383
- if justification:
384
- vals["justification"] = justification
385
- event_id = self.create(vals)
386
- event_id._save_event_file(xml_file, "xml")
387
- return event_id
388
-
389
- def print_document_event(self):
390
- return self.env.ref(
391
- "l10n_br_fiscal.action_report_document_event"
392
- ).report_action(self)