odoo-addon-l10n-br-fiscal 16.0.8.0.2__py3-none-any.whl → 16.0.19.4.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.
Files changed (115) hide show
  1. odoo/addons/l10n_br_fiscal/README.rst +1 -1
  2. odoo/addons/l10n_br_fiscal/__manifest__.py +10 -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/data/uom_data.xml +186 -33
  13. odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +3 -377
  14. odoo/addons/l10n_br_fiscal/demo/fiscal_document_nfse_demo.xml +0 -12
  15. odoo/addons/l10n_br_fiscal/demo/fiscal_operation_demo.xml +2 -2
  16. odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +902 -304
  17. odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +22 -22
  18. odoo/addons/l10n_br_fiscal/migrations/16.0.13.0.0/pre-migration.py +25 -0
  19. odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.0/pre-migration.py +30 -0
  20. odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.5/pre-migration.py +15 -0
  21. odoo/addons/l10n_br_fiscal/models/__init__.py +3 -2
  22. odoo/addons/l10n_br_fiscal/models/comment.py +2 -2
  23. odoo/addons/l10n_br_fiscal/models/data_ncm_nbs_abstract.py +1 -1
  24. odoo/addons/l10n_br_fiscal/models/document.py +83 -226
  25. odoo/addons/l10n_br_fiscal/models/document_line.py +67 -5
  26. odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +1932 -136
  27. odoo/addons/l10n_br_fiscal/models/document_mixin.py +248 -17
  28. odoo/addons/l10n_br_fiscal/models/document_related.py +11 -8
  29. odoo/addons/l10n_br_fiscal/models/document_serie.py +33 -0
  30. odoo/addons/l10n_br_fiscal/models/ibpt.py +1 -1
  31. odoo/addons/l10n_br_fiscal/models/icms_regulation.py +1 -1
  32. odoo/addons/l10n_br_fiscal/models/invalidate_number.py +4 -5
  33. odoo/addons/l10n_br_fiscal/models/operation_dashboard.py +3 -2
  34. odoo/addons/l10n_br_fiscal/models/operation_indicator.py +58 -0
  35. odoo/addons/l10n_br_fiscal/models/operation_line.py +28 -0
  36. odoo/addons/l10n_br_fiscal/models/partner_profile.py +6 -0
  37. odoo/addons/l10n_br_fiscal/models/product_template.py +5 -1
  38. odoo/addons/l10n_br_fiscal/models/res_company.py +18 -0
  39. odoo/addons/l10n_br_fiscal/models/res_partner.py +27 -6
  40. odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +8 -0
  41. odoo/addons/l10n_br_fiscal/models/tax.py +7 -3
  42. odoo/addons/l10n_br_fiscal/models/tax_classification.py +81 -0
  43. odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_base.py +1 -1
  44. odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_credit.py +1 -1
  45. odoo/addons/l10n_br_fiscal/models/uom_uom.py +24 -0
  46. odoo/addons/l10n_br_fiscal/security/fiscal_security.xml +6 -16
  47. odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +8 -2
  48. odoo/addons/l10n_br_fiscal/static/description/index.html +1 -1
  49. odoo/addons/l10n_br_fiscal/tests/__init__.py +3 -0
  50. odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +308 -0
  51. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +23 -111
  52. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +5 -13
  53. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_serie.py +60 -0
  54. odoo/addons/l10n_br_fiscal/tests/test_ibpt.py +2 -2
  55. odoo/addons/l10n_br_fiscal/tests/test_icms_regulation.py +2 -2
  56. odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +14 -20
  57. odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +110 -0
  58. odoo/addons/l10n_br_fiscal/tools.py +1 -1
  59. odoo/addons/l10n_br_fiscal/views/cest_view.xml +2 -4
  60. odoo/addons/l10n_br_fiscal/views/cfop_view.xml +3 -5
  61. odoo/addons/l10n_br_fiscal/views/city_taxation_code.xml +1 -4
  62. odoo/addons/l10n_br_fiscal/views/cnae_view.xml +2 -4
  63. odoo/addons/l10n_br_fiscal/views/comment_view.xml +2 -4
  64. odoo/addons/l10n_br_fiscal/views/cst_view.xml +6 -8
  65. odoo/addons/l10n_br_fiscal/views/{document_fiscal_line_mixin_view.xml → document_line_mixin_view.xml} +525 -388
  66. odoo/addons/l10n_br_fiscal/views/document_line_view.xml +101 -82
  67. odoo/addons/l10n_br_fiscal/views/document_related_view.xml +44 -46
  68. odoo/addons/l10n_br_fiscal/views/document_serie_view.xml +2 -6
  69. odoo/addons/l10n_br_fiscal/views/document_type_view.xml +0 -2
  70. odoo/addons/l10n_br_fiscal/views/document_view.xml +304 -346
  71. odoo/addons/l10n_br_fiscal/views/icms_regulation_view.xml +14 -16
  72. odoo/addons/l10n_br_fiscal/views/icms_relief_view.xml +8 -10
  73. odoo/addons/l10n_br_fiscal/views/invalidate_number_view.xml +46 -48
  74. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +162 -244
  75. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +16 -72
  76. odoo/addons/l10n_br_fiscal/views/legal_nature_view.xml +0 -2
  77. odoo/addons/l10n_br_fiscal/views/nbm_view.xml +5 -6
  78. odoo/addons/l10n_br_fiscal/views/nbs_view.xml +5 -6
  79. odoo/addons/l10n_br_fiscal/views/ncm_view.xml +12 -15
  80. odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +13 -12
  81. odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +75 -0
  82. odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +22 -21
  83. odoo/addons/l10n_br_fiscal/views/operation_view.xml +3 -6
  84. odoo/addons/l10n_br_fiscal/views/partner_profile_view.xml +3 -6
  85. odoo/addons/l10n_br_fiscal/views/product_genre_view.xml +7 -9
  86. odoo/addons/l10n_br_fiscal/views/product_product_view.xml +37 -14
  87. odoo/addons/l10n_br_fiscal/views/product_template_view.xml +34 -14
  88. odoo/addons/l10n_br_fiscal/views/res_company_view.xml +40 -38
  89. odoo/addons/l10n_br_fiscal/views/res_config_settings_view.xml +23 -28
  90. odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +13 -2
  91. odoo/addons/l10n_br_fiscal/views/service_type_view.xml +7 -8
  92. odoo/addons/l10n_br_fiscal/views/simplified_tax_range_view.xml +0 -2
  93. odoo/addons/l10n_br_fiscal/views/simplified_tax_view.xml +0 -2
  94. odoo/addons/l10n_br_fiscal/views/tax_classification.xml +110 -0
  95. odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +157 -129
  96. odoo/addons/l10n_br_fiscal/views/tax_estimate_view.xml +0 -2
  97. odoo/addons/l10n_br_fiscal/views/tax_group_view.xml +3 -6
  98. odoo/addons/l10n_br_fiscal/views/tax_ipi_control_seal_view.xml +0 -2
  99. odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_class_view.xml +0 -2
  100. odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_view.xml +2 -4
  101. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_base_view.xml +2 -4
  102. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_credit_view.xml +2 -4
  103. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_view.xml +5 -7
  104. odoo/addons/l10n_br_fiscal/views/tax_view.xml +5 -7
  105. odoo/addons/l10n_br_fiscal/views/uom_uom.xml +52 -0
  106. odoo/addons/l10n_br_fiscal/wizards/__init__.py +1 -0
  107. odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +1 -1
  108. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +129 -0
  109. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.xml +41 -0
  110. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/METADATA +3 -3
  111. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/RECORD +113 -99
  112. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/WHEEL +1 -1
  113. odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +0 -814
  114. odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +0 -363
  115. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/top_level.txt +0 -0
