odoo-addon-l10n-br-fiscal 18.0.2.0.0.10__py3-none-any.whl → 18.0.7.1.0__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 (78) hide show
  1. odoo/addons/l10n_br_fiscal/README.rst +1 -1
  2. odoo/addons/l10n_br_fiscal/__manifest__.py +7 -3
  3. odoo/addons/l10n_br_fiscal/constants/fiscal.py +64 -18
  4. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cest.csv +1043 -983
  5. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cst.csv +58 -0
  6. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.document.type.csv +1 -0
  7. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.operation.indicator.csv +27 -0
  8. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.classification.csv +163 -0
  9. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.csv +31 -0
  10. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.group.csv +3 -0
  11. odoo/addons/l10n_br_fiscal/data/operation_data.xml +1 -1
  12. odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +3 -179
  13. odoo/addons/l10n_br_fiscal/demo/fiscal_document_nfse_demo.xml +0 -4
  14. odoo/addons/l10n_br_fiscal/demo/fiscal_operation_demo.xml +2 -2
  15. odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +665 -79
  16. odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +713 -102
  17. odoo/addons/l10n_br_fiscal/migrations/18.0.3.0.0/pre-migration.py +30 -0
  18. odoo/addons/l10n_br_fiscal/models/__init__.py +2 -2
  19. odoo/addons/l10n_br_fiscal/models/comment.py +3 -1
  20. odoo/addons/l10n_br_fiscal/models/data_abstract.py +9 -6
  21. odoo/addons/l10n_br_fiscal/models/document.py +27 -8
  22. odoo/addons/l10n_br_fiscal/models/document_line.py +51 -8
  23. odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +1107 -35
  24. odoo/addons/l10n_br_fiscal/models/document_mixin.py +244 -6
  25. odoo/addons/l10n_br_fiscal/models/document_related.py +1 -1
  26. odoo/addons/l10n_br_fiscal/models/document_serie.py +33 -0
  27. odoo/addons/l10n_br_fiscal/models/icms_regulation.py +1 -1
  28. odoo/addons/l10n_br_fiscal/models/operation_dashboard.py +3 -2
  29. odoo/addons/l10n_br_fiscal/models/operation_indicator.py +58 -0
  30. odoo/addons/l10n_br_fiscal/models/operation_line.py +28 -0
  31. odoo/addons/l10n_br_fiscal/models/partner_profile.py +6 -0
  32. odoo/addons/l10n_br_fiscal/models/product_template.py +4 -0
  33. odoo/addons/l10n_br_fiscal/models/res_company.py +17 -0
  34. odoo/addons/l10n_br_fiscal/models/res_partner.py +17 -0
  35. odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +8 -0
  36. odoo/addons/l10n_br_fiscal/models/tax.py +7 -3
  37. odoo/addons/l10n_br_fiscal/models/tax_classification.py +81 -0
  38. odoo/addons/l10n_br_fiscal/security/fiscal_security.xml +6 -16
  39. odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +7 -2
  40. odoo/addons/l10n_br_fiscal/static/description/index.html +1 -1
  41. odoo/addons/l10n_br_fiscal/tests/__init__.py +2 -0
  42. odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +175 -10
  43. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +13 -42
  44. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +0 -5
  45. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_serie.py +60 -0
  46. odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +2 -5
  47. odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +110 -0
  48. odoo/addons/l10n_br_fiscal/views/document_line_mixin_view.xml +107 -4
  49. odoo/addons/l10n_br_fiscal/views/document_line_view.xml +7 -3
  50. odoo/addons/l10n_br_fiscal/views/document_view.xml +34 -15
  51. odoo/addons/l10n_br_fiscal/views/icms_regulation_view.xml +1 -5
  52. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +30 -0
  53. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +16 -9
  54. odoo/addons/l10n_br_fiscal/views/nbs_view.xml +1 -5
  55. odoo/addons/l10n_br_fiscal/views/ncm_view.xml +1 -5
  56. odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +3 -3
  57. odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +75 -0
  58. odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +4 -5
  59. odoo/addons/l10n_br_fiscal/views/operation_view.xml +1 -5
  60. odoo/addons/l10n_br_fiscal/views/product_product_view.xml +33 -6
  61. odoo/addons/l10n_br_fiscal/views/product_template_view.xml +22 -4
  62. odoo/addons/l10n_br_fiscal/views/res_company_view.xml +6 -0
  63. odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +10 -0
  64. odoo/addons/l10n_br_fiscal/views/service_type_view.xml +1 -5
  65. odoo/addons/l10n_br_fiscal/views/tax_classification.xml +108 -0
  66. odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +1 -5
  67. odoo/addons/l10n_br_fiscal/views/tax_view.xml +2 -2
  68. odoo/addons/l10n_br_fiscal/wizards/__init__.py +1 -1
  69. odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +1 -1
  70. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard.py +234 -0
  71. odoo/addons/l10n_br_fiscal/wizards/{document_import_wizard_mixin.xml → document_import_wizard.xml} +26 -7
  72. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/METADATA +3 -3
  73. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/RECORD +75 -68
  74. odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +0 -837
  75. odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +0 -349
  76. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +0 -129
  77. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/WHEEL +0 -0
  78. {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/top_level.txt +0 -0
@@ -1,349 +0,0 @@
1
- # Copyright (C) 2019 Renato Lima - Akretion <renato.lima@akretion.com.br>
2
- # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
3
-
4
- from odoo import api, models
5
-
6
- from ..constants.fiscal import (
7
- DOCUMENT_ISSUER_COMPANY,
8
- )
9
-
10
-
11
- class FiscalDocumentMixinMethods(models.AbstractModel):
12
- """
13
- Provides the method implementations for l10n_br_fiscal.document.mixin.
14
-
15
- These methods are extracted into this separate mixin due to the way
16
- l10n_br_fiscal.document.line is incorporated into account.move
17
- by the l10n_br_account module (decorator pattern).
18
-
19
- Specifically:
20
- - In l10n_br_account, fields from l10n_br_fiscal.document
21
- are added to account.move using Odoo's `_inherits` (composition)
22
- mechanism.
23
- - The methods in *this* mixin, however, are intended to be inherited
24
- using the standard `_inherit` mechanism.
25
-
26
- This separation is crucial because `_inherits` handles field composition
27
- but does not inherit methods. Thus, `_inherit` is used to bring in
28
- these methods. If these methods were defined in the same class as the
29
- fields of l10n_br_fiscal.document.mixin (which are subject to
30
- `_inherits`), and account.move.line also used `_inherit` on that
31
- single class, the fields would be duplicated.
32
- """
33
-
34
- _name = "l10n_br_fiscal.document.mixin.methods"
35
- _description = "Fiscal Document Mixin Methods"
36
-
37
- def _prepare_br_fiscal_dict(self, default=False):
38
- self.ensure_one()
39
- fields = self.env["l10n_br_fiscal.document.mixin"]._fields.keys()
40
-
41
- # we now read the record fiscal fields except the m2m tax:
42
- vals = self._convert_to_write(self.read(fields)[0])
43
-
44
- # remove id field to avoid conflicts
45
- vals.pop("id", None)
46
-
47
- if default: # in case you want to use new rather than write later
48
- return {f"default_{k}": vals[k] for k in vals.keys()}
49
- return vals
50
-
51
- @api.onchange("document_type_id")
52
- def _onchange_document_type_id(self):
53
- if self.document_type_id and self.issuer == DOCUMENT_ISSUER_COMPANY:
54
- self.document_serie_id = self.document_type_id.get_document_serie(
55
- self.company_id, self.fiscal_operation_id
56
- )
57
-
58
- @api.depends("fiscal_operation_id")
59
- def _compute_document_type_id(self):
60
- for doc in self.filtered(lambda doc: doc.fiscal_operation_id):
61
- if doc.issuer == DOCUMENT_ISSUER_COMPANY and not doc.document_type_id:
62
- doc.document_type_id = doc.company_id.document_type_id
63
-
64
- def _get_amount_lines(self):
65
- """Get object lines instances used to compute fiscal fields"""
66
- return self.mapped(self._get_fiscal_lines_field_name())
67
-
68
- def _get_product_amount_lines(self):
69
- fiscal_line_ids = self._get_amount_lines()
70
- return fiscal_line_ids.filtered(lambda line: line.product_id.type != "service")
71
-
72
- @api.model
73
- def _get_amount_fields(self):
74
- """Get all fields with 'amount_' prefix"""
75
- fields = self.env["l10n_br_fiscal.document.mixin"]._fields.keys()
76
- amount_fields = [f for f in fields if f.startswith("amount_")]
77
- return amount_fields
78
-
79
- @api.depends("document_serie_id", "issuer")
80
- def _compute_document_serie(self):
81
- for doc in self:
82
- if doc.document_serie_id and doc.issuer == DOCUMENT_ISSUER_COMPANY:
83
- doc.document_serie = doc.document_serie_id.code
84
- elif doc.document_serie is None:
85
- doc.document_serie = False
86
-
87
- @api.depends("document_type_id", "issuer")
88
- def _compute_document_serie_id(self):
89
- for doc in self:
90
- if doc.document_type_id and doc.issuer == DOCUMENT_ISSUER_COMPANY:
91
- doc.document_serie_id = doc.document_type_id.get_document_serie(
92
- doc.company_id, doc.fiscal_operation_id
93
- )
94
- elif doc.document_serie_id is None:
95
- doc.document_serie_id = False
96
-
97
- @api.model
98
- def _get_fiscal_lines_field_name(self):
99
- return "fiscal_line_ids"
100
-
101
- def _get_fiscal_amount_field_dependencies(self):
102
- """
103
- Dynamically get the list of field dependencies.
104
- """
105
- if self._abstract:
106
- return []
107
- o2m_field_name = self._get_fiscal_lines_field_name()
108
- target_fields = []
109
- for field in self._get_amount_fields():
110
- if (
111
- field.replace("amount_", "")
112
- in getattr(self, o2m_field_name)._fields.keys()
113
- ):
114
- target_fields.append(field.replace("amount_", ""))
115
-
116
- return [o2m_field_name] + [
117
- f"{o2m_field_name}.{target_field}" for target_field in target_fields
118
- ]
119
-
120
- @api.depends(lambda self: self._get_fiscal_amount_field_dependencies())
121
- def _compute_fiscal_amount(self):
122
- """
123
- Compute and sum various fiscal amounts from the document lines.
124
-
125
- This method iterates over fields prefixed with 'amount_' (as determined
126
- by `_get_amount_fields`) and sums corresponding values from the lines
127
- retrieved by `_get_amount_lines`.
128
-
129
- It handles cases where delivery costs (freight, insurance, other) are
130
- defined at the document total level rather than per line.
131
- """
132
-
133
- fields = self._get_amount_fields()
134
- for doc in self.filtered(lambda m: m.fiscal_operation_id):
135
- values = {key: 0.0 for key in fields}
136
- for line in doc._get_amount_lines():
137
- for field in fields:
138
- if field in line._fields.keys():
139
- values[field] += line[field]
140
- if field.replace("amount_", "") in line._fields.keys():
141
- # FIXME this field creates an error in invoice form
142
- if field == "amount_financial_discount_value":
143
- values["amount_financial_discount_value"] += (
144
- 0 # line.financial_discount_value
145
- )
146
- else:
147
- values[field] += line[field.replace("amount_", "")]
148
-
149
- # Valores definidos pelo Total e não pela Linha
150
- if (
151
- doc.company_id.delivery_costs == "total"
152
- or doc.force_compute_delivery_costs_by_total
153
- ):
154
- values["amount_freight_value"] = doc.amount_freight_value
155
- values["amount_insurance_value"] = doc.amount_insurance_value
156
- values["amount_other_value"] = doc.amount_other_value
157
-
158
- doc.update(values)
159
-
160
- def _get_fiscal_partner(self):
161
- """
162
- Hook method to determine the fiscal partner for the document.
163
-
164
- This method is designed to be overridden in implementing models if the
165
- partner relevant for fiscal purposes (e.g., for tax calculations,
166
- final consumer status) is different from the main `partner_id`
167
- of the document record. For instance, an invoice might use a specific
168
- invoicing contact derived from the main partner.
169
-
170
- :return: A `res.partner` recordset representing the fiscal partner.
171
- """
172
-
173
- self.ensure_one()
174
- return self.partner_id
175
-
176
- @api.onchange("partner_id")
177
- def _onchange_partner_id_fiscal(self):
178
- partner = self._get_fiscal_partner()
179
- if partner:
180
- self.ind_final = partner.ind_final
181
- for line in self._get_amount_lines():
182
- # reload fiscal data, operation line, cfop, taxes, etc.
183
- line._onchange_fiscal_operation_id()
184
-
185
- @api.depends("fiscal_operation_id")
186
- def _compute_operation_name(self):
187
- for doc in self:
188
- if doc.fiscal_operation_id:
189
- doc.operation_name = doc.fiscal_operation_id.name
190
- else:
191
- doc.operation_name = False
192
-
193
- @api.depends("fiscal_operation_id")
194
- def _compute_comment_ids(self):
195
- for doc in self:
196
- if doc.fiscal_operation_id:
197
- doc.comment_ids = doc.fiscal_operation_id.comment_ids
198
- elif doc.comment_ids is None:
199
- doc.comment_ids = []
200
-
201
- def _inverse_amount_freight(self):
202
- for record in self.filtered(lambda doc: doc._get_product_amount_lines()):
203
- if (
204
- record.delivery_costs == "total"
205
- or record.force_compute_delivery_costs_by_total
206
- ):
207
- amount_freight_value = record.amount_freight_value
208
- if all(record._get_product_amount_lines().mapped("freight_value")):
209
- amount_freight_old = sum(
210
- record._get_product_amount_lines().mapped("freight_value")
211
- )
212
- for line in record._get_product_amount_lines()[:-1]:
213
- line.freight_value = amount_freight_value * (
214
- line.freight_value / amount_freight_old
215
- )
216
- record._get_product_amount_lines()[-1].freight_value = (
217
- amount_freight_value
218
- - sum(
219
- line.freight_value
220
- for line in record._get_product_amount_lines()[:-1]
221
- )
222
- )
223
- else:
224
- amount_total = sum(
225
- record._get_product_amount_lines().mapped("price_gross")
226
- )
227
- for line in record._get_product_amount_lines()[:-1]:
228
- if line.price_gross and amount_total:
229
- line.freight_value = amount_freight_value * (
230
- line.price_gross / amount_total
231
- )
232
- record._get_product_amount_lines()[-1].freight_value = (
233
- amount_freight_value
234
- - sum(
235
- line.freight_value
236
- for line in record._get_product_amount_lines()[:-1]
237
- )
238
- )
239
- for line in record._get_product_amount_lines():
240
- line._onchange_fiscal_taxes()
241
- record._fields["amount_total"].compute_value(record)
242
- record.write(
243
- {
244
- name: value
245
- for name, value in record._cache.items()
246
- if record._fields[name].compute == "_amount_all"
247
- and not record._fields[name].inverse
248
- }
249
- )
250
-
251
- def _inverse_amount_insurance(self):
252
- for record in self.filtered(lambda doc: doc._get_product_amount_lines()):
253
- if (
254
- record.delivery_costs == "total"
255
- or record.force_compute_delivery_costs_by_total
256
- ):
257
- amount_insurance_value = record.amount_insurance_value
258
- if all(record._get_product_amount_lines().mapped("insurance_value")):
259
- amount_insurance_old = sum(
260
- record._get_product_amount_lines().mapped("insurance_value")
261
- )
262
- for line in record._get_product_amount_lines()[:-1]:
263
- line.insurance_value = amount_insurance_value * (
264
- line.insurance_value / amount_insurance_old
265
- )
266
- record._get_product_amount_lines()[-1].insurance_value = (
267
- amount_insurance_value
268
- - sum(
269
- line.insurance_value
270
- for line in record._get_product_amount_lines()[:-1]
271
- )
272
- )
273
- else:
274
- amount_total = sum(
275
- record._get_product_amount_lines().mapped("price_gross")
276
- )
277
- for line in record._get_product_amount_lines()[:-1]:
278
- if line.price_gross and amount_total:
279
- line.insurance_value = amount_insurance_value * (
280
- line.price_gross / amount_total
281
- )
282
- record._get_product_amount_lines()[-1].insurance_value = (
283
- amount_insurance_value
284
- - sum(
285
- line.insurance_value
286
- for line in record._get_product_amount_lines()[:-1]
287
- )
288
- )
289
- for line in record._get_product_amount_lines():
290
- line._onchange_fiscal_taxes()
291
- record._fields["amount_total"].compute_value(record)
292
- record.write(
293
- {
294
- name: value
295
- for name, value in record._cache.items()
296
- if record._fields[name].compute == "_amount_all"
297
- and not record._fields[name].inverse
298
- }
299
- )
300
-
301
- def _inverse_amount_other(self):
302
- for record in self.filtered(lambda doc: doc._get_product_amount_lines()):
303
- if (
304
- record.delivery_costs == "total"
305
- or record.force_compute_delivery_costs_by_total
306
- ):
307
- amount_other_value = record.amount_other_value
308
- if all(record._get_product_amount_lines().mapped("other_value")):
309
- amount_other_old = sum(
310
- record._get_product_amount_lines().mapped("other_value")
311
- )
312
- for line in record._get_product_amount_lines()[:-1]:
313
- line.other_value = amount_other_value * (
314
- line.other_value / amount_other_old
315
- )
316
- record._get_product_amount_lines()[-1].other_value = (
317
- amount_other_value
318
- - sum(
319
- line.other_value
320
- for line in record._get_product_amount_lines()[:-1]
321
- )
322
- )
323
- else:
324
- amount_total = sum(
325
- record._get_product_amount_lines().mapped("price_gross")
326
- )
327
- for line in record._get_product_amount_lines()[:-1]:
328
- if line.price_gross and amount_total:
329
- line.other_value = amount_other_value * (
330
- line.price_gross / amount_total
331
- )
332
- record._get_product_amount_lines()[-1].other_value = (
333
- amount_other_value
334
- - sum(
335
- line.other_value
336
- for line in record._get_product_amount_lines()[:-1]
337
- )
338
- )
339
- for line in record._get_product_amount_lines():
340
- line._onchange_fiscal_taxes()
341
- record._fields["amount_total"].compute_value(record)
342
- record.write(
343
- {
344
- name: value
345
- for name, value in record._cache.items()
346
- if record._fields[name].compute == "_amount_all"
347
- and not record._fields[name].inverse
348
- }
349
- )
@@ -1,129 +0,0 @@
1
- # Copyright (C) 2023 Felipe Zago Rodrigues - Kmee
2
- # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
3
-
4
- import base64
5
- import logging
6
-
7
- from odoo import _, api, fields, models
8
- from odoo.exceptions import UserError
9
-
10
- from ..constants.fiscal import FISCAL_IN_OUT_ALL
11
-
12
- _logger = logging.getLogger(__name__)
13
-
14
- try:
15
- from xsdata.formats.dataclass.parsers import XmlParser
16
- except ImportError:
17
- _logger.warning("xsdata Python lib not installed!")
18
-
19
-
20
- class DocumentImportWizardMixin(models.TransientModel):
21
- _name = "l10n_br_fiscal.document.import.wizard.mixin"
22
- _description = "Wizard Import Document Mixin"
23
- _inherit = "l10n_br_fiscal.base.wizard.mixin"
24
-
25
- company_id = fields.Many2one(
26
- comodel_name="res.company",
27
- string="Company",
28
- default=lambda self: self.env.company.id,
29
- )
30
-
31
- file = fields.Binary(string="File to Import")
32
-
33
- fiscal_operation_id = fields.Many2one(
34
- comodel_name="l10n_br_fiscal.operation",
35
- string="Fiscal Operation",
36
- domain="[('fiscal_operation_type', '=', fiscal_operation_type)]",
37
- )
38
-
39
- document_type = fields.Char()
40
-
41
- fiscal_operation_type = fields.Selection(selection=FISCAL_IN_OUT_ALL)
42
-
43
- def _import_edoc(self):
44
- self._find_existing_document()
45
- if not self.document_id:
46
- binding, self.document_id = self._create_edoc_from_file()
47
- else:
48
- binding = self._parse_file()
49
- return binding, self.document_id
50
-
51
- def action_import_and_open_document(self):
52
- self._import_edoc()
53
- return self.action_open_document()
54
-
55
- def _create_edoc_from_file(self):
56
- pass # meant to be overriden
57
-
58
- @api.onchange("file")
59
- def _onchange_file(self):
60
- if self.file:
61
- self._fill_wizard_from_binding()
62
-
63
- def _fill_wizard_from_binding(self):
64
- pass # meant to be overriden
65
-
66
- def action_open_document(self):
67
- return {
68
- "name": _("Document Imported"),
69
- "type": "ir.actions.act_window",
70
- "target": "current",
71
- "views": [[False, "form"]],
72
- "res_id": self.document_id.id,
73
- "res_model": "l10n_br_fiscal.document",
74
- }
75
-
76
- def _document_key_from_binding(self, binding):
77
- pass # meant to be overriden
78
-
79
- def _find_existing_document(self):
80
- document_key = self._document_key_from_binding(self._parse_file())
81
- self.document_id = self.env["l10n_br_fiscal.document"].search(
82
- [("document_key", "=", document_key.chave)],
83
- limit=1,
84
- )
85
-
86
- def _find_document_type(self, code):
87
- return self.env["l10n_br_fiscal.document.type"].search(
88
- [("code", "=", code)],
89
- limit=1,
90
- )
91
-
92
- def _find_fiscal_operation(self, cfop, nat_op, fiscal_operation_type):
93
- """try to find a matching fiscal operation via an operation line"""
94
- operation_lines = self.env["l10n_br_fiscal.operation.line"].search(
95
- [
96
- ("state", "=", "approved"),
97
- ("fiscal_type", "=", fiscal_operation_type),
98
- ("cfop_external_id", "=", cfop),
99
- ],
100
- )
101
- for line in operation_lines:
102
- if line.fiscal_operation_id.name == nat_op:
103
- return line.fiscal_operation_id
104
- if operation_lines:
105
- return operation_lines[0].fiscal_operation_id
106
-
107
- def _parse_file(self):
108
- return self._parse_file_data(self.file)
109
-
110
- @api.model
111
- def _parse_file_data(self, file_data):
112
- # NOTE: no try and a stacktrace does help for debug/support
113
- return XmlParser().from_bytes(base64.b64decode(file_data))
114
-
115
- @api.model
116
- def _detect_binding(self, binding):
117
- """
118
- A pluggable method were each specialized fiscal document
119
- importation wizard can register itself and return a tuple
120
- with (the_fiscal_document_type_code, the_name_of_the_importation_wizard)
121
- """
122
- raise UserError(
123
- _("Importation not implemented for %s!")
124
- % (
125
- type(
126
- binding,
127
- )
128
- )
129
- )