odoo-addon-l10n-br-fiscal 16.0.2.17.0__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 (162) hide show
  1. odoo/addons/l10n_br_fiscal/README.rst +11 -4
  2. odoo/addons/l10n_br_fiscal/__manifest__.py +20 -12
  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.cfop.csv +620 -620
  6. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cst.csv +58 -0
  7. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.document.type.csv +1 -0
  8. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.legal.nature.csv +82 -0
  9. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.nbs.csv +791 -764
  10. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.operation.indicator.csv +27 -0
  11. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.partner.profile.csv +11 -0
  12. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.classification.csv +163 -0
  13. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.csv +32 -0
  14. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.group.csv +3 -0
  15. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal_icms_tax_definition_data.xml +340 -352
  16. odoo/addons/l10n_br_fiscal/data/operation_data.xml +1 -1
  17. odoo/addons/l10n_br_fiscal/data/simplified_tax_data.xml +5 -5
  18. odoo/addons/l10n_br_fiscal/data/uom.alias.csv +25 -0
  19. odoo/addons/l10n_br_fiscal/data/uom_data.xml +104 -33
  20. odoo/addons/l10n_br_fiscal/demo/__init__.py +21 -15
  21. odoo/addons/l10n_br_fiscal/demo/company_demo.xml +6 -0
  22. odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +3 -377
  23. odoo/addons/l10n_br_fiscal/demo/fiscal_document_nfse_demo.xml +0 -12
  24. odoo/addons/l10n_br_fiscal/demo/fiscal_operation_demo.xml +2 -2
  25. odoo/addons/l10n_br_fiscal/demo/icms_tax_definition_demo.xml +5 -2
  26. odoo/addons/l10n_br_fiscal/demo/res_users_demo.xml +2 -2
  27. odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +1161 -804
  28. odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +22 -22
  29. odoo/addons/l10n_br_fiscal/migrations/16.0.13.0.0/pre-migration.py +25 -0
  30. odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.0/pre-migration.py +30 -0
  31. odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.5/pre-migration.py +15 -0
  32. odoo/addons/l10n_br_fiscal/migrations/16.0.4.0.0/pre-migration.py +220 -0
  33. odoo/addons/l10n_br_fiscal/migrations/16.0.5.0.0/pre-migration.py +33 -0
  34. odoo/addons/l10n_br_fiscal/migrations/16.0.5.2.0/pre-migration.py +21 -0
  35. odoo/addons/l10n_br_fiscal/models/__init__.py +3 -8
  36. odoo/addons/l10n_br_fiscal/models/cest.py +0 -8
  37. odoo/addons/l10n_br_fiscal/models/cfop.py +91 -0
  38. odoo/addons/l10n_br_fiscal/models/city_taxation_code.py +1 -3
  39. odoo/addons/l10n_br_fiscal/models/comment.py +2 -2
  40. odoo/addons/l10n_br_fiscal/models/cst.py +0 -1
  41. odoo/addons/l10n_br_fiscal/models/data_abstract.py +26 -0
  42. odoo/addons/l10n_br_fiscal/models/data_ncm_nbs_abstract.py +1 -1
  43. odoo/addons/l10n_br_fiscal/models/document.py +131 -222
  44. odoo/addons/l10n_br_fiscal/models/document_line.py +82 -5
  45. odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +1952 -138
  46. odoo/addons/l10n_br_fiscal/models/document_mixin.py +741 -6
  47. odoo/addons/l10n_br_fiscal/models/document_related.py +12 -9
  48. odoo/addons/l10n_br_fiscal/models/document_serie.py +33 -0
  49. odoo/addons/l10n_br_fiscal/models/document_type.py +0 -6
  50. odoo/addons/l10n_br_fiscal/models/ibpt.py +1 -1
  51. odoo/addons/l10n_br_fiscal/models/icms_regulation.py +2 -2
  52. odoo/addons/l10n_br_fiscal/models/invalidate_number.py +4 -5
  53. odoo/addons/l10n_br_fiscal/models/legal_nature.py +20 -0
  54. odoo/addons/l10n_br_fiscal/models/nbm.py +0 -8
  55. odoo/addons/l10n_br_fiscal/models/ncm.py +0 -12
  56. odoo/addons/l10n_br_fiscal/models/operation.py +49 -15
  57. odoo/addons/l10n_br_fiscal/models/operation_dashboard.py +3 -2
  58. odoo/addons/l10n_br_fiscal/models/operation_indicator.py +58 -0
  59. odoo/addons/l10n_br_fiscal/models/operation_line.py +75 -6
  60. odoo/addons/l10n_br_fiscal/models/partner_profile.py +6 -0
  61. odoo/addons/l10n_br_fiscal/models/product_mixin.py +24 -21
  62. odoo/addons/l10n_br_fiscal/models/product_template.py +23 -13
  63. odoo/addons/l10n_br_fiscal/models/res_company.py +31 -9
  64. odoo/addons/l10n_br_fiscal/models/res_partner.py +38 -6
  65. odoo/addons/l10n_br_fiscal/models/simplified_tax.py +0 -3
  66. odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +8 -0
  67. odoo/addons/l10n_br_fiscal/models/tax.py +144 -55
  68. odoo/addons/l10n_br_fiscal/models/tax_classification.py +81 -0
  69. odoo/addons/l10n_br_fiscal/models/tax_definition.py +72 -23
  70. odoo/addons/l10n_br_fiscal/models/tax_pis_cofins.py +0 -3
  71. odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_base.py +1 -1
  72. odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_credit.py +1 -1
  73. odoo/addons/l10n_br_fiscal/models/uom_uom.py +15 -30
  74. odoo/addons/l10n_br_fiscal/security/fiscal_security.xml +11 -27
  75. odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +11 -10
  76. odoo/addons/l10n_br_fiscal/static/description/index.html +27 -21
  77. odoo/addons/l10n_br_fiscal/static/src/js/list_renderer_with_button.esm.js +38 -0
  78. odoo/addons/l10n_br_fiscal/tests/__init__.py +3 -2
  79. odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +308 -0
  80. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +23 -129
  81. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +5 -15
  82. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_serie.py +60 -0
  83. odoo/addons/l10n_br_fiscal/tests/test_ibpt.py +4 -3
  84. odoo/addons/l10n_br_fiscal/tests/test_icms_regulation.py +2 -2
  85. odoo/addons/l10n_br_fiscal/tests/test_ncm.py +4 -1
  86. odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +17 -22
  87. odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +110 -0
  88. odoo/addons/l10n_br_fiscal/tools.py +1 -1
  89. odoo/addons/l10n_br_fiscal/views/cest_view.xml +2 -4
  90. odoo/addons/l10n_br_fiscal/views/cfop_view.xml +25 -5
  91. odoo/addons/l10n_br_fiscal/views/city_taxation_code.xml +1 -4
  92. odoo/addons/l10n_br_fiscal/views/cnae_view.xml +2 -4
  93. odoo/addons/l10n_br_fiscal/views/comment_view.xml +2 -4
  94. odoo/addons/l10n_br_fiscal/views/cst_view.xml +6 -8
  95. odoo/addons/l10n_br_fiscal/views/{document_fiscal_line_mixin_view.xml → document_line_mixin_view.xml} +525 -385
  96. odoo/addons/l10n_br_fiscal/views/document_line_view.xml +101 -82
  97. odoo/addons/l10n_br_fiscal/views/document_related_view.xml +44 -46
  98. odoo/addons/l10n_br_fiscal/views/document_serie_view.xml +2 -6
  99. odoo/addons/l10n_br_fiscal/views/document_type_view.xml +0 -8
  100. odoo/addons/l10n_br_fiscal/views/document_view.xml +303 -370
  101. odoo/addons/l10n_br_fiscal/views/icms_regulation_view.xml +14 -16
  102. odoo/addons/l10n_br_fiscal/views/icms_relief_view.xml +8 -10
  103. odoo/addons/l10n_br_fiscal/views/invalidate_number_view.xml +46 -48
  104. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +166 -280
  105. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +25 -99
  106. odoo/addons/l10n_br_fiscal/views/legal_nature_view.xml +40 -0
  107. odoo/addons/l10n_br_fiscal/views/nbm_view.xml +5 -6
  108. odoo/addons/l10n_br_fiscal/views/nbs_view.xml +5 -6
  109. odoo/addons/l10n_br_fiscal/views/ncm_view.xml +12 -15
  110. odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +13 -12
  111. odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +75 -0
  112. odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +22 -21
  113. odoo/addons/l10n_br_fiscal/views/operation_view.xml +4 -19
  114. odoo/addons/l10n_br_fiscal/views/partner_profile_view.xml +3 -6
  115. odoo/addons/l10n_br_fiscal/views/product_genre_view.xml +7 -9
  116. odoo/addons/l10n_br_fiscal/views/product_product_view.xml +37 -14
  117. odoo/addons/l10n_br_fiscal/views/product_template_view.xml +34 -14
  118. odoo/addons/l10n_br_fiscal/views/res_company_view.xml +55 -52
  119. odoo/addons/l10n_br_fiscal/views/res_config_settings_view.xml +23 -28
  120. odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +22 -2
  121. odoo/addons/l10n_br_fiscal/views/service_type_view.xml +7 -8
  122. odoo/addons/l10n_br_fiscal/views/simplified_tax_range_view.xml +0 -2
  123. odoo/addons/l10n_br_fiscal/views/simplified_tax_view.xml +0 -2
  124. odoo/addons/l10n_br_fiscal/views/tax_classification.xml +110 -0
  125. odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +157 -129
  126. odoo/addons/l10n_br_fiscal/views/tax_estimate_view.xml +0 -2
  127. odoo/addons/l10n_br_fiscal/views/tax_group_view.xml +3 -6
  128. odoo/addons/l10n_br_fiscal/views/tax_ipi_control_seal_view.xml +0 -2
  129. odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_class_view.xml +0 -2
  130. odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_view.xml +2 -4
  131. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_base_view.xml +2 -4
  132. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_credit_view.xml +2 -4
  133. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_view.xml +5 -7
  134. odoo/addons/l10n_br_fiscal/views/tax_view.xml +5 -7
  135. odoo/addons/l10n_br_fiscal/views/uom_uom.xml +24 -17
  136. odoo/addons/l10n_br_fiscal/wizards/__init__.py +1 -0
  137. odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +1 -1
  138. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +129 -0
  139. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.xml +41 -0
  140. {odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/METADATA +15 -6
  141. odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info/RECORD +210 -0
  142. {odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/WHEEL +1 -1
  143. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal_email_template.xml +0 -68
  144. odoo/addons/l10n_br_fiscal/data/partner_profile_data.xml +0 -96
  145. odoo/addons/l10n_br_fiscal/data/uom_alternative_data.xml +0 -58
  146. odoo/addons/l10n_br_fiscal/demo/l10n_br_fiscal_document_email.xml +0 -54
  147. odoo/addons/l10n_br_fiscal/demo/subsequent_operation_demo.xml +0 -10
  148. odoo/addons/l10n_br_fiscal/models/document_email.py +0 -74
  149. odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +0 -913
  150. odoo/addons/l10n_br_fiscal/models/document_mixin_fields.py +0 -473
  151. odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +0 -269
  152. odoo/addons/l10n_br_fiscal/models/document_move_mixin.py +0 -261
  153. odoo/addons/l10n_br_fiscal/models/subsequent_document.py +0 -203
  154. odoo/addons/l10n_br_fiscal/models/subsequent_operation.py +0 -54
  155. odoo/addons/l10n_br_fiscal/models/uom_uom_alternative.py +0 -22
  156. odoo/addons/l10n_br_fiscal/tests/test_subsequent_operation.py +0 -71
  157. odoo/addons/l10n_br_fiscal/tests/test_uom_uom.py +0 -22
  158. odoo/addons/l10n_br_fiscal/views/document_email_view.xml +0 -48
  159. odoo/addons/l10n_br_fiscal/views/subsequent_document_view.xml +0 -43
  160. odoo/addons/l10n_br_fiscal/views/subsequent_operation_view.xml +0 -21
  161. odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info/RECORD +0 -205
  162. {odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/top_level.txt +0 -0
@@ -1,18 +1,29 @@
1
1
  # Copyright (C) 2019 Renato Lima - Akretion <renato.lima@akretion.com.br>
2
2
  # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
3
3
 
4
- from odoo import api, fields, models
4
+ from copy import deepcopy
5
+
6
+ from lxml import etree
7
+ from lxml.builder import E
8
+
9
+ from odoo import Command, api, fields, models
5
10
 
6
11
  from ..constants.fiscal import (
12
+ CFOP_DESTINATION_EXPORT,
13
+ FINAL_CUSTOMER,
7
14
  FISCAL_COMMENT_LINE,
15
+ FISCAL_IN,
16
+ FISCAL_TAX_ID_FIELDS,
8
17
  PRODUCT_FISCAL_TYPE,
9
18
  TAX_BASE_TYPE,
10
19
  TAX_BASE_TYPE_PERCENT,
20
+ TAX_DOMAIN_CBS,
11
21
  TAX_DOMAIN_COFINS,
12
22
  TAX_DOMAIN_COFINS_ST,
13
23
  TAX_DOMAIN_COFINS_WH,
14
24
  TAX_DOMAIN_CSLL,
15
25
  TAX_DOMAIN_CSLL_WH,
26
+ TAX_DOMAIN_IBS,
16
27
  TAX_DOMAIN_ICMS,
17
28
  TAX_DOMAIN_ICMS_FCP,
18
29
  TAX_DOMAIN_ICMS_FCP_ST,
@@ -49,14 +60,28 @@ from ..constants.issqn import (
49
60
 
50
61
 
51
62
  class FiscalDocumentLineMixin(models.AbstractModel):
63
+ """
64
+ Provides the primary field structure for Brazilian fiscal document lines.
65
+
66
+ It is inherited by sale.order.line, purchase.order.linne, account.move.line
67
+ and even stock.move in separate modules.
68
+ Indeed these business documents need to take care of some fiscal parameters
69
+ before creating Fiscal Document Lines. And of course,
70
+ Fiscal Document Lines themselves inherit from this mixin.
71
+
72
+ This abstract model defines an extensive set of fields necessary for
73
+ line-item fiscal calculations and reporting in Brazil. It includes:
74
+ - Product and quantity information.
75
+ - Detailed fiscal classifications (NCM, CFOP, CEST, etc.).
76
+ - Fields for each specific Brazilian tax (ICMS, IPI, PIS, COFINS,
77
+ ISSQN, etc.), covering their respective bases, rates, and
78
+ calculated values.
79
+ - Line-level totals and cost components.
80
+ """
81
+
52
82
  _name = "l10n_br_fiscal.document.line.mixin"
53
- _inherit = "l10n_br_fiscal.document.line.mixin.methods"
54
83
  _description = "Document Fiscal Mixin"
55
84
 
56
- @api.model
57
- def _default_operation(self):
58
- return False
59
-
60
85
  @api.model
61
86
  def _default_icmssn_range_id(self):
62
87
  company = self.env.company
@@ -77,6 +102,810 @@ class FiscalDocumentLineMixin(models.AbstractModel):
77
102
  domain = [("state", "=", "approved")]
78
103
  return domain
79
104
 
105
+ @api.model
106
+ def inject_fiscal_fields(
107
+ self,
108
+ doc,
109
+ view_ref="l10n_br_fiscal.document_fiscal_line_mixin_form",
110
+ xpath_mappings=None,
111
+ ):
112
+ """
113
+ Inject common fiscal fields into view placeholder elements.
114
+ Used for invoice line, sale order line, purchase order line...
115
+ """
116
+
117
+ # the list of computed fields we will add to the view when missing
118
+ missing_line_fields = set(
119
+ [
120
+ fname
121
+ for fname, _field in filter(
122
+ lambda item: item[1].compute
123
+ in (
124
+ "_compute_tax_fields",
125
+ "_compute_fiscal_tax_ids",
126
+ "_compute_product_fiscal_fields",
127
+ ),
128
+ self.env["l10n_br_fiscal.document.line.mixin"]._fields.items(),
129
+ )
130
+ ]
131
+ )
132
+
133
+ fiscal_view = self.env.ref(
134
+ "l10n_br_fiscal.document_fiscal_line_mixin_form"
135
+ ).sudo()
136
+ fsc_doc = etree.fromstring(
137
+ fiscal_view.with_context(inherit_branding=True).get_combined_arch()
138
+ )
139
+
140
+ if xpath_mappings is None:
141
+ xpath_mappings = (
142
+ # (placeholder_xpath, fiscal_xpath)
143
+ (".//group[@name='fiscal_fields']", "//group[@name='fiscal_fields']"),
144
+ (".//page[@name='fiscal_taxes']", "//page[@name='fiscal_taxes']"),
145
+ (
146
+ ".//page[@name='fiscal_line_extra_info']",
147
+ "//page[@name='fiscal_line_extra_info']",
148
+ ),
149
+ # these will only collect (invisible) fields for onchanges:
150
+ (
151
+ ".//control[@name='fiscal_fields']...",
152
+ "//group[@name='fiscal_fields']//field",
153
+ ),
154
+ (
155
+ ".//control[@name='fiscal_taxes_fields']...",
156
+ "//page[@name='fiscal_taxes']//field",
157
+ ),
158
+ (
159
+ ".//control[@name='fiscal_line_extra_info_fields']...",
160
+ "//page[@name='fiscal_line_extra_info']//field",
161
+ ),
162
+ )
163
+ for placeholder_xpath, fiscal_xpath in xpath_mappings:
164
+ placeholder_nodes = doc.findall(placeholder_xpath)
165
+ if not placeholder_nodes:
166
+ continue
167
+ fiscal_nodes = fsc_doc.xpath(fiscal_xpath)
168
+ for target_node in placeholder_nodes:
169
+ if len(fiscal_nodes) == 1:
170
+ # replace unique placeholder
171
+ # (deepcopy is required to inject fiscal nodes in possible
172
+ # next places)
173
+ replace_node = deepcopy(fiscal_nodes[0])
174
+ target_node.getparent().replace(target_node, replace_node)
175
+ else:
176
+ # append multiple fields to placeholder container
177
+ existing_fields = [
178
+ e.attrib["name"] for e in target_node if e.tag == "field"
179
+ ]
180
+ for fiscal_node in fiscal_nodes:
181
+ if fiscal_node.attrib["name"] in missing_line_fields:
182
+ missing_line_fields.remove(fiscal_node.attrib["name"])
183
+ if fiscal_node.attrib["name"] in existing_fields:
184
+ continue
185
+ field = deepcopy(fiscal_node)
186
+ if not field.attrib.get("optional"):
187
+ field.attrib["optional"] = "hide"
188
+ target_node.append(field)
189
+ for fname in missing_line_fields:
190
+ if fname not in existing_fields:
191
+ target_node.append(
192
+ E.field(name=fname, string=fname, optional="hide")
193
+ )
194
+ return doc
195
+
196
+ @api.model
197
+ def _get_view(self, view_id=None, view_type="form", **options):
198
+ arch, view = super()._get_view(view_id, view_type, **options)
199
+ if view_type == "form":
200
+ arch = self.inject_fiscal_fields(arch)
201
+ return arch, view
202
+
203
+ @api.depends(
204
+ "discount_value",
205
+ "amount_tax_not_included",
206
+ "amount_tax_withholding",
207
+ "price_unit",
208
+ "quantity",
209
+ "fiscal_operation_line_id",
210
+ "cfop_id",
211
+ "icms_relief_value",
212
+ "insurance_value",
213
+ "other_value",
214
+ "freight_value",
215
+ "pis_value",
216
+ "cofins_value",
217
+ "icms_value",
218
+ "ii_value",
219
+ "ii_customhouse_charges",
220
+ )
221
+ def _compute_fiscal_amounts(self):
222
+ for record in self:
223
+ round_curr = record.currency_id or self.env.ref("base.BRL")
224
+
225
+ # Total value of products or services
226
+ record.price_gross = round_curr.round(record.price_unit * record.quantity)
227
+ record.amount_fiscal = record.price_gross - record.discount_value
228
+ record.fiscal_amount_tax = record.amount_tax_not_included
229
+
230
+ add_to_amount = sum(record[a] for a in record._add_fields_to_amount())
231
+ rm_to_amount = sum(record[r] for r in record._rm_fields_to_amount())
232
+ record.fiscal_amount_untaxed = (
233
+ record.price_gross
234
+ - record.discount_value
235
+ + add_to_amount
236
+ - rm_to_amount
237
+ )
238
+
239
+ # Valor do documento (NF)
240
+ record.fiscal_amount_total = (
241
+ record.fiscal_amount_untaxed + record.fiscal_amount_tax
242
+ )
243
+
244
+ # Valor Liquido (TOTAL + IMPOSTOS - RETENÇÕES)
245
+ record.amount_taxed = (
246
+ record.fiscal_amount_total - record.amount_tax_withholding
247
+ )
248
+
249
+ # Valor do documento (NF) - RETENÇÕES
250
+ record.fiscal_amount_total = record.amount_taxed
251
+
252
+ # Valor financeiro
253
+ if (
254
+ record.fiscal_operation_line_id
255
+ and record.fiscal_operation_line_id.add_to_amount
256
+ and (not record.cfop_id or record.cfop_id.finance_move)
257
+ ):
258
+ record.financial_total = record.amount_taxed
259
+ record.financial_total_gross = (
260
+ record.financial_total + record.discount_value
261
+ )
262
+ record.financial_discount_value = record.discount_value
263
+ else:
264
+ record.financial_total_gross = record.financial_total = 0.0
265
+ record.financial_discount_value = 0.0
266
+
267
+ @api.depends("tax_icms_or_issqn", "partner_id")
268
+ def _compute_allow_csll_irpj(self):
269
+ """Calculates the possibility of 'CSLL' and 'IRPJ' tax charges."""
270
+ for line in self:
271
+ # Determine if 'CSLL' and 'IRPJ' taxes may apply:
272
+ # 1. When providing services (tax_icms_or_issqn == "issqn")
273
+ # 2. When supplying products to public entities (partner_is_public_entity
274
+ # is True)
275
+ if line.tax_icms_or_issqn == "issqn" or line.partner_is_public_entity:
276
+ line.allow_csll_irpj = True # Tax charges may apply
277
+ else:
278
+ line.allow_csll_irpj = False # No tax charges expected
279
+
280
+ def _prepare_br_fiscal_dict(self, default=False):
281
+ self.ensure_one()
282
+ fields = self.env["l10n_br_fiscal.document.line.mixin"]._fields.keys()
283
+
284
+ # we now read the record fiscal fields except the m2m tax:
285
+ vals = self._convert_to_write(self.read(fields)[0])
286
+
287
+ # remove id field to avoid conflicts
288
+ vals.pop("id", None)
289
+
290
+ if default: # in case you want to use new rather than write later
291
+ return {f"default_{k}": vals[k] for k in vals.keys()}
292
+ return vals
293
+
294
+ @api.depends("fiscal_operation_id", "partner_id", "product_id")
295
+ def _compute_fiscal_operation_line_id(self):
296
+ for line in self:
297
+ if line.fiscal_operation_id:
298
+ line.fiscal_operation_line_id = (
299
+ line.fiscal_operation_id.line_definition(
300
+ company=line.company_id,
301
+ partner=line.partner_id,
302
+ product=line.product_id,
303
+ )
304
+ )
305
+
306
+ @api.depends(
307
+ "partner_id",
308
+ "fiscal_operation_line_id",
309
+ "product_id",
310
+ "ncm_id",
311
+ "nbs_id",
312
+ "nbm_id",
313
+ "cest_id",
314
+ "city_taxation_code_id",
315
+ "service_type_id",
316
+ "ind_final",
317
+ )
318
+ def _compute_fiscal_tax_ids(self):
319
+ for line in self:
320
+ if line.fiscal_operation_line_id:
321
+ mapping_result = line.fiscal_operation_line_id.map_fiscal_taxes(
322
+ company=line.company_id,
323
+ partner=line._get_fiscal_partner(),
324
+ product=line.product_id,
325
+ ncm=line.ncm_id,
326
+ nbm=line.nbm_id,
327
+ nbs=line.nbs_id,
328
+ cest=line.cest_id,
329
+ city_taxation_code=line.city_taxation_code_id,
330
+ service_type=line.service_type_id,
331
+ ind_final=line.ind_final,
332
+ )
333
+ line.cfop_id = mapping_result["cfop"]
334
+ line.ipi_guideline_id = mapping_result["ipi_guideline"]
335
+ line.tax_classification_id = mapping_result["tax_classification"]
336
+ line.icms_tax_benefit_id = mapping_result["icms_tax_benefit_id"]
337
+
338
+ if line._is_imported():
339
+ continue
340
+
341
+ taxes = line.env["l10n_br_fiscal.tax"]
342
+ for tax in mapping_result["taxes"].values():
343
+ taxes |= tax
344
+ line.fiscal_tax_ids = taxes
345
+
346
+ @api.depends("fiscal_operation_line_id")
347
+ def _compute_comment_ids(self):
348
+ for line in self:
349
+ line.comment_ids = [
350
+ Command.set(line.fiscal_operation_line_id.comment_ids.ids)
351
+ ]
352
+
353
+ @api.model
354
+ def _build_null_mask_dict(self) -> dict:
355
+ """
356
+ Build a null values mask dict to reset all fiscal fields.
357
+ """
358
+ mask_dict = {
359
+ f[0]: False
360
+ for f in filter(
361
+ lambda f: f[1].compute == "_compute_tax_fields",
362
+ self.env["l10n_br_fiscal.document.line.mixin"]._fields.items(),
363
+ )
364
+ }
365
+ for fiscal_tax_field in FISCAL_TAX_ID_FIELDS:
366
+ mask_dict[fiscal_tax_field] = False
367
+ return mask_dict
368
+
369
+ def write(self, vals):
370
+ res = super().write(vals)
371
+
372
+ # Verifica se algum campo de imposto relevante foi alterado no 'write'
373
+ tax_fields_in_vals = [fld for fld in vals if fld in FISCAL_TAX_ID_FIELDS]
374
+
375
+ if tax_fields_in_vals:
376
+ # Por segurança, sempre recalcula se um campo relevante mudou.
377
+ self._update_fiscal_tax_ids()
378
+
379
+ return res
380
+
381
+ def _update_fiscal_tax_ids(self):
382
+ taxes = self.env["l10n_br_fiscal.tax"]
383
+ for fiscal_tax_field in FISCAL_TAX_ID_FIELDS:
384
+ taxes |= self[fiscal_tax_field]
385
+
386
+ for line in self:
387
+ taxes_groups = line.fiscal_tax_ids.mapped("tax_domain")
388
+ fiscal_taxes = line.fiscal_tax_ids.filtered(
389
+ lambda ft, taxes_groups=taxes_groups: ft.tax_domain not in taxes_groups
390
+ )
391
+ line.fiscal_tax_ids = fiscal_taxes + taxes
392
+
393
+ @api.onchange(*FISCAL_TAX_ID_FIELDS)
394
+ def _onchange_fiscal_taxes(self):
395
+ self._update_fiscal_tax_ids()
396
+
397
+ @api.depends(
398
+ "partner_id",
399
+ "fiscal_tax_ids",
400
+ "product_id",
401
+ "price_unit",
402
+ "quantity",
403
+ "uom_id",
404
+ "fiscal_price",
405
+ "fiscal_quantity",
406
+ "uot_id",
407
+ "discount_value",
408
+ "insurance_value",
409
+ "ii_customhouse_charges",
410
+ "ii_iof_value",
411
+ "other_value",
412
+ "freight_value",
413
+ "ncm_id",
414
+ "nbs_id",
415
+ "nbm_id",
416
+ "cest_id",
417
+ "fiscal_operation_line_id",
418
+ "cfop_id",
419
+ "icmssn_range_id",
420
+ "icms_origin",
421
+ "icms_cst_id",
422
+ "ind_final",
423
+ "icms_relief_id",
424
+ )
425
+ def _compute_tax_fields(self):
426
+ """
427
+ Compute base, percent, value... tax fields for ICMS, IPI, PIS, COFINS... taxes.
428
+ """
429
+ null_mask = None
430
+ for line in self.filtered(lambda line: not line._is_imported()):
431
+ if null_mask is None:
432
+ null_mask = self._build_null_mask_dict()
433
+ to_update = null_mask.copy()
434
+ # prepare with default values
435
+ to_update.update(
436
+ {
437
+ "icms_base_type": ICMS_BASE_TYPE_DEFAULT,
438
+ "icmsst_base_type": ICMS_ST_BASE_TYPE_DEFAULT,
439
+ "ipi_base_type": TAX_BASE_TYPE_PERCENT,
440
+ "cofins_base_type": TAX_BASE_TYPE_PERCENT,
441
+ "cofinsst_base_type": TAX_BASE_TYPE_PERCENT,
442
+ "cofins_wh_base_type": TAX_BASE_TYPE_PERCENT,
443
+ "pis_base_type": TAX_BASE_TYPE_PERCENT,
444
+ "pisst_base_type": TAX_BASE_TYPE_PERCENT,
445
+ "pis_wh_base_type": TAX_BASE_TYPE_PERCENT,
446
+ "cbs_base_type": TAX_BASE_TYPE_PERCENT,
447
+ "ibs_base_type": TAX_BASE_TYPE_PERCENT,
448
+ }
449
+ )
450
+ if line.fiscal_operation_line_id:
451
+ compute_result = line.fiscal_tax_ids.compute_taxes(
452
+ company=line.company_id,
453
+ partner=line._get_fiscal_partner(),
454
+ product=line.product_id,
455
+ price_unit=line.price_unit,
456
+ quantity=line.quantity,
457
+ uom_id=line.uom_id,
458
+ fiscal_price=line.fiscal_price,
459
+ fiscal_quantity=line.fiscal_quantity,
460
+ uot_id=line.uot_id,
461
+ discount_value=line.discount_value,
462
+ insurance_value=line.insurance_value,
463
+ ii_customhouse_charges=line.ii_customhouse_charges,
464
+ ii_iof_value=line.ii_iof_value,
465
+ other_value=line.other_value,
466
+ freight_value=line.freight_value,
467
+ ncm=line.ncm_id,
468
+ nbs=line.nbs_id,
469
+ nbm=line.nbm_id,
470
+ cest=line.cest_id,
471
+ operation_line=line.fiscal_operation_line_id,
472
+ cfop=line.cfop_id,
473
+ icmssn_range=line.icmssn_range_id,
474
+ icms_origin=line.icms_origin,
475
+ icms_cst_id=line.icms_cst_id,
476
+ ind_final=line.ind_final,
477
+ icms_relief_id=line.icms_relief_id,
478
+ )
479
+ to_update.update(line._prepare_tax_fields(compute_result))
480
+ else:
481
+ compute_result = {}
482
+ to_update.update(
483
+ {
484
+ "amount_tax_included": compute_result.get("amount_included", 0.0),
485
+ "amount_tax_not_included": compute_result.get(
486
+ "amount_not_included", 0.0
487
+ ),
488
+ "amount_tax_withholding": compute_result.get(
489
+ "amount_withholding", 0.0
490
+ ),
491
+ "estimate_tax": compute_result.get("estimate_tax", 0.0),
492
+ }
493
+ )
494
+ in_draft_mode = line != line._origin
495
+ if in_draft_mode:
496
+ line.update(to_update)
497
+ else:
498
+ line.write(to_update)
499
+
500
+ def _prepare_tax_fields(self, compute_result):
501
+ self.ensure_one()
502
+ tax_values = {}
503
+ if self._is_imported():
504
+ return tax_values
505
+ computed_taxes = compute_result.get("taxes", {})
506
+ for tax in self.fiscal_tax_ids:
507
+ computed_tax = computed_taxes.get(tax.tax_domain, {})
508
+ tax_field_name = f"{tax.tax_domain}_tax_id"
509
+ if hasattr(self, tax_field_name):
510
+ tax_values[tax_field_name] = tax.ids[0]
511
+ method = getattr(self, f"_prepare_fields_{tax.tax_domain}", None)
512
+ if method and computed_tax:
513
+ prepared_fields = method(computed_tax)
514
+ if prepared_fields:
515
+ tax_values.update(prepared_fields)
516
+ return tax_values
517
+
518
+ @api.depends(
519
+ "product_id",
520
+ "fiscal_operation_id",
521
+ )
522
+ def _compute_price_unit_fiscal(self): # OK when edited from aml?? c-> check
523
+ for line in self:
524
+ line.price_unit = {
525
+ "sale_price": line.product_id.list_price,
526
+ "cost_price": line.product_id.standard_price,
527
+ }.get(line.fiscal_operation_id.default_price_unit, 0)
528
+
529
+ def _get_document(self):
530
+ self.ensure_one()
531
+ return self.document_id
532
+
533
+ def _get_fiscal_partner(self):
534
+ """
535
+ Meant to be overriden when the l10n_br_fiscal.document partner_id should not
536
+ be the same as the sale.order, purchase.order, account.move (...) partner_id.
537
+
538
+ (In the case of invoicing, the invoicing partner set by the user should
539
+ get priority over any invoicing contact returned by address_get.)
540
+ """
541
+ self.ensure_one()
542
+ return self.partner_id
543
+
544
+ @api.depends("product_id")
545
+ def _compute_product_fiscal_fields(self):
546
+ for line in self:
547
+ if not line.product_id:
548
+ # reset to default values:
549
+ line.fiscal_type = False
550
+ line.ncm_id = False
551
+ line.nbm_id = False
552
+ line.tax_icms_or_issqn = TAX_DOMAIN_ICMS
553
+ line.icms_origin = ICMS_ORIGIN_DEFAULT
554
+ line.cest_id = False
555
+ line.nbs_id = False
556
+ line.fiscal_genre_id = False
557
+ line.service_type_id = False
558
+ line.operation_indicator_id = False
559
+ continue
560
+ p = line.product_id
561
+ line.fiscal_type = p.fiscal_type
562
+ line.ncm_id = p.ncm_id
563
+ line.nbm_id = p.nbm_id
564
+ line.tax_icms_or_issqn = p.tax_icms_or_issqn
565
+ line.icms_origin = p.icms_origin
566
+ line.cest_id = p.cest_id
567
+ line.nbs_id = p.nbs_id
568
+ line.fiscal_genre_id = p.fiscal_genre_id
569
+ line.service_type_id = p.service_type_id
570
+ line.operation_indicator_id = p.operation_indicator_id
571
+
572
+ @api.depends("product_id")
573
+ def _compute_city_taxation_code_id(self):
574
+ for line in self:
575
+ if not line.product_id:
576
+ line.city_taxation_code_id = False
577
+ continue
578
+ company_city = line.company_id.city_id
579
+ city_tax_codes = line.product_id.city_taxation_code_ids
580
+ city_tax_code = city_tax_codes.filtered(
581
+ lambda r, _city_id=company_city: r.city_id == _city_id
582
+ )
583
+ if city_tax_code:
584
+ line.city_taxation_code_id = city_tax_code
585
+ else:
586
+ line.city_taxation_code_id = False
587
+
588
+ def _prepare_fields_issqn(self, tax_dict):
589
+ self.ensure_one()
590
+ return {
591
+ "issqn_base": tax_dict.get("base"),
592
+ "issqn_percent": tax_dict.get("percent_amount"),
593
+ "issqn_reduction": tax_dict.get("percent_reduction"),
594
+ "issqn_value": tax_dict.get("tax_value"),
595
+ }
596
+
597
+ def _prepare_fields_issqn_wh(self, tax_dict):
598
+ self.ensure_one()
599
+ return {
600
+ "issqn_wh_base": tax_dict.get("base"),
601
+ "issqn_wh_percent": tax_dict.get("percent_amount"),
602
+ "issqn_wh_reduction": tax_dict.get("percent_reduction"),
603
+ "issqn_wh_value": tax_dict.get("tax_value"),
604
+ }
605
+
606
+ def _prepare_fields_csll(self, tax_dict):
607
+ self.ensure_one()
608
+ return {
609
+ "csll_base": tax_dict.get("base"),
610
+ "csll_percent": tax_dict.get("percent_amount"),
611
+ "csll_reduction": tax_dict.get("percent_reduction"),
612
+ "csll_value": tax_dict.get("tax_value"),
613
+ }
614
+
615
+ def _prepare_fields_csll_wh(self, tax_dict):
616
+ self.ensure_one()
617
+ return {
618
+ "csll_wh_base": tax_dict.get("base"),
619
+ "csll_wh_percent": tax_dict.get("percent_amount"),
620
+ "csll_wh_reduction": tax_dict.get("percent_reduction"),
621
+ "csll_wh_value": tax_dict.get("tax_value"),
622
+ }
623
+
624
+ def _prepare_fields_irpj(self, tax_dict):
625
+ self.ensure_one()
626
+ return {
627
+ "irpj_base": tax_dict.get("base"),
628
+ "irpj_percent": tax_dict.get("percent_amount"),
629
+ "irpj_reduction": tax_dict.get("percent_reduction"),
630
+ "irpj_value": tax_dict.get("tax_value"),
631
+ }
632
+
633
+ def _prepare_fields_irpj_wh(self, tax_dict):
634
+ self.ensure_one()
635
+ return {
636
+ "irpj_wh_base": tax_dict.get("base"),
637
+ "irpj_wh_percent": tax_dict.get("percent_amount"),
638
+ "irpj_wh_reduction": tax_dict.get("percent_reduction"),
639
+ "irpj_wh_value": tax_dict.get("tax_value"),
640
+ }
641
+
642
+ def _prepare_fields_inss(self, tax_dict):
643
+ self.ensure_one()
644
+ return {
645
+ "inss_base": tax_dict.get("base"),
646
+ "inss_percent": tax_dict.get("percent_amount"),
647
+ "inss_reduction": tax_dict.get("percent_reduction"),
648
+ "inss_value": tax_dict.get("tax_value"),
649
+ }
650
+
651
+ def _prepare_fields_inss_wh(self, tax_dict):
652
+ self.ensure_one()
653
+ return {
654
+ "inss_wh_base": tax_dict.get("base"),
655
+ "inss_wh_percent": tax_dict.get("percent_amount"),
656
+ "inss_wh_reduction": tax_dict.get("percent_reduction"),
657
+ "inss_wh_value": tax_dict.get("tax_value"),
658
+ }
659
+
660
+ def _prepare_fields_icms(self, tax_dict):
661
+ self.ensure_one()
662
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
663
+ return {
664
+ "icms_cst_id": cst_id,
665
+ "icms_base_type": tax_dict.get("icms_base_type", ICMS_BASE_TYPE_DEFAULT),
666
+ "icms_base": tax_dict.get("base", 0.0),
667
+ "icms_percent": tax_dict.get("percent_amount", 0.0),
668
+ "icms_reduction": tax_dict.get("percent_reduction", 0.0),
669
+ "icms_value": tax_dict.get("tax_value", 0.0),
670
+ "icms_origin_percent": tax_dict.get("icms_origin_perc", 0.0),
671
+ "icms_destination_percent": tax_dict.get("icms_dest_perc", 0.0),
672
+ "icms_sharing_percent": tax_dict.get("icms_sharing_percent", 0.0),
673
+ "icms_destination_base": tax_dict.get("icms_dest_base", 0.0),
674
+ "icms_origin_value": tax_dict.get("icms_origin_value", 0.0),
675
+ "icms_destination_value": tax_dict.get("icms_dest_value", 0.0),
676
+ "icms_relief_value": tax_dict.get("icms_relief", 0.0),
677
+ }
678
+
679
+ @api.onchange(
680
+ "icms_base",
681
+ "icms_percent",
682
+ "icms_reduction",
683
+ "icms_value",
684
+ "icms_destination_base",
685
+ "icms_origin_percent",
686
+ "icms_destination_percent",
687
+ "icms_sharing_percent",
688
+ "icms_origin_value",
689
+ "icms_tax_benefit_id",
690
+ )
691
+ def _onchange_icms_fields(self):
692
+ if self.icms_tax_benefit_id:
693
+ self.icms_tax_id = self.icms_tax_benefit_id.tax_id
694
+
695
+ @api.onchange("tax_classification_id")
696
+ def _onchange_tax_classification_id(self):
697
+ if self.tax_classification_id:
698
+ self.ibs_tax_id = self.tax_classification_id.tax_ibs_id
699
+ self.cbs_tax_id = self.tax_classification_id.tax_cbs_id
700
+
701
+ def _prepare_fields_icmssn(self, tax_dict):
702
+ self.ensure_one()
703
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
704
+ icmssn_base = tax_dict.get("base", 0.0)
705
+ icmssn_credit_value = tax_dict.get("tax_value", 0.0)
706
+ simple_value = icmssn_base * self.icmssn_range_id.total_tax_percent
707
+ simple_without_icms_value = simple_value - icmssn_credit_value
708
+ return {
709
+ "icms_cst_id": cst_id,
710
+ "icmssn_base": icmssn_base,
711
+ "icmssn_percent": tax_dict.get("percent_amount"),
712
+ "icmssn_reduction": tax_dict.get("percent_reduction"),
713
+ "icmssn_credit_value": icmssn_credit_value,
714
+ "simple_value": simple_value,
715
+ "simple_without_icms_value": simple_without_icms_value,
716
+ }
717
+
718
+ def _prepare_fields_icmsst(self, tax_dict):
719
+ self.ensure_one()
720
+ return {
721
+ "icmsst_base_type": tax_dict.get(
722
+ "icmsst_base_type", ICMS_ST_BASE_TYPE_DEFAULT
723
+ ),
724
+ "icmsst_mva_percent": tax_dict.get("icmsst_mva_percent"),
725
+ "icmsst_percent": tax_dict.get("percent_amount"),
726
+ "icmsst_reduction": tax_dict.get("percent_reduction"),
727
+ "icmsst_base": tax_dict.get("base"),
728
+ "icmsst_value": tax_dict.get("tax_value"),
729
+ }
730
+
731
+ def _prepare_fields_icmsfcp(self, tax_dict):
732
+ self.ensure_one()
733
+ return {
734
+ "icmsfcp_base": tax_dict.get("base", 0.0),
735
+ "icmsfcp_percent": tax_dict.get("percent_amount", 0.0),
736
+ "icmsfcp_value": tax_dict.get("tax_value", 0.0),
737
+ }
738
+
739
+ def _prepare_fields_icmsfcpst(self, tax_dict):
740
+ self.ensure_one()
741
+ return {
742
+ "icmsfcpst_base": self.icmsst_base,
743
+ "icmsfcpst_percent": tax_dict.get("percent_amount", 0.0),
744
+ "icmsfcpst_value": tax_dict.get("tax_value", 0.0),
745
+ }
746
+
747
+ def _prepare_fields_ipi(self, tax_dict):
748
+ self.ensure_one()
749
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
750
+ return {
751
+ "ipi_cst_id": cst_id,
752
+ "ipi_base_type": tax_dict.get("base_type", False),
753
+ "ipi_base": tax_dict.get("base", 0.00),
754
+ "ipi_percent": tax_dict.get("percent_amount", 0.00),
755
+ "ipi_reduction": tax_dict.get("percent_reduction", 0.00),
756
+ "ipi_value": tax_dict.get("tax_value", 0.00),
757
+ }
758
+
759
+ def _prepare_fields_ii(self, tax_dict):
760
+ self.ensure_one()
761
+ return {
762
+ "ii_base": tax_dict.get("base", 0.00),
763
+ "ii_percent": tax_dict.get("percent_amount", 0.00),
764
+ "ii_value": tax_dict.get("tax_value", 0.00),
765
+ }
766
+
767
+ def _prepare_fields_cbs(self, tax_dict):
768
+ self.ensure_one()
769
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
770
+ return {
771
+ "cbs_cst_id": cst_id,
772
+ "cbs_base_type": tax_dict.get("base_type", False),
773
+ "cbs_base": tax_dict.get("base", 0.00),
774
+ "cbs_percent": tax_dict.get("percent_amount", 0.00),
775
+ "cbs_reduction": tax_dict.get("percent_reduction", 0.00),
776
+ "cbs_value": tax_dict.get("tax_value", 0.00),
777
+ }
778
+
779
+ def _prepare_fields_ibs(self, tax_dict):
780
+ self.ensure_one()
781
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
782
+ return {
783
+ "ibs_cst_id": cst_id,
784
+ "ibs_base_type": tax_dict.get("base_type", False),
785
+ "ibs_base": tax_dict.get("base", 0.00),
786
+ "ibs_percent": tax_dict.get("percent_amount", 0.00),
787
+ "ibs_reduction": tax_dict.get("percent_reduction", 0.00),
788
+ "ibs_value": tax_dict.get("tax_value", 0.00),
789
+ }
790
+
791
+ def _prepare_fields_pis(self, tax_dict):
792
+ self.ensure_one()
793
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
794
+ return {
795
+ "pis_cst_id": cst_id,
796
+ "pis_base_type": tax_dict.get("base_type"),
797
+ "pis_base": tax_dict.get("base", 0.00),
798
+ "pis_percent": tax_dict.get("percent_amount", 0.00),
799
+ "pis_reduction": tax_dict.get("percent_reduction", 0.00),
800
+ "pis_value": tax_dict.get("tax_value", 0.00),
801
+ }
802
+
803
+ def _prepare_fields_pis_wh(self, tax_dict):
804
+ self.ensure_one()
805
+ return {
806
+ "pis_wh_base_type": tax_dict.get("base_type"),
807
+ "pis_wh_base": tax_dict.get("base", 0.00),
808
+ "pis_wh_percent": tax_dict.get("percent_amount", 0.00),
809
+ "pis_wh_reduction": tax_dict.get("percent_reduction", 0.00),
810
+ "pis_wh_value": tax_dict.get("tax_value", 0.00),
811
+ }
812
+
813
+ def _prepare_fields_pisst(self, tax_dict):
814
+ self.ensure_one()
815
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
816
+ return {
817
+ "pisst_cst_id": cst_id,
818
+ "pisst_base_type": tax_dict.get("base_type"),
819
+ "pisst_base": tax_dict.get("base", 0.00),
820
+ "pisst_percent": tax_dict.get("percent_amount", 0.00),
821
+ "pisst_reduction": tax_dict.get("percent_reduction", 0.00),
822
+ "pisst_value": tax_dict.get("tax_value", 0.00),
823
+ }
824
+
825
+ def _prepare_fields_cofins(self, tax_dict):
826
+ self.ensure_one()
827
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
828
+ return {
829
+ "cofins_cst_id": cst_id,
830
+ "cofins_base_type": tax_dict.get("base_type"),
831
+ "cofins_base": tax_dict.get("base", 0.00),
832
+ "cofins_percent": tax_dict.get("percent_amount", 0.00),
833
+ "cofins_reduction": tax_dict.get("percent_reduction", 0.00),
834
+ "cofins_value": tax_dict.get("tax_value", 0.00),
835
+ }
836
+
837
+ def _prepare_fields_cofins_wh(self, tax_dict):
838
+ self.ensure_one()
839
+ return {
840
+ "cofins_wh_base_type": tax_dict.get("base_type"),
841
+ "cofins_wh_base": tax_dict.get("base", 0.00),
842
+ "cofins_wh_percent": tax_dict.get("percent_amount", 0.00),
843
+ "cofins_wh_reduction": tax_dict.get("percent_reduction", 0.00),
844
+ "cofins_wh_value": tax_dict.get("tax_value", 0.00),
845
+ }
846
+
847
+ def _prepare_fields_cofinsst(self, tax_dict):
848
+ self.ensure_one()
849
+ cst_id = tax_dict.get("cst_id").id if tax_dict.get("cst_id") else False
850
+ return {
851
+ "cofinsst_cst_id": cst_id,
852
+ "cofinsst_base_type": tax_dict.get("base_type"),
853
+ "cofinsst_base": tax_dict.get("base", 0.00),
854
+ "cofinsst_percent": tax_dict.get("percent_amount", 0.00),
855
+ "cofinsst_reduction": tax_dict.get("percent_reduction", 0.00),
856
+ "cofinsst_value": tax_dict.get("tax_value", 0.00),
857
+ }
858
+
859
+ @api.depends("product_id", "uom_id")
860
+ def _compute_uot_id(self):
861
+ for line in self:
862
+ p = line.product_id
863
+ line.uot_id = (p.uot_id if p else False) or line.uom_id
864
+
865
+ @api.depends("price_unit")
866
+ def _compute_fiscal_price(self):
867
+ for line in self:
868
+ if line.product_id and line.price_unit:
869
+ line.fiscal_price = line.price_unit / (
870
+ line.product_id.uot_factor or 1.0
871
+ )
872
+ else:
873
+ line.fiscal_price = line.price_unit
874
+
875
+ @api.depends("quantity")
876
+ def _compute_fiscal_quantity(self):
877
+ for line in self:
878
+ if line.product_id and line.quantity:
879
+ line.fiscal_quantity = line.quantity * (
880
+ line.product_id.uot_factor or 1.0
881
+ )
882
+ else:
883
+ line.fiscal_quantity = line.quantity
884
+
885
+ @api.model
886
+ def _add_fields_to_amount(self):
887
+ fields_to_amount = ["insurance_value", "other_value", "freight_value"]
888
+ if (
889
+ self.cfop_id.destination == CFOP_DESTINATION_EXPORT
890
+ and self.fiscal_operation_id.fiscal_operation_type == FISCAL_IN
891
+ ):
892
+ fields_to_amount.append("pis_value")
893
+ fields_to_amount.append("cofins_value")
894
+ fields_to_amount.append("icms_value")
895
+ fields_to_amount.append("ii_value")
896
+ fields_to_amount.append("ii_customhouse_charges")
897
+ return fields_to_amount
898
+
899
+ @api.model
900
+ def _rm_fields_to_amount(self):
901
+ return ["icms_relief_value"]
902
+
903
+ def _is_imported(self):
904
+ # When the mixin is used for instance
905
+ # in a PO line or SO line, there is no document_id
906
+ # and we consider the document is not imported
907
+ return hasattr(self, "document_id") and self.document_id.imported_document
908
+
80
909
  currency_id = fields.Many2one(
81
910
  comodel_name="res.currency",
82
911
  string="Currency",
@@ -92,7 +921,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
92
921
  tax_icms_or_issqn = fields.Selection(
93
922
  selection=TAX_ICMS_OR_ISSQN,
94
923
  string="ICMS or ISSQN Tax",
95
- default=TAX_DOMAIN_ICMS,
924
+ compute="_compute_product_fiscal_fields",
925
+ store=True,
926
+ readonly=False,
927
+ precompute=True,
96
928
  )
97
929
 
98
930
  partner_is_public_entity = fields.Boolean(related="partner_id.is_public_entity")
@@ -102,22 +934,60 @@ class FiscalDocumentLineMixin(models.AbstractModel):
102
934
  help="Indicates potential 'CSLL' and 'IRPJ' tax charges.",
103
935
  )
104
936
 
105
- price_unit = fields.Float(digits="Product Price")
937
+ price_unit = fields.Float(
938
+ digits="Product Price",
939
+ store=True,
940
+ )
106
941
 
107
942
  partner_id = fields.Many2one(comodel_name="res.partner", string="Partner")
108
943
 
944
+ company_id = fields.Many2one(
945
+ comodel_name="res.company",
946
+ string="Company",
947
+ )
948
+
949
+ ind_final = fields.Selection(
950
+ selection=FINAL_CUSTOMER,
951
+ string="Consumidor final",
952
+ compute="_compute_ind_final",
953
+ store=True,
954
+ precompute=True,
955
+ readonly=False,
956
+ )
957
+
958
+ def _compute_ind_final(self):
959
+ for line in self:
960
+ doc = line._get_document()
961
+ if line.ind_final != doc.ind_final:
962
+ line.ind_final = doc.ind_final
963
+
109
964
  partner_company_type = fields.Selection(related="partner_id.company_type")
110
965
 
111
- uom_id = fields.Many2one(comodel_name="uom.uom", string="UOM")
966
+ uom_id = fields.Many2one(
967
+ comodel_name="uom.uom",
968
+ string="UOM",
969
+ )
112
970
 
113
971
  quantity = fields.Float(
114
972
  digits="Product Unit of Measure",
115
973
  )
116
974
 
117
- fiscal_type = fields.Selection(selection=PRODUCT_FISCAL_TYPE)
975
+ fiscal_type = fields.Selection(
976
+ selection=PRODUCT_FISCAL_TYPE,
977
+ compute="_compute_product_fiscal_fields",
978
+ store=True,
979
+ readonly=False,
980
+ precompute=True,
981
+ )
118
982
 
119
983
  ncm_id = fields.Many2one(
120
- comodel_name="l10n_br_fiscal.ncm", index=True, string="NCM"
984
+ comodel_name="l10n_br_fiscal.ncm",
985
+ index=True,
986
+ string="NCM",
987
+ compute="_compute_product_fiscal_fields",
988
+ store=True,
989
+ readonly=False,
990
+ precompute=True,
121
991
  )
122
992
 
123
993
  nbm_id = fields.Many2one(
@@ -125,6 +995,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
125
995
  index=True,
126
996
  string="NBM",
127
997
  domain="[('ncm_ids', '=', ncm_id)]",
998
+ compute="_compute_product_fiscal_fields",
999
+ store=True,
1000
+ readonly=False,
1001
+ precompute=True,
128
1002
  )
129
1003
 
130
1004
  cest_id = fields.Many2one(
@@ -132,41 +1006,57 @@ class FiscalDocumentLineMixin(models.AbstractModel):
132
1006
  index=True,
133
1007
  string="CEST",
134
1008
  domain="[('ncm_ids', '=', ncm_id)]",
1009
+ compute="_compute_product_fiscal_fields",
1010
+ store=True,
1011
+ readonly=False,
1012
+ precompute=True,
135
1013
  )
136
1014
 
137
1015
  nbs_id = fields.Many2one(
138
- comodel_name="l10n_br_fiscal.nbs", index=True, string="NBS"
1016
+ comodel_name="l10n_br_fiscal.nbs",
1017
+ index=True,
1018
+ string="NBS",
1019
+ compute="_compute_product_fiscal_fields",
1020
+ store=True,
1021
+ readonly=False,
1022
+ precompute=True,
139
1023
  )
140
1024
 
141
1025
  fiscal_operation_id = fields.Many2one(
142
1026
  comodel_name="l10n_br_fiscal.operation",
143
1027
  string="Operation",
144
1028
  domain=lambda self: self._operation_domain(),
145
- default=_default_operation,
146
1029
  )
147
1030
 
148
1031
  fiscal_operation_type = fields.Selection(
149
1032
  string="Operation Type",
150
1033
  related="fiscal_operation_id.fiscal_operation_type",
151
- readonly=True,
152
1034
  )
153
1035
 
154
1036
  operation_fiscal_type = fields.Selection(
155
1037
  related="fiscal_operation_id.fiscal_type",
156
- readonly=True,
1038
+ string="Operation Fiscal Type",
157
1039
  )
158
1040
 
159
1041
  fiscal_operation_line_id = fields.Many2one(
160
1042
  comodel_name="l10n_br_fiscal.operation.line",
161
1043
  string="Operation Line",
1044
+ compute="_compute_fiscal_operation_line_id",
162
1045
  domain="[('fiscal_operation_id', '=', fiscal_operation_id), "
163
1046
  "('state', '=', 'approved')]",
1047
+ store=True,
1048
+ precompute=True,
1049
+ readonly=False,
164
1050
  )
165
1051
 
166
1052
  cfop_id = fields.Many2one(
167
1053
  comodel_name="l10n_br_fiscal.cfop",
168
1054
  string="CFOP",
169
1055
  domain="[('type_in_out', '=', fiscal_operation_type)]",
1056
+ compute="_compute_fiscal_tax_ids",
1057
+ store=True,
1058
+ precompute=True,
1059
+ readonly=False,
170
1060
  )
171
1061
 
172
1062
  cfop_destination = fields.Selection(
@@ -174,11 +1064,30 @@ class FiscalDocumentLineMixin(models.AbstractModel):
174
1064
  string="CFOP Destination",
175
1065
  )
176
1066
 
177
- fiscal_price = fields.Float(digits="Product Price")
1067
+ fiscal_price = fields.Float(
1068
+ digits="Product Price",
1069
+ compute="_compute_fiscal_price",
1070
+ store=True,
1071
+ precompute=True,
1072
+ readonly=False,
1073
+ )
178
1074
 
179
- uot_id = fields.Many2one(comodel_name="uom.uom", string="Tax UoM")
1075
+ uot_id = fields.Many2one(
1076
+ comodel_name="uom.uom",
1077
+ string="Tax UoM",
1078
+ compute="_compute_uot_id",
1079
+ store=True,
1080
+ readonly=False,
1081
+ precompute=True,
1082
+ )
180
1083
 
181
- fiscal_quantity = fields.Float(digits="Product Unit of Measure")
1084
+ fiscal_quantity = fields.Float(
1085
+ digits="Product Unit of Measure",
1086
+ compute="_compute_fiscal_quantity",
1087
+ store=True,
1088
+ precompute=True,
1089
+ readonly=False,
1090
+ )
182
1091
 
183
1092
  discount_value = fields.Monetary()
184
1093
 
@@ -190,10 +1099,11 @@ class FiscalDocumentLineMixin(models.AbstractModel):
190
1099
 
191
1100
  fiscal_tax_ids = fields.Many2many(
192
1101
  comodel_name="l10n_br_fiscal.tax",
193
- relation="fiscal_tax_rel",
194
- column1="document_id",
195
- column2="fiscal_tax_id",
196
1102
  string="Fiscal Taxes",
1103
+ compute="_compute_fiscal_tax_ids",
1104
+ store=True,
1105
+ precompute=True,
1106
+ readonly=False,
197
1107
  )
198
1108
 
199
1109
  amount_fiscal = fields.Monetary(
@@ -209,11 +1119,11 @@ class FiscalDocumentLineMixin(models.AbstractModel):
209
1119
  compute="_compute_fiscal_amounts",
210
1120
  )
211
1121
 
212
- amount_untaxed = fields.Monetary(
1122
+ fiscal_amount_untaxed = fields.Monetary(
213
1123
  compute="_compute_fiscal_amounts",
214
1124
  )
215
1125
 
216
- amount_tax = fields.Monetary(
1126
+ fiscal_amount_tax = fields.Monetary(
217
1127
  compute="_compute_fiscal_amounts",
218
1128
  )
219
1129
 
@@ -221,7 +1131,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
221
1131
  compute="_compute_fiscal_amounts",
222
1132
  )
223
1133
 
224
- amount_total = fields.Monetary(
1134
+ fiscal_amount_total = fields.Monetary(
225
1135
  compute="_compute_fiscal_amounts",
226
1136
  )
227
1137
 
@@ -240,14 +1150,35 @@ class FiscalDocumentLineMixin(models.AbstractModel):
240
1150
  compute="_compute_fiscal_amounts",
241
1151
  )
242
1152
 
243
- amount_tax_included = fields.Monetary()
1153
+ amount_tax_included = fields.Monetary(
1154
+ compute="_compute_tax_fields",
1155
+ store=True,
1156
+ precompute=True,
1157
+ readonly=False,
1158
+ )
244
1159
 
245
- amount_tax_not_included = fields.Monetary()
1160
+ amount_tax_not_included = fields.Monetary(
1161
+ compute="_compute_tax_fields",
1162
+ store=True,
1163
+ precompute=True,
1164
+ readonly=False,
1165
+ )
246
1166
 
247
- amount_tax_withholding = fields.Monetary(string="Tax Withholding")
1167
+ amount_tax_withholding = fields.Monetary(
1168
+ string="Tax Withholding",
1169
+ compute="_compute_tax_fields",
1170
+ store=True,
1171
+ precompute=True,
1172
+ readonly=False,
1173
+ )
248
1174
 
249
1175
  fiscal_genre_id = fields.Many2one(
250
- comodel_name="l10n_br_fiscal.product.genre", string="Fiscal Product Genre"
1176
+ comodel_name="l10n_br_fiscal.product.genre",
1177
+ string="Fiscal Product Genre",
1178
+ compute="_compute_product_fiscal_fields",
1179
+ store=True,
1180
+ readonly=False,
1181
+ precompute=True,
251
1182
  )
252
1183
 
253
1184
  fiscal_genre_code = fields.Char(
@@ -258,10 +1189,27 @@ class FiscalDocumentLineMixin(models.AbstractModel):
258
1189
  comodel_name="l10n_br_fiscal.service.type",
259
1190
  string="Service Type LC 166",
260
1191
  domain="[('internal_type', '=', 'normal')]",
1192
+ compute="_compute_product_fiscal_fields",
1193
+ store=True,
1194
+ readonly=False,
1195
+ precompute=True,
261
1196
  )
262
1197
 
263
1198
  city_taxation_code_id = fields.Many2one(
264
- comodel_name="l10n_br_fiscal.city.taxation.code", string="City Taxation Code"
1199
+ comodel_name="l10n_br_fiscal.city.taxation.code",
1200
+ compute="_compute_city_taxation_code_id",
1201
+ store=True,
1202
+ readonly=False,
1203
+ precompute=True,
1204
+ )
1205
+
1206
+ operation_indicator_id = fields.Many2one(
1207
+ comodel_name="l10n_br_fiscal.operation.indicator",
1208
+ string="Operation Indicator",
1209
+ compute="_compute_product_fiscal_fields",
1210
+ store=True,
1211
+ readonly=False,
1212
+ precompute=True,
265
1213
  )
266
1214
 
267
1215
  partner_order = fields.Char(string="Partner Order (xPed)", size=15)
@@ -273,11 +1221,18 @@ class FiscalDocumentLineMixin(models.AbstractModel):
273
1221
  comodel_name="l10n_br_fiscal.tax",
274
1222
  string="Tax ISSQN",
275
1223
  domain=[("tax_domain", "=", TAX_DOMAIN_ISSQN)],
1224
+ compute="_compute_tax_fields",
1225
+ store=True,
1226
+ precompute=True,
1227
+ readonly=False,
276
1228
  )
277
1229
 
278
1230
  issqn_fg_city_id = fields.Many2one(
279
1231
  comodel_name="res.city",
1232
+ related="city_taxation_code_id.city_id",
280
1233
  string="ISSQN City",
1234
+ store=True,
1235
+ precompute=True,
281
1236
  )
282
1237
 
283
1238
  # vDeducao
@@ -306,33 +1261,89 @@ class FiscalDocumentLineMixin(models.AbstractModel):
306
1261
  default=ISSQN_INCENTIVE_DEFAULT,
307
1262
  )
308
1263
 
309
- issqn_base = fields.Monetary(string="ISSQN Base")
1264
+ issqn_base = fields.Monetary(
1265
+ string="ISSQN Base",
1266
+ compute="_compute_tax_fields",
1267
+ store=True,
1268
+ precompute=True,
1269
+ readonly=False,
1270
+ )
310
1271
 
311
- issqn_percent = fields.Float(string="ISSQN %")
1272
+ issqn_percent = fields.Float(
1273
+ string="ISSQN %",
1274
+ compute="_compute_tax_fields",
1275
+ store=True,
1276
+ precompute=True,
1277
+ readonly=False,
1278
+ )
312
1279
 
313
- issqn_reduction = fields.Float(string="ISSQN % Reduction")
1280
+ issqn_reduction = fields.Float(
1281
+ string="ISSQN % Reduction",
1282
+ compute="_compute_tax_fields",
1283
+ store=True,
1284
+ precompute=True,
1285
+ readonly=False,
1286
+ )
314
1287
 
315
- issqn_value = fields.Monetary(string="ISSQN Value")
1288
+ issqn_value = fields.Monetary(
1289
+ string="ISSQN Value",
1290
+ compute="_compute_tax_fields",
1291
+ store=True,
1292
+ precompute=True,
1293
+ readonly=False,
1294
+ )
316
1295
 
317
1296
  issqn_wh_tax_id = fields.Many2one(
318
1297
  comodel_name="l10n_br_fiscal.tax",
319
1298
  string="Tax ISSQN RET",
320
1299
  domain=[("tax_domain", "=", TAX_DOMAIN_ISSQN_WH)],
1300
+ compute="_compute_tax_fields",
1301
+ store=True,
1302
+ precompute=True,
1303
+ readonly=False,
321
1304
  )
322
1305
 
323
- issqn_wh_base = fields.Monetary(string="ISSQN RET Base")
1306
+ issqn_wh_base = fields.Monetary(
1307
+ string="ISSQN RET Base",
1308
+ compute="_compute_tax_fields",
1309
+ store=True,
1310
+ precompute=True,
1311
+ readonly=False,
1312
+ )
324
1313
 
325
- issqn_wh_percent = fields.Float(string="ISSQN RET %")
1314
+ issqn_wh_percent = fields.Float(
1315
+ string="ISSQN RET %",
1316
+ compute="_compute_tax_fields",
1317
+ store=True,
1318
+ precompute=True,
1319
+ readonly=False,
1320
+ )
326
1321
 
327
- issqn_wh_reduction = fields.Float(string="ISSQN RET % Reduction")
1322
+ issqn_wh_reduction = fields.Float(
1323
+ string="ISSQN RET % Reduction",
1324
+ compute="_compute_tax_fields",
1325
+ store=True,
1326
+ precompute=True,
1327
+ readonly=False,
1328
+ )
328
1329
 
329
- issqn_wh_value = fields.Monetary(string="ISSQN RET Value")
1330
+ issqn_wh_value = fields.Monetary(
1331
+ string="ISSQN RET Value",
1332
+ compute="_compute_tax_fields",
1333
+ store=True,
1334
+ precompute=True,
1335
+ readonly=False,
1336
+ )
330
1337
 
331
1338
  # ICMS Fields
332
1339
  icms_tax_id = fields.Many2one(
333
1340
  comodel_name="l10n_br_fiscal.tax",
334
1341
  string="Tax ICMS",
335
1342
  domain=[("tax_domain", "=", TAX_DOMAIN_ICMS)],
1343
+ compute="_compute_tax_fields",
1344
+ store=True,
1345
+ precompute=True,
1346
+ readonly=False,
336
1347
  )
337
1348
 
338
1349
  icms_cst_id = fields.Many2one(
@@ -340,6 +1351,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
340
1351
  string="CST ICMS",
341
1352
  domain="[('tax_domain', '=', {'1': 'icmssn', '2': 'icmssn', "
342
1353
  "'3': 'icms'}.get(tax_framework))]",
1354
+ compute="_compute_tax_fields",
1355
+ store=True,
1356
+ precompute=True,
1357
+ readonly=False,
343
1358
  )
344
1359
 
345
1360
  icms_cst_code = fields.Char(
@@ -353,6 +1368,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
353
1368
  ("is_benefit", "=", True),
354
1369
  ("tax_domain", "=", TAX_DOMAIN_ICMS),
355
1370
  ],
1371
+ compute="_compute_fiscal_tax_ids",
1372
+ store=True,
1373
+ precompute=True,
1374
+ readonly=False,
356
1375
  )
357
1376
 
358
1377
  icms_tax_benefit_code = fields.Char(
@@ -362,24 +1381,56 @@ class FiscalDocumentLineMixin(models.AbstractModel):
362
1381
  icms_base_type = fields.Selection(
363
1382
  selection=ICMS_BASE_TYPE,
364
1383
  string="ICMS Base Type",
365
- default=ICMS_BASE_TYPE_DEFAULT,
1384
+ compute="_compute_tax_fields",
1385
+ store=True,
1386
+ precompute=True,
1387
+ readonly=False,
366
1388
  )
367
1389
 
368
1390
  icms_origin = fields.Selection(
369
- selection=ICMS_ORIGIN, string="ICMS Origin", default=ICMS_ORIGIN_DEFAULT
1391
+ selection=ICMS_ORIGIN,
1392
+ string="ICMS Origin",
1393
+ compute="_compute_product_fiscal_fields",
1394
+ store=True,
1395
+ readonly=False,
1396
+ precompute=True,
370
1397
  )
371
1398
 
372
1399
  # vBC - Valor da base de cálculo do ICMS
373
- icms_base = fields.Monetary(string="ICMS Base")
1400
+ icms_base = fields.Monetary(
1401
+ string="ICMS Base",
1402
+ compute="_compute_tax_fields",
1403
+ store=True,
1404
+ precompute=True,
1405
+ readonly=False,
1406
+ )
374
1407
 
375
1408
  # pICMS - Alíquota do IMCS
376
- icms_percent = fields.Float(string="ICMS %")
1409
+ icms_percent = fields.Float(
1410
+ string="ICMS %",
1411
+ compute="_compute_tax_fields",
1412
+ store=True,
1413
+ precompute=True,
1414
+ readonly=False,
1415
+ )
377
1416
 
378
1417
  # pRedBC - Percentual de redução do ICMS
379
- icms_reduction = fields.Float(string="ICMS % Reduction")
1418
+ icms_reduction = fields.Float(
1419
+ string="ICMS % Reduction",
1420
+ compute="_compute_tax_fields",
1421
+ store=True,
1422
+ precompute=True,
1423
+ readonly=False,
1424
+ )
380
1425
 
381
1426
  # vICMS - Valor do ICMS
382
- icms_value = fields.Monetary(string="ICMS Value")
1427
+ icms_value = fields.Monetary(
1428
+ string="ICMS Value",
1429
+ compute="_compute_tax_fields",
1430
+ store=True,
1431
+ precompute=True,
1432
+ readonly=False,
1433
+ )
383
1434
 
384
1435
  # vICMSSubstituto - Valor do ICMS cobrado em operação anterior
385
1436
  icms_substitute = fields.Monetary(
@@ -393,36 +1444,79 @@ class FiscalDocumentLineMixin(models.AbstractModel):
393
1444
  )
394
1445
 
395
1446
  # vICMSDeson - Valor do ICMS desonerado
396
- icms_relief_value = fields.Monetary(string="ICMS Relief Value")
1447
+ icms_relief_value = fields.Monetary(
1448
+ string="ICMS Relief Value",
1449
+ compute="_compute_tax_fields",
1450
+ store=True,
1451
+ precompute=True,
1452
+ readonly=False,
1453
+ )
397
1454
 
398
1455
  # ICMS ST Fields
399
1456
  icmsst_tax_id = fields.Many2one(
400
1457
  comodel_name="l10n_br_fiscal.tax",
401
1458
  string="Tax ICMS ST",
402
1459
  domain=[("tax_domain", "=", TAX_DOMAIN_ICMS_ST)],
1460
+ compute="_compute_tax_fields",
1461
+ store=True,
1462
+ precompute=True,
1463
+ readonly=False,
403
1464
  )
404
1465
 
405
1466
  # modBCST - Modalidade de determinação da BC do ICMS ST
406
1467
  icmsst_base_type = fields.Selection(
407
1468
  selection=ICMS_ST_BASE_TYPE,
408
1469
  string="ICMS ST Base Type",
409
- default=ICMS_ST_BASE_TYPE_DEFAULT,
1470
+ compute="_compute_tax_fields",
1471
+ store=True,
1472
+ precompute=True,
1473
+ readonly=False,
410
1474
  )
411
1475
 
412
1476
  # pMVAST - Percentual da margem de valor Adicionado do ICMS ST
413
- icmsst_mva_percent = fields.Float(string="ICMS ST MVA %")
1477
+ icmsst_mva_percent = fields.Float(
1478
+ string="ICMS ST MVA %",
1479
+ compute="_compute_tax_fields",
1480
+ store=True,
1481
+ precompute=True,
1482
+ readonly=False,
1483
+ )
414
1484
 
415
1485
  # pRedBCST - Percentual da Redução de BC do ICMS ST
416
- icmsst_reduction = fields.Float(string="ICMS ST % Reduction")
1486
+ icmsst_reduction = fields.Float(
1487
+ string="ICMS ST % Reduction",
1488
+ compute="_compute_tax_fields",
1489
+ store=True,
1490
+ precompute=True,
1491
+ readonly=False,
1492
+ )
417
1493
 
418
1494
  # vBCST - Valor da BC do ICMS ST
419
- icmsst_base = fields.Monetary(string="ICMS ST Base")
1495
+ icmsst_base = fields.Monetary(
1496
+ string="ICMS ST Base",
1497
+ compute="_compute_tax_fields",
1498
+ store=True,
1499
+ precompute=True,
1500
+ readonly=False,
1501
+ )
420
1502
 
421
1503
  # pICMSST - Alíquota do imposto do ICMS ST
422
- icmsst_percent = fields.Float(string="ICMS ST %")
1504
+ icmsst_percent = fields.Float(
1505
+ string="ICMS ST %",
1506
+ compute="_compute_tax_fields",
1507
+ store=True,
1508
+ precompute=True,
1509
+ readonly=False,
1510
+ )
423
1511
 
424
1512
  # vICMSST - Valor do ICMS ST
425
- icmsst_value = fields.Monetary(string="ICMS ST Value")
1513
+ icmsst_value = fields.Monetary(
1514
+ string="ICMS ST Value",
1515
+ compute="_compute_tax_fields",
1516
+ store=True,
1517
+ precompute=True,
1518
+ readonly=False,
1519
+ )
426
1520
 
427
1521
  # vBCSTRet - Valor da base de cálculo do ICMS ST retido
428
1522
  icmsst_wh_base = fields.Monetary(string="ICMS ST WH Base")
@@ -438,58 +1532,134 @@ class FiscalDocumentLineMixin(models.AbstractModel):
438
1532
  comodel_name="l10n_br_fiscal.tax",
439
1533
  string="Tax ICMS FCP",
440
1534
  domain=[("tax_domain", "=", TAX_DOMAIN_ICMS_FCP)],
1535
+ compute="_compute_tax_fields",
1536
+ store=True,
1537
+ precompute=True,
1538
+ readonly=False,
441
1539
  )
442
1540
 
443
1541
  # vBCFCPUFDest
444
1542
  icmsfcp_base = fields.Monetary(
445
1543
  string="ICMS FCP Base",
1544
+ compute="_compute_tax_fields",
1545
+ store=True,
1546
+ precompute=True,
1547
+ readonly=False,
446
1548
  )
447
1549
 
448
1550
  # pFCPUFDest - Percentual do ICMS relativo ao Fundo de
449
1551
  # Combate à Pobreza (FCP) na UF de destino
450
- icmsfcp_percent = fields.Float(string="ICMS FCP %")
1552
+ icmsfcp_percent = fields.Float(
1553
+ string="ICMS FCP %",
1554
+ compute="_compute_tax_fields",
1555
+ store=True,
1556
+ precompute=True,
1557
+ readonly=False,
1558
+ )
451
1559
 
452
1560
  # vFCPUFDest - Valor do ICMS relativo ao Fundo
453
1561
  # de Combate à Pobreza (FCP) da UF de destino
454
- icmsfcp_value = fields.Monetary(string="ICMS FCP Value")
1562
+ icmsfcp_value = fields.Monetary(
1563
+ string="ICMS FCP Value",
1564
+ compute="_compute_tax_fields",
1565
+ store=True,
1566
+ precompute=True,
1567
+ readonly=False,
1568
+ )
455
1569
 
456
1570
  # ICMS FCP ST Fields
457
1571
  icmsfcpst_tax_id = fields.Many2one(
458
1572
  comodel_name="l10n_br_fiscal.tax",
459
1573
  string="Tax ICMS FCP ST",
460
1574
  domain=[("tax_domain", "=", TAX_DOMAIN_ICMS_FCP_ST)],
1575
+ compute="_compute_tax_fields",
1576
+ store=True,
1577
+ precompute=True,
1578
+ readonly=False,
461
1579
  )
462
1580
 
463
1581
  # vBCFCPST
464
1582
  icmsfcpst_base = fields.Monetary(
465
1583
  string="ICMS FCP ST Base",
1584
+ compute="_compute_tax_fields",
1585
+ store=True,
1586
+ precompute=True,
1587
+ readonly=False,
466
1588
  )
467
1589
 
468
1590
  # pFCPST - Percentual do FCP ST
469
- icmsfcpst_percent = fields.Float(string="ICMS FCP ST %")
1591
+ icmsfcpst_percent = fields.Float(
1592
+ string="ICMS FCP ST %",
1593
+ compute="_compute_tax_fields",
1594
+ store=True,
1595
+ precompute=True,
1596
+ readonly=False,
1597
+ )
470
1598
 
471
1599
  # vFCPST - Valor do ICMS relativo ao
472
1600
  # Fundo de Combate à Pobreza (FCP) por Substituição Tributária
473
- icmsfcpst_value = fields.Monetary(string="ICMS FCP ST Value")
1601
+ icmsfcpst_value = fields.Monetary(
1602
+ string="ICMS FCP ST Value",
1603
+ compute="_compute_tax_fields",
1604
+ store=True,
1605
+ precompute=True,
1606
+ readonly=False,
1607
+ )
474
1608
 
475
1609
  # ICMS DIFAL Fields
476
1610
  # vBCUFDest - Valor da BC do ICMS na UF de destino
477
- icms_destination_base = fields.Monetary(string="ICMS Destination Base")
1611
+ icms_destination_base = fields.Monetary(
1612
+ string="ICMS Destination Base",
1613
+ compute="_compute_tax_fields",
1614
+ store=True,
1615
+ precompute=True,
1616
+ readonly=False,
1617
+ )
478
1618
 
479
1619
  # pICMSUFDest - Alíquota interna da UF de destino
480
- icms_origin_percent = fields.Float(string="ICMS Internal %")
1620
+ icms_origin_percent = fields.Float(
1621
+ string="ICMS Internal %",
1622
+ compute="_compute_tax_fields",
1623
+ store=True,
1624
+ precompute=True,
1625
+ readonly=False,
1626
+ )
481
1627
 
482
1628
  # pICMSInter - Alíquota interestadual das UF envolvidas
483
- icms_destination_percent = fields.Float(string="ICMS External %")
1629
+ icms_destination_percent = fields.Float(
1630
+ string="ICMS External %",
1631
+ compute="_compute_tax_fields",
1632
+ store=True,
1633
+ precompute=True,
1634
+ readonly=False,
1635
+ )
484
1636
 
485
1637
  # pICMSInterPart - Percentual provisório de partilha do ICMS Interestadual
486
- icms_sharing_percent = fields.Float(string="ICMS Sharing %")
1638
+ icms_sharing_percent = fields.Float(
1639
+ string="ICMS Sharing %",
1640
+ compute="_compute_tax_fields",
1641
+ store=True,
1642
+ precompute=True,
1643
+ readonly=False,
1644
+ )
487
1645
 
488
1646
  # vICMSUFRemet - Valor do ICMS Interestadual para a UF do remetente
489
- icms_origin_value = fields.Monetary(string="ICMS Origin Value")
1647
+ icms_origin_value = fields.Monetary(
1648
+ string="ICMS Origin Value",
1649
+ compute="_compute_tax_fields",
1650
+ store=True,
1651
+ precompute=True,
1652
+ readonly=False,
1653
+ )
490
1654
 
491
1655
  # vICMSUFDest - Valor do ICMS Interestadual para a UF de destino
492
- icms_destination_value = fields.Monetary(string="ICMS Dest. Value")
1656
+ icms_destination_value = fields.Monetary(
1657
+ string="ICMS Dest. Value",
1658
+ compute="_compute_tax_fields",
1659
+ store=True,
1660
+ precompute=True,
1661
+ readonly=False,
1662
+ )
493
1663
 
494
1664
  # ICMS Simples Nacional Fields
495
1665
  icmssn_range_id = fields.Many2one(
@@ -502,17 +1672,45 @@ class FiscalDocumentLineMixin(models.AbstractModel):
502
1672
  comodel_name="l10n_br_fiscal.tax",
503
1673
  string="Tax ICMS SN",
504
1674
  domain=[("tax_domain", "=", TAX_DOMAIN_ICMS_SN)],
1675
+ compute="_compute_tax_fields",
1676
+ store=True,
1677
+ precompute=True,
1678
+ readonly=False,
505
1679
  )
506
1680
 
507
- icmssn_base = fields.Monetary(string="ICMS SN Base")
1681
+ icmssn_base = fields.Monetary(
1682
+ string="ICMS SN Base",
1683
+ compute="_compute_tax_fields",
1684
+ store=True,
1685
+ precompute=True,
1686
+ readonly=False,
1687
+ )
508
1688
 
509
- icmssn_reduction = fields.Monetary(string="ICMS SN Reduction")
1689
+ icmssn_reduction = fields.Monetary(
1690
+ string="ICMS SN Reduction",
1691
+ compute="_compute_tax_fields",
1692
+ store=True,
1693
+ precompute=True,
1694
+ readonly=False,
1695
+ )
510
1696
 
511
1697
  # pCredICMSSN - Alíquota aplicável de cálculo do crédito (Simples Nacional)
512
- icmssn_percent = fields.Float(string="ICMS SN %")
1698
+ icmssn_percent = fields.Float(
1699
+ string="ICMS SN %",
1700
+ compute="_compute_tax_fields",
1701
+ store=True,
1702
+ precompute=True,
1703
+ readonly=False,
1704
+ )
513
1705
 
514
1706
  # vCredICMSSN - Valor do crédito do ICMS que pode ser aproveitado
515
- icmssn_credit_value = fields.Monetary(string="ICMS SN Credit")
1707
+ icmssn_credit_value = fields.Monetary(
1708
+ string="ICMS SN Credit",
1709
+ compute="_compute_tax_fields",
1710
+ store=True,
1711
+ precompute=True,
1712
+ readonly=False,
1713
+ )
516
1714
 
517
1715
  # ICMS COBRADO ANTERIORMENTE POR ST
518
1716
  # vBCFCPSTRet - Valor da base de cálculo do FCP retido anteriormente
@@ -541,13 +1739,20 @@ class FiscalDocumentLineMixin(models.AbstractModel):
541
1739
  comodel_name="l10n_br_fiscal.tax",
542
1740
  string="Tax IPI",
543
1741
  domain=[("tax_domain", "=", TAX_DOMAIN_IPI)],
1742
+ compute="_compute_tax_fields",
1743
+ store=True,
1744
+ precompute=True,
1745
+ readonly=False,
544
1746
  )
545
1747
 
546
1748
  ipi_cst_id = fields.Many2one(
547
1749
  comodel_name="l10n_br_fiscal.cst",
548
1750
  string="CST IPI",
549
- domain="[('cst_type', '=', fiscal_operation_type),"
550
- "('tax_domain', '=', 'ipi')]",
1751
+ domain="[('cst_type', '=', fiscal_operation_type),('tax_domain', '=', 'ipi')]",
1752
+ compute="_compute_tax_fields",
1753
+ store=True,
1754
+ precompute=True,
1755
+ readonly=False,
551
1756
  )
552
1757
 
553
1758
  ipi_cst_code = fields.Char(
@@ -555,22 +1760,54 @@ class FiscalDocumentLineMixin(models.AbstractModel):
555
1760
  )
556
1761
 
557
1762
  ipi_base_type = fields.Selection(
558
- selection=TAX_BASE_TYPE, string="IPI Base Type", default=TAX_BASE_TYPE_PERCENT
1763
+ selection=TAX_BASE_TYPE,
1764
+ string="IPI Base Type",
1765
+ compute="_compute_tax_fields",
1766
+ store=True,
1767
+ precompute=True,
1768
+ readonly=False,
559
1769
  )
560
1770
 
561
- ipi_base = fields.Monetary(string="IPI Base")
1771
+ ipi_base = fields.Monetary(
1772
+ string="IPI Base",
1773
+ compute="_compute_tax_fields",
1774
+ store=True,
1775
+ precompute=True,
1776
+ readonly=False,
1777
+ )
562
1778
 
563
- ipi_percent = fields.Float(string="IPI %")
1779
+ ipi_percent = fields.Float(
1780
+ string="IPI %",
1781
+ compute="_compute_tax_fields",
1782
+ store=True,
1783
+ precompute=True,
1784
+ readonly=False,
1785
+ )
564
1786
 
565
- ipi_reduction = fields.Float(string="IPI % Reduction")
1787
+ ipi_reduction = fields.Float(
1788
+ string="IPI % Reduction",
1789
+ compute="_compute_tax_fields",
1790
+ store=True,
1791
+ precompute=True,
1792
+ readonly=False,
1793
+ )
566
1794
 
567
- ipi_value = fields.Monetary(string="IPI Value")
1795
+ ipi_value = fields.Monetary(
1796
+ string="IPI Value",
1797
+ compute="_compute_tax_fields",
1798
+ store=True,
1799
+ precompute=True,
1800
+ readonly=False,
1801
+ )
568
1802
 
569
1803
  ipi_guideline_id = fields.Many2one(
570
1804
  comodel_name="l10n_br_fiscal.tax.ipi.guideline",
571
1805
  string="IPI Guideline",
572
- domain="['|', ('cst_in_id', '=', ipi_cst_id),"
573
- "('cst_out_id', '=', ipi_cst_id)]",
1806
+ domain="['|', ('cst_in_id', '=', ipi_cst_id),('cst_out_id', '=', ipi_cst_id)]",
1807
+ compute="_compute_fiscal_tax_ids",
1808
+ store=True,
1809
+ precompute=True,
1810
+ readonly=False,
574
1811
  )
575
1812
 
576
1813
  # IPI Devolvido Fields
@@ -578,18 +1815,205 @@ class FiscalDocumentLineMixin(models.AbstractModel):
578
1815
 
579
1816
  ipi_devol_value = fields.Monetary(string="Valor do IPI devolvido")
580
1817
 
1818
+ # CBS Fields
1819
+ cbs_tax_id = fields.Many2one(
1820
+ comodel_name="l10n_br_fiscal.tax",
1821
+ string="Tax CBS",
1822
+ domain=(
1823
+ f"[('tax_domain', '=', '{TAX_DOMAIN_CBS}'), '|', "
1824
+ "('cst_in_id.code', 'like', cst_code_prefix_like), "
1825
+ "('cst_out_id.code', 'like', cst_code_prefix_like)]"
1826
+ ),
1827
+ compute="_compute_tax_fields",
1828
+ store=True,
1829
+ precompute=True,
1830
+ readonly=False,
1831
+ )
1832
+
1833
+ cbs_cst_id = fields.Many2one(
1834
+ comodel_name="l10n_br_fiscal.cst",
1835
+ string="CST CBS",
1836
+ domain="[('cst_type', '=', fiscal_operation_type),('tax_domain', '=', 'cbs')]",
1837
+ compute="_compute_tax_fields",
1838
+ store=True,
1839
+ precompute=True,
1840
+ readonly=False,
1841
+ )
1842
+
1843
+ cbs_cst_code = fields.Char(
1844
+ related="cbs_cst_id.code", string="CBS CST Code", store=True
1845
+ )
1846
+
1847
+ cbs_base_type = fields.Selection(
1848
+ selection=TAX_BASE_TYPE,
1849
+ string="CBS Base Type",
1850
+ compute="_compute_tax_fields",
1851
+ store=True,
1852
+ precompute=True,
1853
+ readonly=False,
1854
+ )
1855
+
1856
+ cbs_base = fields.Monetary(
1857
+ string="CBS Base",
1858
+ compute="_compute_tax_fields",
1859
+ store=True,
1860
+ precompute=True,
1861
+ readonly=False,
1862
+ )
1863
+
1864
+ cbs_percent = fields.Float(
1865
+ string="CBS %",
1866
+ compute="_compute_tax_fields",
1867
+ store=True,
1868
+ precompute=True,
1869
+ readonly=False,
1870
+ )
1871
+
1872
+ cbs_reduction = fields.Float(
1873
+ string="CBS % Reduction",
1874
+ compute="_compute_tax_fields",
1875
+ store=True,
1876
+ precompute=True,
1877
+ readonly=False,
1878
+ )
1879
+
1880
+ cbs_value = fields.Monetary(
1881
+ string="CBS Value",
1882
+ compute="_compute_tax_fields",
1883
+ store=True,
1884
+ precompute=True,
1885
+ readonly=False,
1886
+ )
1887
+
1888
+ # IBS Fields
1889
+ ibs_tax_id = fields.Many2one(
1890
+ comodel_name="l10n_br_fiscal.tax",
1891
+ string="Tax IBS",
1892
+ domain=(
1893
+ f"[('tax_domain', '=', '{TAX_DOMAIN_IBS}'), '|', "
1894
+ "('cst_in_id.code', 'like', cst_code_prefix_like), "
1895
+ "('cst_out_id.code', 'like', cst_code_prefix_like)]"
1896
+ ),
1897
+ compute="_compute_tax_fields",
1898
+ store=True,
1899
+ precompute=True,
1900
+ readonly=False,
1901
+ )
1902
+
1903
+ ibs_cst_id = fields.Many2one(
1904
+ comodel_name="l10n_br_fiscal.cst",
1905
+ string="CST IBS",
1906
+ domain="[('cst_type', '=', fiscal_operation_type),('tax_domain', '=', 'ibs')]",
1907
+ compute="_compute_tax_fields",
1908
+ store=True,
1909
+ precompute=True,
1910
+ readonly=False,
1911
+ )
1912
+
1913
+ ibs_cst_code = fields.Char(
1914
+ related="ibs_cst_id.code", string="IBS CST Code", store=True
1915
+ )
1916
+
1917
+ ibs_base_type = fields.Selection(
1918
+ selection=TAX_BASE_TYPE,
1919
+ string="IBS Base Type",
1920
+ compute="_compute_tax_fields",
1921
+ store=True,
1922
+ precompute=True,
1923
+ readonly=False,
1924
+ )
1925
+
1926
+ ibs_base = fields.Monetary(
1927
+ string="IBS Base",
1928
+ compute="_compute_tax_fields",
1929
+ store=True,
1930
+ precompute=True,
1931
+ readonly=False,
1932
+ )
1933
+
1934
+ ibs_percent = fields.Float(
1935
+ string="IBS %",
1936
+ compute="_compute_tax_fields",
1937
+ store=True,
1938
+ precompute=True,
1939
+ readonly=False,
1940
+ )
1941
+
1942
+ ibs_reduction = fields.Float(
1943
+ string="IBS % Reduction",
1944
+ compute="_compute_tax_fields",
1945
+ store=True,
1946
+ precompute=True,
1947
+ readonly=False,
1948
+ )
1949
+
1950
+ ibs_value = fields.Monetary(
1951
+ string="IBS Value",
1952
+ compute="_compute_tax_fields",
1953
+ store=True,
1954
+ precompute=True,
1955
+ readonly=False,
1956
+ )
1957
+
1958
+ # CBS/IBS Tax Classification
1959
+ tax_classification_id = fields.Many2one(
1960
+ comodel_name="l10n_br_fiscal.tax.classification",
1961
+ string="Tax Classification",
1962
+ compute="_compute_fiscal_tax_ids",
1963
+ store=True,
1964
+ precompute=True,
1965
+ readonly=False,
1966
+ )
1967
+
1968
+ cst_code_prefix_like = fields.Char(
1969
+ compute="_compute_cst_code_prefix_like",
1970
+ help="Helper field to filter taxes by CST code prefix (3 chars) using LIKE.",
1971
+ )
1972
+
1973
+ @api.depends("tax_classification_id")
1974
+ def _compute_cst_code_prefix_like(self):
1975
+ for rec in self:
1976
+ code = rec.tax_classification_id.code if rec.tax_classification_id else ""
1977
+ prefix = (code or "")[:3]
1978
+ # Avoid matching all records when the prefix is not available yet.
1979
+ rec.cst_code_prefix_like = (
1980
+ f"{prefix}%" if len(prefix) == 3 else "__no_match__%"
1981
+ )
1982
+
581
1983
  # II Fields
582
1984
  ii_tax_id = fields.Many2one(
583
1985
  comodel_name="l10n_br_fiscal.tax",
584
1986
  string="Tax II",
585
1987
  domain=[("tax_domain", "=", TAX_DOMAIN_II)],
1988
+ compute="_compute_tax_fields",
1989
+ store=True,
1990
+ precompute=True,
1991
+ readonly=False,
586
1992
  )
587
1993
 
588
- ii_base = fields.Monetary(string="II Base")
1994
+ ii_base = fields.Monetary(
1995
+ string="II Base",
1996
+ compute="_compute_tax_fields",
1997
+ store=True,
1998
+ precompute=True,
1999
+ readonly=False,
2000
+ )
589
2001
 
590
- ii_percent = fields.Float(string="II %")
2002
+ ii_percent = fields.Float(
2003
+ string="II %",
2004
+ compute="_compute_tax_fields",
2005
+ store=True,
2006
+ precompute=True,
2007
+ readonly=False,
2008
+ )
591
2009
 
592
- ii_value = fields.Monetary(string="II Value")
2010
+ ii_value = fields.Monetary(
2011
+ string="II Value",
2012
+ compute="_compute_tax_fields",
2013
+ store=True,
2014
+ precompute=True,
2015
+ readonly=False,
2016
+ )
593
2017
 
594
2018
  ii_iof_value = fields.Monetary(string="IOF Value")
595
2019
 
@@ -601,6 +2025,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
601
2025
  comodel_name="l10n_br_fiscal.tax",
602
2026
  string="Tax COFINS",
603
2027
  domain=[("tax_domain", "=", TAX_DOMAIN_COFINS)],
2028
+ compute="_compute_tax_fields",
2029
+ store=True,
2030
+ precompute=True,
2031
+ readonly=False,
604
2032
  )
605
2033
 
606
2034
  cofins_cst_id = fields.Many2one(
@@ -609,6 +2037,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
609
2037
  domain="['|', ('cst_type', '=', fiscal_operation_type),"
610
2038
  "('cst_type', '=', 'all'),"
611
2039
  "('tax_domain', '=', 'cofins')]",
2040
+ compute="_compute_tax_fields",
2041
+ store=True,
2042
+ precompute=True,
2043
+ readonly=False,
612
2044
  )
613
2045
 
614
2046
  cofins_cst_code = fields.Char(
@@ -618,16 +2050,43 @@ class FiscalDocumentLineMixin(models.AbstractModel):
618
2050
  cofins_base_type = fields.Selection(
619
2051
  selection=TAX_BASE_TYPE,
620
2052
  string="COFINS Base Type",
621
- default=TAX_BASE_TYPE_PERCENT,
2053
+ compute="_compute_tax_fields",
2054
+ store=True,
2055
+ precompute=True,
2056
+ readonly=False,
622
2057
  )
623
2058
 
624
- cofins_base = fields.Monetary(string="COFINS Base")
2059
+ cofins_base = fields.Monetary(
2060
+ string="COFINS Base",
2061
+ compute="_compute_tax_fields",
2062
+ store=True,
2063
+ precompute=True,
2064
+ readonly=False,
2065
+ )
625
2066
 
626
- cofins_percent = fields.Float(string="COFINS %")
2067
+ cofins_percent = fields.Float(
2068
+ string="COFINS %",
2069
+ compute="_compute_tax_fields",
2070
+ store=True,
2071
+ precompute=True,
2072
+ readonly=False,
2073
+ )
627
2074
 
628
- cofins_reduction = fields.Float(string="COFINS % Reduction")
2075
+ cofins_reduction = fields.Float(
2076
+ string="COFINS % Reduction",
2077
+ compute="_compute_tax_fields",
2078
+ store=True,
2079
+ precompute=True,
2080
+ readonly=False,
2081
+ )
629
2082
 
630
- cofins_value = fields.Monetary(string="COFINS Value")
2083
+ cofins_value = fields.Monetary(
2084
+ string="COFINS Value",
2085
+ compute="_compute_tax_fields",
2086
+ store=True,
2087
+ precompute=True,
2088
+ readonly=False,
2089
+ )
631
2090
 
632
2091
  cofins_base_id = fields.Many2one(
633
2092
  comodel_name="l10n_br_fiscal.tax.pis.cofins.base", string="COFINS Base Code"
@@ -642,6 +2101,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
642
2101
  comodel_name="l10n_br_fiscal.tax",
643
2102
  string="Tax COFINS ST",
644
2103
  domain=[("tax_domain", "=", TAX_DOMAIN_COFINS_ST)],
2104
+ compute="_compute_tax_fields",
2105
+ store=True,
2106
+ precompute=True,
2107
+ readonly=False,
645
2108
  )
646
2109
 
647
2110
  cofinsst_cst_id = fields.Many2one(
@@ -650,6 +2113,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
650
2113
  domain="['|', ('cst_type', '=', fiscal_operation_type),"
651
2114
  "('cst_type', '=', 'all'),"
652
2115
  "('tax_domain', '=', 'cofinsst')]",
2116
+ compute="_compute_tax_fields",
2117
+ store=True,
2118
+ precompute=True,
2119
+ readonly=False,
653
2120
  )
654
2121
 
655
2122
  cofinsst_cst_code = fields.Char(
@@ -659,42 +2126,104 @@ class FiscalDocumentLineMixin(models.AbstractModel):
659
2126
  cofinsst_base_type = fields.Selection(
660
2127
  selection=TAX_BASE_TYPE,
661
2128
  string="COFINS ST Base Type",
662
- default=TAX_BASE_TYPE_PERCENT,
2129
+ compute="_compute_tax_fields",
2130
+ store=True,
2131
+ precompute=True,
2132
+ readonly=False,
663
2133
  )
664
2134
 
665
- cofinsst_base = fields.Monetary(string="COFINS ST Base")
2135
+ cofinsst_base = fields.Monetary(
2136
+ string="COFINS ST Base",
2137
+ compute="_compute_tax_fields",
2138
+ store=True,
2139
+ precompute=True,
2140
+ readonly=False,
2141
+ )
666
2142
 
667
- cofinsst_percent = fields.Float(string="COFINS ST %")
2143
+ cofinsst_percent = fields.Float(
2144
+ string="COFINS ST %",
2145
+ compute="_compute_tax_fields",
2146
+ store=True,
2147
+ precompute=True,
2148
+ readonly=False,
2149
+ )
668
2150
 
669
- cofinsst_reduction = fields.Float(string="COFINS ST % Reduction")
2151
+ cofinsst_reduction = fields.Float(
2152
+ string="COFINS ST % Reduction",
2153
+ compute="_compute_tax_fields",
2154
+ store=True,
2155
+ precompute=True,
2156
+ readonly=False,
2157
+ )
670
2158
 
671
- cofinsst_value = fields.Monetary(string="COFINS ST Value")
2159
+ cofinsst_value = fields.Monetary(
2160
+ string="COFINS ST Value",
2161
+ compute="_compute_tax_fields",
2162
+ store=True,
2163
+ precompute=True,
2164
+ readonly=False,
2165
+ )
672
2166
 
673
2167
  cofins_wh_tax_id = fields.Many2one(
674
2168
  comodel_name="l10n_br_fiscal.tax",
675
2169
  string="Tax COFINS RET",
676
2170
  domain=[("tax_domain", "=", TAX_DOMAIN_COFINS_WH)],
2171
+ compute="_compute_tax_fields",
2172
+ store=True,
2173
+ precompute=True,
2174
+ readonly=False,
677
2175
  )
678
2176
 
679
2177
  cofins_wh_base_type = fields.Selection(
680
2178
  selection=TAX_BASE_TYPE,
681
2179
  string="COFINS WH Base Type",
682
- default=TAX_BASE_TYPE_PERCENT,
2180
+ compute="_compute_tax_fields",
2181
+ store=True,
2182
+ precompute=True,
2183
+ readonly=False,
683
2184
  )
684
2185
 
685
- cofins_wh_base = fields.Monetary(string="COFINS RET Base")
2186
+ cofins_wh_base = fields.Monetary(
2187
+ string="COFINS RET Base",
2188
+ compute="_compute_tax_fields",
2189
+ store=True,
2190
+ precompute=True,
2191
+ readonly=False,
2192
+ )
686
2193
 
687
- cofins_wh_percent = fields.Float(string="COFINS RET %")
2194
+ cofins_wh_percent = fields.Float(
2195
+ string="COFINS RET %",
2196
+ compute="_compute_tax_fields",
2197
+ store=True,
2198
+ precompute=True,
2199
+ readonly=False,
2200
+ )
688
2201
 
689
- cofins_wh_reduction = fields.Float(string="COFINS RET % Reduction")
2202
+ cofins_wh_reduction = fields.Float(
2203
+ string="COFINS RET % Reduction",
2204
+ compute="_compute_tax_fields",
2205
+ store=True,
2206
+ precompute=True,
2207
+ readonly=False,
2208
+ )
690
2209
 
691
- cofins_wh_value = fields.Monetary(string="COFINS RET Value")
2210
+ cofins_wh_value = fields.Monetary(
2211
+ string="COFINS RET Value",
2212
+ compute="_compute_tax_fields",
2213
+ store=True,
2214
+ precompute=True,
2215
+ readonly=False,
2216
+ )
692
2217
 
693
2218
  # PIS
694
2219
  pis_tax_id = fields.Many2one(
695
2220
  comodel_name="l10n_br_fiscal.tax",
696
2221
  string="Tax PIS",
697
2222
  domain=[("tax_domain", "=", TAX_DOMAIN_PIS)],
2223
+ compute="_compute_tax_fields",
2224
+ store=True,
2225
+ precompute=True,
2226
+ readonly=False,
698
2227
  )
699
2228
 
700
2229
  pis_cst_id = fields.Many2one(
@@ -703,6 +2232,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
703
2232
  domain="['|', ('cst_type', '=', fiscal_operation_type),"
704
2233
  "('cst_type', '=', 'all'),"
705
2234
  "('tax_domain', '=', 'pis')]",
2235
+ compute="_compute_tax_fields",
2236
+ store=True,
2237
+ precompute=True,
2238
+ readonly=False,
706
2239
  )
707
2240
 
708
2241
  pis_cst_code = fields.Char(
@@ -710,16 +2243,45 @@ class FiscalDocumentLineMixin(models.AbstractModel):
710
2243
  )
711
2244
 
712
2245
  pis_base_type = fields.Selection(
713
- selection=TAX_BASE_TYPE, string="PIS Base Type", default=TAX_BASE_TYPE_PERCENT
2246
+ selection=TAX_BASE_TYPE,
2247
+ string="PIS Base Type",
2248
+ compute="_compute_tax_fields",
2249
+ store=True,
2250
+ precompute=True,
2251
+ readonly=False,
714
2252
  )
715
2253
 
716
- pis_base = fields.Monetary(string="PIS Base")
2254
+ pis_base = fields.Monetary(
2255
+ string="PIS Base",
2256
+ compute="_compute_tax_fields",
2257
+ store=True,
2258
+ precompute=True,
2259
+ readonly=False,
2260
+ )
717
2261
 
718
- pis_percent = fields.Float(string="PIS %")
2262
+ pis_percent = fields.Float(
2263
+ string="PIS %",
2264
+ compute="_compute_tax_fields",
2265
+ store=True,
2266
+ precompute=True,
2267
+ readonly=False,
2268
+ )
719
2269
 
720
- pis_reduction = fields.Float(string="PIS % Reduction")
2270
+ pis_reduction = fields.Float(
2271
+ string="PIS % Reduction",
2272
+ compute="_compute_tax_fields",
2273
+ store=True,
2274
+ precompute=True,
2275
+ readonly=False,
2276
+ )
721
2277
 
722
- pis_value = fields.Monetary(string="PIS Value")
2278
+ pis_value = fields.Monetary(
2279
+ string="PIS Value",
2280
+ compute="_compute_tax_fields",
2281
+ store=True,
2282
+ precompute=True,
2283
+ readonly=False,
2284
+ )
723
2285
 
724
2286
  pis_base_id = fields.Many2one(
725
2287
  comodel_name="l10n_br_fiscal.tax.pis.cofins.base", string="PIS Base Code"
@@ -734,6 +2296,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
734
2296
  comodel_name="l10n_br_fiscal.tax",
735
2297
  string="Tax PIS ST",
736
2298
  domain=[("tax_domain", "=", TAX_DOMAIN_PIS_ST)],
2299
+ compute="_compute_tax_fields",
2300
+ store=True,
2301
+ precompute=True,
2302
+ readonly=False,
737
2303
  )
738
2304
 
739
2305
  pisst_cst_id = fields.Many2one(
@@ -742,6 +2308,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
742
2308
  domain="['|', ('cst_type', '=', fiscal_operation_type),"
743
2309
  "('cst_type', '=', 'all'),"
744
2310
  "('tax_domain', '=', 'pisst')]",
2311
+ compute="_compute_tax_fields",
2312
+ store=True,
2313
+ precompute=True,
2314
+ readonly=False,
745
2315
  )
746
2316
 
747
2317
  pisst_cst_code = fields.Char(
@@ -751,148 +2321,392 @@ class FiscalDocumentLineMixin(models.AbstractModel):
751
2321
  pisst_base_type = fields.Selection(
752
2322
  selection=TAX_BASE_TYPE,
753
2323
  string="PIS ST Base Type",
754
- default=TAX_BASE_TYPE_PERCENT,
2324
+ compute="_compute_tax_fields",
2325
+ store=True,
2326
+ precompute=True,
2327
+ readonly=False,
755
2328
  )
756
2329
 
757
- pisst_base = fields.Monetary(string="PIS ST Base")
2330
+ pisst_base = fields.Monetary(
2331
+ string="PIS ST Base",
2332
+ compute="_compute_tax_fields",
2333
+ store=True,
2334
+ precompute=True,
2335
+ readonly=False,
2336
+ )
758
2337
 
759
- pisst_percent = fields.Float(string="PIS ST %")
2338
+ pisst_percent = fields.Float(
2339
+ string="PIS ST %",
2340
+ compute="_compute_tax_fields",
2341
+ store=True,
2342
+ precompute=True,
2343
+ readonly=False,
2344
+ )
760
2345
 
761
- pisst_reduction = fields.Float(string="PIS ST % Reduction")
2346
+ pisst_reduction = fields.Float(
2347
+ string="PIS ST % Reduction",
2348
+ compute="_compute_tax_fields",
2349
+ store=True,
2350
+ precompute=True,
2351
+ readonly=False,
2352
+ )
762
2353
 
763
- pisst_value = fields.Monetary(string="PIS ST Value")
2354
+ pisst_value = fields.Monetary(
2355
+ string="PIS ST Value",
2356
+ compute="_compute_tax_fields",
2357
+ store=True,
2358
+ precompute=True,
2359
+ readonly=False,
2360
+ )
764
2361
 
765
2362
  pis_wh_tax_id = fields.Many2one(
766
2363
  comodel_name="l10n_br_fiscal.tax",
767
2364
  string="Tax PIS RET",
768
2365
  domain=[("tax_domain", "=", TAX_DOMAIN_PIS_WH)],
2366
+ compute="_compute_tax_fields",
2367
+ store=True,
2368
+ precompute=True,
2369
+ readonly=False,
769
2370
  )
770
2371
 
771
2372
  pis_wh_base_type = fields.Selection(
772
2373
  selection=TAX_BASE_TYPE,
773
2374
  string="PIS WH Base Type",
774
- default=TAX_BASE_TYPE_PERCENT,
2375
+ compute="_compute_tax_fields",
2376
+ store=True,
2377
+ precompute=True,
2378
+ readonly=False,
775
2379
  )
776
2380
 
777
- pis_wh_base = fields.Monetary(string="PIS RET Base")
2381
+ pis_wh_base = fields.Monetary(
2382
+ string="PIS RET Base",
2383
+ compute="_compute_tax_fields",
2384
+ store=True,
2385
+ precompute=True,
2386
+ readonly=False,
2387
+ )
778
2388
 
779
- pis_wh_percent = fields.Float(string="PIS RET %")
2389
+ pis_wh_percent = fields.Float(
2390
+ string="PIS RET %",
2391
+ compute="_compute_tax_fields",
2392
+ store=True,
2393
+ precompute=True,
2394
+ readonly=False,
2395
+ )
780
2396
 
781
- pis_wh_reduction = fields.Float(string="PIS RET % Reduction")
2397
+ pis_wh_reduction = fields.Float(
2398
+ string="PIS RET % Reduction",
2399
+ compute="_compute_tax_fields",
2400
+ store=True,
2401
+ precompute=True,
2402
+ readonly=False,
2403
+ )
782
2404
 
783
- pis_wh_value = fields.Monetary(string="PIS RET Value")
2405
+ pis_wh_value = fields.Monetary(
2406
+ string="PIS RET Value",
2407
+ compute="_compute_tax_fields",
2408
+ store=True,
2409
+ precompute=True,
2410
+ readonly=False,
2411
+ )
784
2412
 
785
2413
  # CSLL Fields
786
2414
  csll_tax_id = fields.Many2one(
787
2415
  comodel_name="l10n_br_fiscal.tax",
788
2416
  string="Tax CSLL",
789
2417
  domain=[("tax_domain", "=", TAX_DOMAIN_CSLL)],
2418
+ compute="_compute_tax_fields",
2419
+ store=True,
2420
+ precompute=True,
2421
+ readonly=False,
790
2422
  )
791
2423
 
792
- csll_base = fields.Monetary(string="CSLL Base")
2424
+ csll_base = fields.Monetary(
2425
+ string="CSLL Base",
2426
+ compute="_compute_tax_fields",
2427
+ store=True,
2428
+ precompute=True,
2429
+ readonly=False,
2430
+ )
793
2431
 
794
- csll_percent = fields.Float(string="CSLL %")
2432
+ csll_percent = fields.Float(
2433
+ string="CSLL %",
2434
+ compute="_compute_tax_fields",
2435
+ store=True,
2436
+ precompute=True,
2437
+ readonly=False,
2438
+ )
795
2439
 
796
- csll_reduction = fields.Float(string="CSLL % Reduction")
2440
+ csll_reduction = fields.Float(
2441
+ string="CSLL % Reduction",
2442
+ compute="_compute_tax_fields",
2443
+ store=True,
2444
+ precompute=True,
2445
+ readonly=False,
2446
+ )
797
2447
 
798
- csll_value = fields.Monetary(string="CSLL Value")
2448
+ csll_value = fields.Monetary(
2449
+ string="CSLL Value",
2450
+ compute="_compute_tax_fields",
2451
+ store=True,
2452
+ precompute=True,
2453
+ readonly=False,
2454
+ )
799
2455
 
800
2456
  csll_wh_tax_id = fields.Many2one(
801
2457
  comodel_name="l10n_br_fiscal.tax",
802
2458
  string="Tax CSLL RET",
803
2459
  domain=[("tax_domain", "=", TAX_DOMAIN_CSLL_WH)],
2460
+ compute="_compute_tax_fields",
2461
+ store=True,
2462
+ precompute=True,
2463
+ readonly=False,
804
2464
  )
805
2465
 
806
- csll_wh_base = fields.Monetary(string="CSLL RET Base")
2466
+ csll_wh_base = fields.Monetary(
2467
+ string="CSLL RET Base",
2468
+ compute="_compute_tax_fields",
2469
+ store=True,
2470
+ precompute=True,
2471
+ readonly=False,
2472
+ )
807
2473
 
808
- csll_wh_percent = fields.Float(string="CSLL RET %")
2474
+ csll_wh_percent = fields.Float(
2475
+ string="CSLL RET %",
2476
+ compute="_compute_tax_fields",
2477
+ store=True,
2478
+ precompute=True,
2479
+ readonly=False,
2480
+ )
809
2481
 
810
- csll_wh_reduction = fields.Float(string="CSLL RET % Reduction")
2482
+ csll_wh_reduction = fields.Float(
2483
+ string="CSLL RET % Reduction",
2484
+ compute="_compute_tax_fields",
2485
+ store=True,
2486
+ precompute=True,
2487
+ readonly=False,
2488
+ )
811
2489
 
812
- csll_wh_value = fields.Monetary(string="CSLL RET Value")
2490
+ csll_wh_value = fields.Monetary(
2491
+ string="CSLL RET Value",
2492
+ compute="_compute_tax_fields",
2493
+ store=True,
2494
+ precompute=True,
2495
+ readonly=False,
2496
+ )
813
2497
 
814
2498
  irpj_tax_id = fields.Many2one(
815
2499
  comodel_name="l10n_br_fiscal.tax",
816
2500
  string="Tax IRPJ",
817
2501
  domain=[("tax_domain", "=", TAX_DOMAIN_IRPJ)],
2502
+ compute="_compute_tax_fields",
2503
+ store=True,
2504
+ precompute=True,
2505
+ readonly=False,
818
2506
  )
819
2507
 
820
- irpj_base = fields.Monetary(string="IRPJ Base")
2508
+ irpj_base = fields.Monetary(
2509
+ string="IRPJ Base",
2510
+ compute="_compute_tax_fields",
2511
+ store=True,
2512
+ precompute=True,
2513
+ readonly=False,
2514
+ )
821
2515
 
822
- irpj_percent = fields.Float(string="IRPJ %")
2516
+ irpj_percent = fields.Float(
2517
+ string="IRPJ %",
2518
+ compute="_compute_tax_fields",
2519
+ store=True,
2520
+ precompute=True,
2521
+ readonly=False,
2522
+ )
823
2523
 
824
- irpj_reduction = fields.Float(string="IRPJ % Reduction")
2524
+ irpj_reduction = fields.Float(
2525
+ string="IRPJ % Reduction",
2526
+ compute="_compute_tax_fields",
2527
+ store=True,
2528
+ precompute=True,
2529
+ readonly=False,
2530
+ )
825
2531
 
826
- irpj_value = fields.Monetary(string="IRPJ Value")
2532
+ irpj_value = fields.Monetary(
2533
+ string="IRPJ Value",
2534
+ compute="_compute_tax_fields",
2535
+ store=True,
2536
+ precompute=True,
2537
+ readonly=False,
2538
+ )
827
2539
 
828
2540
  irpj_wh_tax_id = fields.Many2one(
829
2541
  comodel_name="l10n_br_fiscal.tax",
830
2542
  string="Tax IRPJ RET",
831
2543
  domain=[("tax_domain", "=", TAX_DOMAIN_IRPJ_WH)],
2544
+ compute="_compute_tax_fields",
2545
+ store=True,
2546
+ precompute=True,
2547
+ readonly=False,
832
2548
  )
833
2549
 
834
- irpj_wh_base = fields.Monetary(string="IRPJ RET Base")
2550
+ irpj_wh_base = fields.Monetary(
2551
+ string="IRPJ RET Base",
2552
+ compute="_compute_tax_fields",
2553
+ store=True,
2554
+ precompute=True,
2555
+ readonly=False,
2556
+ )
835
2557
 
836
- irpj_wh_percent = fields.Float(string="IRPJ RET %")
2558
+ irpj_wh_percent = fields.Float(
2559
+ string="IRPJ RET %",
2560
+ compute="_compute_tax_fields",
2561
+ store=True,
2562
+ precompute=True,
2563
+ readonly=False,
2564
+ )
837
2565
 
838
- irpj_wh_reduction = fields.Float(string="IRPJ RET % Reduction")
2566
+ irpj_wh_reduction = fields.Float(
2567
+ string="IRPJ RET % Reduction",
2568
+ compute="_compute_tax_fields",
2569
+ store=True,
2570
+ precompute=True,
2571
+ readonly=False,
2572
+ )
839
2573
 
840
- irpj_wh_value = fields.Monetary(string="IRPJ RET Value")
2574
+ irpj_wh_value = fields.Monetary(
2575
+ string="IRPJ RET Value",
2576
+ compute="_compute_tax_fields",
2577
+ store=True,
2578
+ precompute=True,
2579
+ readonly=False,
2580
+ )
841
2581
 
842
2582
  inss_tax_id = fields.Many2one(
843
2583
  comodel_name="l10n_br_fiscal.tax",
844
2584
  string="Tax INSS",
845
2585
  domain=[("tax_domain", "=", TAX_DOMAIN_INSS)],
2586
+ compute="_compute_tax_fields",
2587
+ store=True,
2588
+ precompute=True,
2589
+ readonly=False,
846
2590
  )
847
2591
 
848
- inss_base = fields.Monetary(string="INSS Base")
2592
+ inss_base = fields.Monetary(
2593
+ string="INSS Base",
2594
+ compute="_compute_tax_fields",
2595
+ store=True,
2596
+ precompute=True,
2597
+ readonly=False,
2598
+ )
849
2599
 
850
- inss_percent = fields.Float(string="INSS %")
2600
+ inss_percent = fields.Float(
2601
+ string="INSS %",
2602
+ compute="_compute_tax_fields",
2603
+ store=True,
2604
+ precompute=True,
2605
+ readonly=False,
2606
+ )
851
2607
 
852
- inss_reduction = fields.Float(string="INSS % Reduction")
2608
+ inss_reduction = fields.Float(
2609
+ string="INSS % Reduction",
2610
+ compute="_compute_tax_fields",
2611
+ store=True,
2612
+ precompute=True,
2613
+ readonly=False,
2614
+ )
853
2615
 
854
- inss_value = fields.Monetary(string="INSS Value")
2616
+ inss_value = fields.Monetary(
2617
+ string="INSS Value",
2618
+ compute="_compute_tax_fields",
2619
+ store=True,
2620
+ precompute=True,
2621
+ readonly=False,
2622
+ )
855
2623
 
856
2624
  inss_wh_tax_id = fields.Many2one(
857
2625
  comodel_name="l10n_br_fiscal.tax",
858
2626
  string="Tax INSS RET",
859
2627
  domain=[("tax_domain", "=", TAX_DOMAIN_INSS_WH)],
2628
+ compute="_compute_tax_fields",
2629
+ store=True,
2630
+ precompute=True,
2631
+ readonly=False,
860
2632
  )
861
2633
 
862
- inss_wh_base = fields.Monetary(string="INSS RET Base")
2634
+ inss_wh_base = fields.Monetary(
2635
+ string="INSS RET Base",
2636
+ compute="_compute_tax_fields",
2637
+ store=True,
2638
+ precompute=True,
2639
+ readonly=False,
2640
+ )
863
2641
 
864
- inss_wh_percent = fields.Float(string="INSS RET %")
2642
+ inss_wh_percent = fields.Float(
2643
+ string="INSS RET %",
2644
+ compute="_compute_tax_fields",
2645
+ store=True,
2646
+ precompute=True,
2647
+ readonly=False,
2648
+ )
865
2649
 
866
- inss_wh_reduction = fields.Float(string="INSS RET % Reduction")
2650
+ inss_wh_reduction = fields.Float(
2651
+ string="INSS RET % Reduction",
2652
+ compute="_compute_tax_fields",
2653
+ store=True,
2654
+ precompute=True,
2655
+ readonly=False,
2656
+ )
867
2657
 
868
- inss_wh_value = fields.Monetary(string="INSS RET Value")
2658
+ inss_wh_value = fields.Monetary(
2659
+ string="INSS RET Value",
2660
+ compute="_compute_tax_fields",
2661
+ store=True,
2662
+ precompute=True,
2663
+ readonly=False,
2664
+ )
869
2665
 
870
- simple_value = fields.Monetary(string="National Simple Taxes")
2666
+ simple_value = fields.Monetary(
2667
+ string="National Simple Taxes",
2668
+ compute="_compute_tax_fields",
2669
+ store=True,
2670
+ precompute=True,
2671
+ readonly=False,
2672
+ )
871
2673
 
872
2674
  simple_without_icms_value = fields.Monetary(
873
- string="National Simple Taxes without ICMS"
2675
+ string="National Simple Taxes without ICMS",
2676
+ compute="_compute_tax_fields",
2677
+ store=True,
2678
+ precompute=True,
2679
+ readonly=False,
874
2680
  )
875
2681
 
876
2682
  comment_ids = fields.Many2many(
877
2683
  comodel_name="l10n_br_fiscal.comment",
878
- relation="l10n_br_fiscal_document_line_mixin_comment_rel",
879
- column1="document_line_mixin_id",
880
- column2="comment_id",
881
2684
  string="Comments",
882
2685
  domain=[("object", "=", FISCAL_COMMENT_LINE)],
2686
+ compute="_compute_comment_ids",
2687
+ store=True,
2688
+ precompute=True,
2689
+ readonly=False,
883
2690
  )
884
2691
 
885
- additional_data = fields.Text()
886
-
887
2692
  manual_additional_data = fields.Text(
888
2693
  help="Additional data manually entered by user"
889
2694
  )
890
2695
 
891
- estimate_tax = fields.Monetary()
2696
+ estimate_tax = fields.Monetary(
2697
+ compute="_compute_tax_fields",
2698
+ store=True,
2699
+ precompute=True,
2700
+ readonly=False,
2701
+ )
892
2702
 
893
2703
  cnae_id = fields.Many2one(
2704
+ related="city_taxation_code_id.cnae_id",
894
2705
  comodel_name="l10n_br_fiscal.cnae",
895
2706
  string="CNAE Code",
2707
+ store=True,
2708
+ precompute=True,
2709
+ readonly=False,
896
2710
  )
897
2711
 
898
2712
  @api.depends("company_id")