@@ -1,814 +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 copy import deepcopy
5
-
6
- from lxml import etree
7
-
8
- from odoo import api, models
9
-
10
- from ..constants.fiscal import CFOP_DESTINATION_EXPORT, FISCAL_IN
11
- from ..constants.icms import ICMS_BASE_TYPE_DEFAULT, ICMS_ST_BASE_TYPE_DEFAULT
12
- from .tax import TAX_DICT_VALUES
13
-
14
- FISCAL_TAX_ID_FIELDS = [
15
- "cofins_tax_id",
16
- "cofins_wh_tax_id",
17
- "cofinsst_tax_id",
18
- "csll_tax_id",
19
- "csll_wh_tax_id",
20
- "icms_tax_id",
21
- "icmsfcp_tax_id",
22
- "icmssn_tax_id",
23
- "icmsst_tax_id",
24
- "icmsfcpst_tax_id",
25
- "ii_tax_id",
26
- "inss_tax_id",
27
- "inss_wh_tax_id",
28
- "ipi_tax_id",
29
- "irpj_tax_id",
30
- "irpj_wh_tax_id",
31
- "issqn_tax_id",
32
- "issqn_wh_tax_id",
33
- "pis_tax_id",
34
- "pis_wh_tax_id",
35
- "pisst_tax_id",
36
- ]
37
-
38
- FISCAL_CST_ID_FIELDS = [
39
- "icms_cst_id",
40
- "ipi_cst_id",
41
- "pis_cst_id",
42
- "pisst_cst_id",
43
- "cofins_cst_id",
44
- "cofinsst_cst_id",
45
- ]
46
-
47
-
48
- class FiscalDocumentLineMixinMethods(models.AbstractModel):
49
- """
50
- Provides the method implementations for l10n_br_fiscal.document.line.mixin.
51
-
52
- These methods are extracted into this separate mixin due to the way
53
- l10n_br_fiscal.document.line is incorporated into account.move.line
54
- by the l10n_br_account module (decorator pattern).
55
-
56
- Specifically:
57
- - In l10n_br_account, fields from l10n_br_fiscal.document.line
58
- are added to account.move.line using Odoo's `_inherits` (composition)
59
- mechanism.
60
- - The methods in *this* mixin, however, are intended to be inherited
61
- using the standard `_inherit` mechanism.
62
-
63
- This separation is crucial because `_inherits` handles field composition
64
- but does not inherit methods. Thus, `_inherit` is used to bring in
65
- these methods. If these methods were defined in the same class as the
66
- fields of l10n_br_fiscal.document.line.mixin (which are subject to
67
- `_inherits`), and account.move.line also used `_inherit` on that
68
- single class, the fields would be duplicated.
69
- """
70
-
71
- _name = "l10n_br_fiscal.document.line.mixin.methods"
72
- _description = "Fiscal Document Mixin Methods"
73
-
74
- @api.model
75
- def inject_fiscal_fields(
76
- self,
77
- doc,
78
- view_ref="l10n_br_fiscal.document_fiscal_line_mixin_form",
79
- xpath_mappings=None,
80
- ):
81
- """
82
- Inject common fiscal fields into view placeholder elements.
83
- Used for invoice line, sale order line, purchase order line...
84
- """
85
- fiscal_view = self.env.ref(
86
- "l10n_br_fiscal.document_fiscal_line_mixin_form"
87
- ).sudo()
88
- fsc_doc = etree.fromstring(
89
- fiscal_view.with_context(inherit_branding=True).get_combined_arch()
90
- )
91
-
92
- if xpath_mappings is None:
93
- xpath_mappings = (
94
- # (placeholder_xpath, fiscal_xpath)
95
- (".//group[@name='fiscal_fields']", "//group[@name='fiscal_fields']"),
96
- (".//page[@name='fiscal_taxes']", "//page[@name='fiscal_taxes']"),
97
- (
98
- ".//page[@name='fiscal_line_extra_info']",
99
- "//page[@name='fiscal_line_extra_info']",
100
- ),
101
- # these will only collect (invisible) fields for onchanges:
102
- (
103
- ".//control[@name='fiscal_fields']...",
104
- "//group[@name='fiscal_fields']//field",
105
- ),
106
- (
107
- ".//control[@name='fiscal_taxes_fields']...",
108
- "//page[@name='fiscal_taxes']//field",
109
- ),
110
- (
111
- ".//control[@name='fiscal_line_extra_info_fields']...",
112
- "//page[@name='fiscal_line_extra_info']//field",
113
- ),
114
- )
115
- for placeholder_xpath, fiscal_xpath in xpath_mappings:
116
- placeholder_nodes = doc.findall(placeholder_xpath)
117
- if not placeholder_nodes:
118
- continue
119
- fiscal_nodes = fsc_doc.xpath(fiscal_xpath)
120
- for target_node in placeholder_nodes:
121
- if len(fiscal_nodes) == 1:
122
- # replace unique placeholder
123
- # (deepcopy is required to inject fiscal nodes in possible
124
- # next places)
125
- replace_node = deepcopy(fiscal_nodes[0])
126
- target_node.getparent().replace(target_node, replace_node)
127
- else:
128
- # append multiple fields to placeholder container
129
- existing_fields = [
130
- e.attrib["name"] for e in target_node if e.tag == "field"
131
- ]
132
- for fiscal_node in fiscal_nodes:
133
- if fiscal_node.attrib["name"] in existing_fields:
134
- continue
135
- field = deepcopy(fiscal_node)
136
- if not field.attrib.get("optional"):
137
- field.attrib["invisible"] = "0"
138
- field.attrib["optional"] = "hide"
139
- target_node.append(field)
140
- return doc
141
-
142
- @api.model
143
- def _get_view(self, view_id=None, view_type="form", **options):
144
- arch, view = super()._get_view(view_id, view_type, **options)
145
- if view_type == "form":
146
- arch = self.inject_fiscal_fields(arch)
147
- return arch, view
148
-
149
- @api.depends(
150
- "fiscal_price",
151
- "discount_value",
152
- "insurance_value",
153
- "other_value",
154
- "freight_value",
155
- "fiscal_quantity",
156
- "amount_tax_not_included",
157
- "amount_tax_included",
158
- "amount_tax_withholding",
159
- "uot_id",
160
- "product_id",
161
- "partner_id",
162
- "company_id",
163
- "price_unit",
164
- "quantity",
165
- "icms_relief_id",
166
- "fiscal_operation_line_id",
167
- )
168
- def _compute_fiscal_amounts(self):
169
- for record in self:
170
- round_curr = record.currency_id or self.env.ref("base.BRL")
171
-
172
- # Total value of products or services
173
- record.price_gross = round_curr.round(record.price_unit * record.quantity)
174
- record.amount_fiscal = record.price_gross - record.discount_value
175
- record.amount_tax = record.amount_tax_not_included
176
-
177
- add_to_amount = sum(record[a] for a in record._add_fields_to_amount())
178
- rm_to_amount = sum(record[r] for r in record._rm_fields_to_amount())
179
- record.amount_untaxed = (
180
- record.price_gross
181
- - record.discount_value
182
- + add_to_amount
183
- - rm_to_amount
184
- )
185
-
186
- # Valor do documento (NF)
187
- record.amount_total = record.amount_untaxed + record.amount_tax
188
-
189
- # Valor Liquido (TOTAL + IMPOSTOS - RETENÇÕES)
190
- record.amount_taxed = record.amount_total - record.amount_tax_withholding
191
-
192
- # Valor do documento (NF) - RETENÇÕES
193
- record.amount_total = record.amount_taxed
194
-
195
- # Valor financeiro
196
- if (
197
- record.fiscal_operation_line_id
198
- and record.fiscal_operation_line_id.add_to_amount
199
- and (not record.cfop_id or record.cfop_id.finance_move)
200
- ):
201
- record.financial_total = record.amount_taxed
202
- record.financial_total_gross = (
203
- record.financial_total + record.discount_value
204
- )
205
- record.financial_discount_value = record.discount_value
206
- else:
207
- record.financial_total_gross = record.financial_total = 0.0
208
- record.financial_discount_value = 0.0
209
-
210
- def _compute_taxes(self, taxes, cst=None):
211
- self.ensure_one()
212
- return taxes.compute_taxes(
213
- company=self.company_id,
214
- partner=self._get_fiscal_partner(),
215
- product=self.product_id,
216
- price_unit=self.price_unit,
217
- quantity=self.quantity,
218
- uom_id=self.uom_id,
219
- fiscal_price=self.fiscal_price,
220
- fiscal_quantity=self.fiscal_quantity,
221
- uot_id=self.uot_id,
222
- discount_value=self.discount_value,
223
- insurance_value=self.insurance_value,
224
- ii_customhouse_charges=self.ii_customhouse_charges,
225
- ii_iof_value=self.ii_iof_value,
226
- other_value=self.other_value,
227
- freight_value=self.freight_value,
228
- ncm=self.ncm_id,
229
- nbs=self.nbs_id,
230
- nbm=self.nbm_id,
231
- cest=self.cest_id,
232
- operation_line=self.fiscal_operation_line_id,
233
- cfop=self.cfop_id,
234
- icmssn_range=self.icmssn_range_id,
235
- icms_origin=self.icms_origin,
236
- icms_cst_id=self.icms_cst_id,
237
- ind_final=self.ind_final,
238
- icms_relief_id=self.icms_relief_id,
239
- )
240
-
241
- @api.depends("tax_icms_or_issqn", "partner_is_public_entity")
242
- def _compute_allow_csll_irpj(self):
243
- """Calculates the possibility of 'CSLL' and 'IRPJ' tax charges."""
244
- for line in self:
245
- # Determine if 'CSLL' and 'IRPJ' taxes may apply:
246
- # 1. When providing services (tax_icms_or_issqn == "issqn")
247
- # 2. When supplying products to public entities (partner_is_public_entity
248
- # is True)
249
- if line.tax_icms_or_issqn == "issqn" or line.partner_is_public_entity:
250
- line.allow_csll_irpj = True # Tax charges may apply
251
- else:
252
- line.allow_csll_irpj = False # No tax charges expected
253
-
254
- def _prepare_br_fiscal_dict(self, default=False):
255
- self.ensure_one()
256
- fields = self.env["l10n_br_fiscal.document.line.mixin"]._fields.keys()
257
-
258
- # we now read the record fiscal fields except the m2m tax:
259
- vals = self._convert_to_write(self.read(fields)[0])
260
-
261
- # remove id field to avoid conflicts
262
- vals.pop("id", None)
263
-
264
- if default: # in case you want to use new rather than write later
265
- return {f"default_{k}": vals[k] for k in vals.keys()}
266
- return vals
267
-
268
- def _get_all_tax_id_fields(self):
269
- self.ensure_one()
270
- taxes = self.env["l10n_br_fiscal.tax"]
271
-
272
- for fiscal_tax_field in FISCAL_TAX_ID_FIELDS:
273
- taxes |= self[fiscal_tax_field]
274
-
275
- return taxes
276
-
277
- def _remove_all_fiscal_tax_ids(self):
278
- for line in self:
279
- to_update = {"fiscal_tax_ids": False}
280
- for fiscal_tax_field in FISCAL_TAX_ID_FIELDS:
281
- to_update[fiscal_tax_field] = False
282
- tax_methods = [
283
- self._prepare_fields_issqn,
284
- self._prepare_fields_csll,
285
- self._prepare_fields_irpj,
286
- self._prepare_fields_inss,
287
- self._prepare_fields_icms,
288
- self._prepare_fields_icmsfcp,
289
- self._prepare_fields_icmsfcpst,
290
- self._prepare_fields_icmsst,
291
- self._prepare_fields_icmssn,
292
- self._prepare_fields_ipi,
293
- self._prepare_fields_ii,
294
- self._prepare_fields_pis,
295
- self._prepare_fields_pisst,
296
- self._prepare_fields_cofins,
297
- self._prepare_fields_cofinsst,
298
- self._prepare_fields_issqn_wh,
299
- self._prepare_fields_pis_wh,
300
- self._prepare_fields_cofins_wh,
301
- self._prepare_fields_csll_wh,
302
- self._prepare_fields_irpj_wh,
303
- self._prepare_fields_inss_wh,
304
- ]
305
- for method in tax_methods:
306
- prepared_fields = method(TAX_DICT_VALUES)
307
- if prepared_fields:
308
- to_update.update(prepared_fields)
309
- # Update all fields at once
310
- line.update(to_update)
311
-
312
- def _update_fiscal_tax_ids(self, taxes):
313
- for line in self:
314
- taxes_groups = line.fiscal_tax_ids.mapped("tax_domain")
315
- fiscal_taxes = line.fiscal_tax_ids.filtered(
316
- lambda ft, taxes_groups=taxes_groups: ft.tax_domain not in taxes_groups
317
- )
318
- line.fiscal_tax_ids = fiscal_taxes + taxes
319
-
320
- def _update_fiscal_taxes(self):
321
- for line in self:
322
- compute_result = self._compute_taxes(line.fiscal_tax_ids)
323
- to_update = {
324
- "amount_tax_included": compute_result.get("amount_included", 0.0),
325
- "amount_tax_not_included": compute_result.get(
326
- "amount_not_included", 0.0
327
- ),
328
- "amount_tax_withholding": compute_result.get("amount_withholding", 0.0),
329
- "estimate_tax": compute_result.get("estimate_tax", 0.0),
330
- }
331
- to_update.update(line._prepare_tax_fields(compute_result))
332
-
333
- in_draft_mode = self != self._origin
334
- if in_draft_mode:
335
- line.update(to_update)
336
- else:
337
- line.write(to_update)
338
-
339
- def _prepare_tax_fields(self, compute_result):
340
- self.ensure_one()
341
- computed_taxes = compute_result.get("taxes", {})
342
- tax_values = {}
343
- for tax in self.fiscal_tax_ids:
344
- computed_tax = computed_taxes.get(tax.tax_domain, {})
345
- tax_field_name = f"{tax.tax_domain}_tax_id"
346
- if hasattr(self, tax_field_name):
347
- tax_values[tax_field_name] = tax.ids[0]
348
- method = getattr(self, f"_prepare_fields_{tax.tax_domain}", None)
349
- if method and computed_tax:
350
- prepared_fields = method(computed_tax)
351
- if prepared_fields:
352
- tax_values.update(prepared_fields)
353
- return tax_values
354
-
355
- def _get_product_price(self):
356
- self.ensure_one()
357
- price = {
358
- "sale_price": self.product_id.list_price,
359
- "cost_price": self.product_id.standard_price,
360
- }
361
-
362
- self.price_unit = price.get(self.fiscal_operation_id.default_price_unit, 0.00)
363
-
364
- def __document_comment_vals(self):
365
- self.ensure_one()
366
- return {
367
- "user": self.env.user,
368
- "ctx": self._context,
369
- "doc": self.document_id,
370
- "item": self,
371
- }
372
-
373
- def _document_comment(self):
374
- for d in self:
375
- d.additional_data = d.comment_ids.compute_message(
376
- d.__document_comment_vals(), d.manual_additional_data
377
- )
378
-
379
- def _get_fiscal_partner(self):
380
- """
381
- Meant to be overriden when the l10n_br_fiscal.document partner_id should not
382
- be the same as the sale.order, purchase.order, account.move (...) partner_id.
383
-
384
- (In the case of invoicing, the invoicing partner set by the user should
385
- get priority over any invoicing contact returned by address_get.)
386
- """
387
- self.ensure_one()
388
- return self.partner_id
389
-
390
- @api.onchange(
391
- "fiscal_operation_id", "ncm_id", "nbs_id", "cest_id", "service_type_id"
392
- )
393
- def _onchange_fiscal_operation_id(self):
394
- if self.fiscal_operation_id:
395
- if not self.price_unit:
396
- self._get_product_price()
397
- self._onchange_commercial_quantity()
398
- self.fiscal_operation_line_id = self.fiscal_operation_id.line_definition(
399
- company=self.company_id,
400
- partner=self._get_fiscal_partner(),
401
- product=self.product_id,
402
- )
403
- self._onchange_fiscal_operation_line_id()
404
-
405
- @api.onchange("fiscal_operation_line_id")
406
- def _onchange_fiscal_operation_line_id(self):
407
- # Reset Taxes
408
- self._remove_all_fiscal_tax_ids()
409
- if self.fiscal_operation_line_id:
410
- mapping_result = self.fiscal_operation_line_id.map_fiscal_taxes(
411
- company=self.company_id,
412
- partner=self._get_fiscal_partner(),
413
- product=self.product_id,
414
- ncm=self.ncm_id,
415
- nbm=self.nbm_id,
416
- nbs=self.nbs_id,
417
- cest=self.cest_id,
418
- city_taxation_code=self.city_taxation_code_id,
419
- service_type=self.service_type_id,
420
- ind_final=self.ind_final,
421
- )
422
-
423
- self.cfop_id = mapping_result["cfop"]
424
- self._process_fiscal_mapping(mapping_result)
425
-
426
- if not self.fiscal_operation_line_id:
427
- self.cfop_id = False
428
-
429
- def _process_fiscal_mapping(self, mapping_result):
430
- self.ipi_guideline_id = mapping_result["ipi_guideline"]
431
- self.icms_tax_benefit_id = mapping_result["icms_tax_benefit_id"]
432
- taxes = self.env["l10n_br_fiscal.tax"]
433
- for tax in mapping_result["taxes"].values():
434
- taxes |= tax
435
- self.fiscal_tax_ids = taxes
436
- self._update_fiscal_taxes()
437
- self.comment_ids = self.fiscal_operation_line_id.comment_ids
438
-
439
- @api.onchange("product_id")
440
- def _onchange_product_id_fiscal(self):
441
- if not self.fiscal_operation_id:
442
- return
443
- if self.product_id:
444
- self.name = self.product_id.display_name
445
- self.fiscal_type = self.product_id.fiscal_type
446
- self.uom_id = self.product_id.uom_id
447
- self.ncm_id = self.product_id.ncm_id
448
- self.nbm_id = self.product_id.nbm_id
449
- self.tax_icms_or_issqn = self.product_id.tax_icms_or_issqn
450
- self.icms_origin = self.product_id.icms_origin
451
- self.cest_id = self.product_id.cest_id
452
- self.nbs_id = self.product_id.nbs_id
453
- self.fiscal_genre_id = self.product_id.fiscal_genre_id
454
- self.service_type_id = self.product_id.service_type_id
455
- self.uot_id = self.product_id.uot_id or self.product_id.uom_id
456
- if self.product_id.city_taxation_code_id:
457
- company_city_id = self.company_id.city_id
458
- city_id = self.product_id.city_taxation_code_id.filtered(
459
- lambda r: r.city_id == company_city_id
460
- )
461
- if city_id:
462
- self.city_taxation_code_id = city_id
463
- self.issqn_fg_city_id = company_city_id
464
- else:
465
- self.name = False
466
- self.fiscal_type = False
467
- self.uom_id = False
468
- self.ncm_id = False
469
- self.nbm_id = False
470
- self.tax_icms_or_issqn = False
471
- self.icms_origin = False
472
- self.cest_id = False
473
- self.nbs_id = False
474
- self.fiscal_genre_id = False
475
- self.service_type_id = False
476
- self.city_taxation_code_id = False
477
- self.uot_id = False
478
-
479
- self._get_product_price()
480
- self._onchange_fiscal_operation_id()
481
-
482
- def _prepare_fields_issqn(self, tax_dict):
483
- self.ensure_one()
484
- return {
485
- "issqn_base": tax_dict.get("base"),
486
- "issqn_percent": tax_dict.get("percent_amount"),
487
- "issqn_reduction": tax_dict.get("percent_reduction"),
488
- "issqn_value": tax_dict.get("tax_value"),
489
- }
490
-
491
- def _prepare_fields_issqn_wh(self, tax_dict):
492
- self.ensure_one()
493
- return {
494
- "issqn_wh_base": tax_dict.get("base"),
495
- "issqn_wh_percent": tax_dict.get("percent_amount"),
496
- "issqn_wh_reduction": tax_dict.get("percent_reduction"),
497
- "issqn_wh_value": tax_dict.get("tax_value"),
498
- }
499
-
500
- def _prepare_fields_csll(self, tax_dict):
501
- self.ensure_one()
502
- return {
503
- "csll_base": tax_dict.get("base"),
504
- "csll_percent": tax_dict.get("percent_amount"),
505
- "csll_reduction": tax_dict.get("percent_reduction"),
506
- "csll_value": tax_dict.get("tax_value"),
507
- }
508
-
509
- def _prepare_fields_csll_wh(self, tax_dict):
510
- self.ensure_one()
511
- return {
512
- "csll_wh_base": tax_dict.get("base"),
513
- "csll_wh_percent": tax_dict.get("percent_amount"),
514
- "csll_wh_reduction": tax_dict.get("percent_reduction"),
515
- "csll_wh_value": tax_dict.get("tax_value"),
516
- }
517
-
518
- def _prepare_fields_irpj(self, tax_dict):
519
- self.ensure_one()
520
- return {
521
- "irpj_base": tax_dict.get("base"),
522
- "irpj_percent": tax_dict.get("percent_amount"),
523
- "irpj_reduction": tax_dict.get("percent_reduction"),
524
- "irpj_value": tax_dict.get("tax_value"),
525
- }
526
-
527
- def _prepare_fields_irpj_wh(self, tax_dict):
528
- self.ensure_one()
529
- return {
530
- "irpj_wh_base": tax_dict.get("base"),
531
- "irpj_wh_percent": tax_dict.get("percent_amount"),
532
- "irpj_wh_reduction": tax_dict.get("percent_reduction"),
533
- "irpj_wh_value": tax_dict.get("tax_value"),
534
- }
535
-
536
- def _prepare_fields_inss(self, tax_dict):
537
- self.ensure_one()
538
- return {
539
- "inss_base": tax_dict.get("base"),
540
- "inss_percent": tax_dict.get("percent_amount"),
541
- "inss_reduction": tax_dict.get("percent_reduction"),
542
- "inss_value": tax_dict.get("tax_value"),
543
- }
544
-
545
- def _prepare_fields_inss_wh(self, tax_dict):
546
- self.ensure_one()
547
- return {
548
- "inss_wh_base": tax_dict.get("base"),
549
- "inss_wh_percent": tax_dict.get("percent_amount"),
550
- "inss_wh_reduction": tax_dict.get("percent_reduction"),
551
- "inss_wh_value": tax_dict.get("tax_value"),
552
- }
553
-
554
- def _prepare_fields_icms(self, tax_dict):
555
- self.ensure_one()
556
- cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
557
- return {
558
- "icms_cst_id": cst_id,
559
- "icms_base_type": tax_dict.get("icms_base_type", ICMS_BASE_TYPE_DEFAULT),
560
- "icms_base": tax_dict.get("base", 0.0),
561
- "icms_percent": tax_dict.get("percent_amount", 0.0),
562
- "icms_reduction": tax_dict.get("percent_reduction", 0.0),
563
- "icms_value": tax_dict.get("tax_value", 0.0),
564
- "icms_origin_percent": tax_dict.get("icms_origin_perc", 0.0),
565
- "icms_destination_percent": tax_dict.get("icms_dest_perc", 0.0),
566
- "icms_sharing_percent": tax_dict.get("icms_sharing_percent", 0.0),
567
- "icms_destination_base": tax_dict.get("icms_dest_base", 0.0),
568
- "icms_origin_value": tax_dict.get("icms_origin_value", 0.0),
569
- "icms_destination_value": tax_dict.get("icms_dest_value", 0.0),
570
- "icms_relief_value": tax_dict.get("icms_relief", 0.0),
571
- }
572
-
573
- @api.onchange(
574
- "icms_base",
575
- "icms_percent",
576
- "icms_reduction",
577
- "icms_value",
578
- "icms_destination_base",
579
- "icms_origin_percent",
580
- "icms_destination_percent",
581
- "icms_sharing_percent",
582
- "icms_origin_value",
583
- "icms_tax_benefit_id",
584
- )
585
- def _onchange_icms_fields(self):
586
- if self.icms_tax_benefit_id:
587
- self.icms_tax_id = self.icms_tax_benefit_id.tax_id
588
-
589
- def _prepare_fields_icmssn(self, tax_dict):
590
- self.ensure_one()
591
- cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
592
- icmssn_base = tax_dict.get("base", 0.0)
593
- icmssn_credit_value = tax_dict.get("tax_value", 0.0)
594
- simple_value = icmssn_base * self.icmssn_range_id.total_tax_percent
595
- simple_without_icms_value = simple_value - icmssn_credit_value
596
- return {
597
- "icms_cst_id": cst_id,
598
- "icmssn_base": icmssn_base,
599
- "icmssn_percent": tax_dict.get("percent_amount"),
600
- "icmssn_reduction": tax_dict.get("percent_reduction"),
601
- "icmssn_credit_value": icmssn_credit_value,
602
- "simple_value": simple_value,
603
- "simple_without_icms_value": simple_without_icms_value,
604
- }
605
-
606
- def _prepare_fields_icmsst(self, tax_dict):
607
- self.ensure_one()
608
- return {
609
- "icmsst_base_type": tax_dict.get(
610
- "icmsst_base_type", ICMS_ST_BASE_TYPE_DEFAULT
611
- ),
612
- "icmsst_mva_percent": tax_dict.get("icmsst_mva_percent"),
613
- "icmsst_percent": tax_dict.get("percent_amount"),
614
- "icmsst_reduction": tax_dict.get("percent_reduction"),
615
- "icmsst_base": tax_dict.get("base"),
616
- "icmsst_value": tax_dict.get("tax_value"),
617
- }
618
-
619
- def _prepare_fields_icmsfcp(self, tax_dict):
620
- self.ensure_one()
621
- return {
622
- "icmsfcp_base": tax_dict.get("base", 0.0),
623
- "icmsfcp_percent": tax_dict.get("percent_amount", 0.0),
624
- "icmsfcp_value": tax_dict.get("tax_value", 0.0),
625
- }
626
-
627
- def _prepare_fields_icmsfcpst(self, tax_dict):
628
- self.ensure_one()
629
- return {
630
- "icmsfcpst_base": self.icmsst_base,
631
- "icmsfcpst_percent": tax_dict.get("percent_amount", 0.0),
632
- "icmsfcpst_value": tax_dict.get("tax_value", 0.0),
633
- }
634
-
635
- def _prepare_fields_ipi(self, tax_dict):
636
- self.ensure_one()
637
- cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
638
- return {
639
- "ipi_cst_id": cst_id,
640
- "ipi_base_type": tax_dict.get("base_type", False),
641
- "ipi_base": tax_dict.get("base", 0.00),
642
- "ipi_percent": tax_dict.get("percent_amount", 0.00),
643
- "ipi_reduction": tax_dict.get("percent_reduction", 0.00),
644
- "ipi_value": tax_dict.get("tax_value", 0.00),
645
- }
646
-
647
- def _prepare_fields_ii(self, tax_dict):
648
- self.ensure_one()
649
- return {
650
- "ii_base": tax_dict.get("base", 0.00),
651
- "ii_percent": tax_dict.get("percent_amount", 0.00),
652
- "ii_value": tax_dict.get("tax_value", 0.00),
653
- }
654
-
655
- def _prepare_fields_pis(self, tax_dict):
656
- self.ensure_one()
657
- cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
658
- return {
659
- "pis_cst_id": cst_id,
660
- "pis_base_type": tax_dict.get("base_type"),
661
- "pis_base": tax_dict.get("base", 0.00),
662
- "pis_percent": tax_dict.get("percent_amount", 0.00),
663
- "pis_reduction": tax_dict.get("percent_reduction", 0.00),
664
- "pis_value": tax_dict.get("tax_value", 0.00),
665
- }
666
-
667
- def _prepare_fields_pis_wh(self, tax_dict):
668
- self.ensure_one()
669
- return {
670
- "pis_wh_base_type": tax_dict.get("base_type"),
671
- "pis_wh_base": tax_dict.get("base", 0.00),
672
- "pis_wh_percent": tax_dict.get("percent_amount", 0.00),
673
- "pis_wh_reduction": tax_dict.get("percent_reduction", 0.00),
674
- "pis_wh_value": tax_dict.get("tax_value", 0.00),
675
- }
676
-
677
- def _prepare_fields_pisst(self, tax_dict):
678
- self.ensure_one()
679
- cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
680
- return {
681
- "pisst_cst_id": cst_id,
682
- "pisst_base_type": tax_dict.get("base_type"),
683
- "pisst_base": tax_dict.get("base", 0.00),
684
- "pisst_percent": tax_dict.get("percent_amount", 0.00),
685
- "pisst_reduction": tax_dict.get("percent_reduction", 0.00),
686
- "pisst_value": tax_dict.get("tax_value", 0.00),
687
- }
688
-
689
- def _prepare_fields_cofins(self, tax_dict):
690
- self.ensure_one()
691
- cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
692
- return {
693
- "cofins_cst_id": cst_id,
694
- "cofins_base_type": tax_dict.get("base_type"),
695
- "cofins_base": tax_dict.get("base", 0.00),
696
- "cofins_percent": tax_dict.get("percent_amount", 0.00),
697
- "cofins_reduction": tax_dict.get("percent_reduction", 0.00),
698
- "cofins_value": tax_dict.get("tax_value", 0.00),
699
- }
700
-
701
- def _prepare_fields_cofins_wh(self, tax_dict):
702
- self.ensure_one()
703
- return {
704
- "cofins_wh_base_type": tax_dict.get("base_type"),
705
- "cofins_wh_base": tax_dict.get("base", 0.00),
706
- "cofins_wh_percent": tax_dict.get("percent_amount", 0.00),
707
- "cofins_wh_reduction": tax_dict.get("percent_reduction", 0.00),
708
- "cofins_wh_value": tax_dict.get("tax_value", 0.00),
709
- }
710
-
711
- def _prepare_fields_cofinsst(self, tax_dict):
712
- self.ensure_one()
713
- cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
714
- return {
715
- "cofinsst_cst_id": cst_id,
716
- "cofinsst_base_type": tax_dict.get("base_type"),
717
- "cofinsst_base": tax_dict.get("base", 0.00),
718
- "cofinsst_percent": tax_dict.get("percent_amount", 0.00),
719
- "cofinsst_reduction": tax_dict.get("percent_reduction", 0.00),
720
- "cofinsst_value": tax_dict.get("tax_value", 0.00),
721
- }
722
-
723
- @api.onchange(
724
- "csll_tax_id",
725
- "csll_wh_tax_id",
726
- "irpj_tax_id",
727
- "irpj_wh_tax_id",
728
- "inss_tax_id",
729
- "inss_wh_tax_id",
730
- "issqn_tax_id",
731
- "issqn_wh_tax_id",
732
- "icms_tax_id",
733
- "icmssn_tax_id",
734
- "icmsst_tax_id",
735
- "icmsfcp_tax_id",
736
- "icmsfcpst_tax_id",
737
- "icms_relief_id",
738
- "icms_relief_value",
739
- "ipi_tax_id",
740
- "ii_tax_id",
741
- "pis_tax_id",
742
- "pis_wh_tax_id",
743
- "pisst_tax_id",
744
- "cofins_tax_id",
745
- "cofins_wh_tax_id",
746
- "cofinsst_tax_id",
747
- "fiscal_price",
748
- "fiscal_quantity",
749
- "discount_value",
750
- "insurance_value",
751
- "other_value",
752
- "freight_value",
753
- )
754
- def _onchange_fiscal_taxes(self):
755
- self._update_fiscal_tax_ids(self._get_all_tax_id_fields())
756
- self._update_fiscal_taxes()
757
-
758
- @api.model
759
- def _update_fiscal_quantity(self, product_id, price, quantity, uom_id, uot_id):
760
- result = {"uot_id": uom_id, "fiscal_quantity": quantity, "fiscal_price": price}
761
- if uot_id and uom_id != uot_id:
762
- result["uot_id"] = uot_id
763
- if product_id and price and quantity:
764
- product = self.env["product.product"].browse(product_id)
765
- result["fiscal_price"] = price / (product.uot_factor or 1.0)
766
- result["fiscal_quantity"] = quantity * (product.uot_factor or 1.0)
767
-
768
- return result
769
-
770
- @api.onchange("uot_id", "uom_id", "price_unit", "quantity")
771
- def _onchange_commercial_quantity(self):
772
- product_id = False
773
- if self.product_id:
774
- product_id = self.product_id.id
775
- self.update(
776
- self._update_fiscal_quantity(
777
- product_id, self.price_unit, self.quantity, self.uom_id, self.uot_id
778
- )
779
- )
780
-
781
- @api.onchange("ii_customhouse_charges")
782
- def _onchange_ii_customhouse_charges(self):
783
- if self.ii_customhouse_charges:
784
- self._update_fiscal_taxes()
785
-
786
- @api.onchange("fiscal_tax_ids")
787
- def _onchange_fiscal_tax_ids(self):
788
- self._update_fiscal_taxes()
789
-
790
- @api.onchange("city_taxation_code_id")
791
- def _onchange_city_taxation_code_id(self):
792
- if self.city_taxation_code_id:
793
- self.cnae_id = self.city_taxation_code_id.cnae_id
794
- self._onchange_fiscal_operation_id()
795
- if self.city_taxation_code_id.city_id:
796
- self.update({"issqn_fg_city_id": self.city_taxation_code_id.city_id})
797
-
798
- @api.model
799
- def _add_fields_to_amount(self):
800
- fields_to_amount = ["insurance_value", "other_value", "freight_value"]
801
- if (
802
- self.cfop_id.destination == CFOP_DESTINATION_EXPORT
803
- and self.fiscal_operation_id.fiscal_operation_type == FISCAL_IN
804
- ):
805
- fields_to_amount.append("pis_value")
806
- fields_to_amount.append("cofins_value")
807
- fields_to_amount.append("icms_value")
808
- fields_to_amount.append("ii_value")
809
- fields_to_amount.append("ii_customhouse_charges")
810
- return fields_to_amount
811
-
812
- @api.model
813
- def _rm_fields_to_amount(self):
814
- return ["icms_relief_value"]