odoo-addon-l10n-br-fiscal 16.0.19.4.0__py3-none-any.whl → 17.0.4.0.0.1__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 (90) hide show
  1. odoo/addons/l10n_br_fiscal/README.rst +10 -10
  2. odoo/addons/l10n_br_fiscal/__init__.py +2 -3
  3. odoo/addons/l10n_br_fiscal/__manifest__.py +3 -7
  4. odoo/addons/l10n_br_fiscal/constants/fiscal.py +0 -66
  5. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cest.csv +983 -1043
  6. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cst.csv +0 -58
  7. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.csv +0 -31
  8. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.group.csv +0 -3
  9. odoo/addons/l10n_br_fiscal/data/product_data.xml +2 -2
  10. odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +88 -0
  11. odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +28 -1031
  12. odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +1078 -1197
  13. odoo/addons/l10n_br_fiscal/models/__init__.py +2 -2
  14. odoo/addons/l10n_br_fiscal/models/comment.py +20 -18
  15. odoo/addons/l10n_br_fiscal/models/data_abstract.py +11 -12
  16. odoo/addons/l10n_br_fiscal/models/document.py +4 -30
  17. odoo/addons/l10n_br_fiscal/models/document_line.py +3 -16
  18. odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +27 -1048
  19. odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +883 -0
  20. odoo/addons/l10n_br_fiscal/models/document_mixin.py +3 -241
  21. odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +239 -0
  22. odoo/addons/l10n_br_fiscal/models/document_serie.py +5 -3
  23. odoo/addons/l10n_br_fiscal/models/invalidate_number.py +0 -6
  24. odoo/addons/l10n_br_fiscal/models/operation.py +0 -11
  25. odoo/addons/l10n_br_fiscal/models/operation_dashboard.py +2 -3
  26. odoo/addons/l10n_br_fiscal/models/operation_line.py +0 -28
  27. odoo/addons/l10n_br_fiscal/models/partner_profile.py +0 -6
  28. odoo/addons/l10n_br_fiscal/models/product_template.py +0 -4
  29. odoo/addons/l10n_br_fiscal/models/res_company.py +0 -18
  30. odoo/addons/l10n_br_fiscal/models/res_partner.py +0 -17
  31. odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +0 -8
  32. odoo/addons/l10n_br_fiscal/models/tax_definition.py +2 -35
  33. odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +0 -6
  34. odoo/addons/l10n_br_fiscal/static/description/index.html +8 -8
  35. odoo/addons/l10n_br_fiscal/tests/__init__.py +0 -1
  36. odoo/addons/l10n_br_fiscal/tests/test_cnae.py +2 -3
  37. odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +10 -37
  38. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +28 -4
  39. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +4 -0
  40. odoo/addons/l10n_br_fiscal/tests/test_service_type.py +2 -3
  41. odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +4 -2
  42. odoo/addons/l10n_br_fiscal/views/cest_view.xml +2 -2
  43. odoo/addons/l10n_br_fiscal/views/cnae_view.xml +0 -1
  44. odoo/addons/l10n_br_fiscal/views/document_line_mixin_view.xml +170 -243
  45. odoo/addons/l10n_br_fiscal/views/document_line_view.xml +7 -11
  46. odoo/addons/l10n_br_fiscal/views/document_related_view.xml +15 -11
  47. odoo/addons/l10n_br_fiscal/views/document_serie_view.xml +1 -1
  48. odoo/addons/l10n_br_fiscal/views/document_view.xml +32 -44
  49. odoo/addons/l10n_br_fiscal/views/invalidate_number_view.xml +12 -12
  50. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +0 -31
  51. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +2 -18
  52. odoo/addons/l10n_br_fiscal/views/nbm_view.xml +2 -2
  53. odoo/addons/l10n_br_fiscal/views/nbs_view.xml +1 -1
  54. odoo/addons/l10n_br_fiscal/views/ncm_view.xml +3 -3
  55. odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +27 -18
  56. odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +2 -5
  57. odoo/addons/l10n_br_fiscal/views/operation_view.xml +39 -16
  58. odoo/addons/l10n_br_fiscal/views/partner_profile_view.xml +3 -6
  59. odoo/addons/l10n_br_fiscal/views/product_genre_view.xml +2 -2
  60. odoo/addons/l10n_br_fiscal/views/product_product_view.xml +17 -45
  61. odoo/addons/l10n_br_fiscal/views/product_template_view.xml +16 -35
  62. odoo/addons/l10n_br_fiscal/views/res_company_view.xml +17 -18
  63. odoo/addons/l10n_br_fiscal/views/res_config_settings_view.xml +37 -98
  64. odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +3 -13
  65. odoo/addons/l10n_br_fiscal/views/service_type_view.xml +2 -3
  66. odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +60 -29
  67. odoo/addons/l10n_br_fiscal/views/tax_estimate_view.xml +2 -2
  68. odoo/addons/l10n_br_fiscal/views/tax_group_view.xml +4 -4
  69. odoo/addons/l10n_br_fiscal/views/tax_view.xml +14 -16
  70. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +1 -1
  71. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.xml +2 -5
  72. {odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info → odoo_addon_l10n_br_fiscal-17.0.4.0.0.1.dist-info}/METADATA +16 -16
  73. {odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info → odoo_addon_l10n_br_fiscal-17.0.4.0.0.1.dist-info}/RECORD +77 -88
  74. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.operation.indicator.csv +0 -27
  75. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.classification.csv +0 -163
  76. odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.5/pre-migration.py +0 -15
  77. odoo/addons/l10n_br_fiscal/migrations/16.0.2.0.0/pre-migration.py +0 -25
  78. odoo/addons/l10n_br_fiscal/migrations/16.0.2.15.0/pre-migration.py +0 -19
  79. odoo/addons/l10n_br_fiscal/migrations/16.0.4.0.0/pre-migration.py +0 -220
  80. odoo/addons/l10n_br_fiscal/migrations/16.0.5.0.0/pre-migration.py +0 -33
  81. odoo/addons/l10n_br_fiscal/migrations/16.0.5.2.0/pre-migration.py +0 -21
  82. odoo/addons/l10n_br_fiscal/models/operation_indicator.py +0 -58
  83. odoo/addons/l10n_br_fiscal/models/tax_classification.py +0 -81
  84. odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +0 -110
  85. odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +0 -75
  86. odoo/addons/l10n_br_fiscal/views/tax_classification.xml +0 -110
  87. /odoo/addons/l10n_br_fiscal/migrations/{16.0.13.0.0 → 17.0.2.0.0}/pre-migration.py +0 -0
  88. /odoo/addons/l10n_br_fiscal/migrations/{16.0.14.0.0 → 17.0.3.0.0}/pre-migration.py +0 -0
  89. {odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info → odoo_addon_l10n_br_fiscal-17.0.4.0.0.1.dist-info}/WHEEL +0 -0
  90. {odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info → odoo_addon_l10n_br_fiscal-17.0.4.0.0.1.dist-info}/top_level.txt +0 -0
@@ -1,29 +1,18 @@
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 copy import deepcopy
5
-
6
- from lxml import etree
7
- from lxml.builder import E
8
-
9
- from odoo import Command, api, fields, models
4
+ from odoo import api, fields, models
10
5
 
11
6
  from ..constants.fiscal import (
12
- CFOP_DESTINATION_EXPORT,
13
- FINAL_CUSTOMER,
14
7
  FISCAL_COMMENT_LINE,
15
- FISCAL_IN,
16
- FISCAL_TAX_ID_FIELDS,
17
8
  PRODUCT_FISCAL_TYPE,
18
9
  TAX_BASE_TYPE,
19
10
  TAX_BASE_TYPE_PERCENT,
20
- TAX_DOMAIN_CBS,
21
11
  TAX_DOMAIN_COFINS,
22
12
  TAX_DOMAIN_COFINS_ST,
23
13
  TAX_DOMAIN_COFINS_WH,
24
14
  TAX_DOMAIN_CSLL,
25
15
  TAX_DOMAIN_CSLL_WH,
26
- TAX_DOMAIN_IBS,
27
16
  TAX_DOMAIN_ICMS,
28
17
  TAX_DOMAIN_ICMS_FCP,
29
18
  TAX_DOMAIN_ICMS_FCP_ST,
@@ -47,7 +36,6 @@ from ..constants.icms import (
47
36
  ICMS_BASE_TYPE,
48
37
  ICMS_BASE_TYPE_DEFAULT,
49
38
  ICMS_ORIGIN,
50
- ICMS_ORIGIN_DEFAULT,
51
39
  ICMS_ST_BASE_TYPE,
52
40
  ICMS_ST_BASE_TYPE_DEFAULT,
53
41
  )
@@ -77,9 +65,16 @@ class FiscalDocumentLineMixin(models.AbstractModel):
77
65
  ISSQN, etc.), covering their respective bases, rates, and
78
66
  calculated values.
79
67
  - Line-level totals and cost components.
68
+
69
+ It inherits computational logic, onchange handlers, and other complex
70
+ methods from `l10n_br_fiscal.document.line.mixin.methods`. Models
71
+ that represent actual document lines (e.g.,
72
+ `l10n_br_fiscal.document.line`) should inherit this mixin to
73
+ acquire the necessary fiscal field definitions and associated behaviors.
80
74
  """
81
75
 
82
76
  _name = "l10n_br_fiscal.document.line.mixin"
77
+ _inherit = "l10n_br_fiscal.document.line.mixin.methods"
83
78
  _description = "Document Fiscal Mixin"
84
79
 
85
80
  @api.model
@@ -102,810 +97,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
102
97
  domain = [("state", "=", "approved")]
103
98
  return domain
104
99
 
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
-
909
100
  currency_id = fields.Many2one(
910
101
  comodel_name="res.currency",
911
102
  string="Currency",
@@ -921,10 +112,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
921
112
  tax_icms_or_issqn = fields.Selection(
922
113
  selection=TAX_ICMS_OR_ISSQN,
923
114
  string="ICMS or ISSQN Tax",
924
- compute="_compute_product_fiscal_fields",
925
- store=True,
926
- readonly=False,
927
- precompute=True,
115
+ default=TAX_DOMAIN_ICMS,
928
116
  )
929
117
 
930
118
  partner_is_public_entity = fields.Boolean(related="partner_id.is_public_entity")
@@ -936,30 +124,13 @@ class FiscalDocumentLineMixin(models.AbstractModel):
936
124
 
937
125
  price_unit = fields.Float(
938
126
  digits="Product Price",
939
- store=True,
940
- )
941
-
942
- partner_id = fields.Many2one(comodel_name="res.partner", string="Partner")
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",
127
+ compute="_compute_price_unit_fiscal",
953
128
  store=True,
954
129
  precompute=True,
955
130
  readonly=False,
956
131
  )
957
132
 
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
133
+ partner_id = fields.Many2one(comodel_name="res.partner", string="Partner")
963
134
 
964
135
  partner_company_type = fields.Selection(related="partner_id.company_type")
965
136
 
@@ -1041,12 +212,8 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1041
212
  fiscal_operation_line_id = fields.Many2one(
1042
213
  comodel_name="l10n_br_fiscal.operation.line",
1043
214
  string="Operation Line",
1044
- compute="_compute_fiscal_operation_line_id",
1045
215
  domain="[('fiscal_operation_id', '=', fiscal_operation_id), "
1046
216
  "('state', '=', 'approved')]",
1047
- store=True,
1048
- precompute=True,
1049
- readonly=False,
1050
217
  )
1051
218
 
1052
219
  cfop_id = fields.Many2one(
@@ -1150,27 +317,11 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1150
317
  compute="_compute_fiscal_amounts",
1151
318
  )
1152
319
 
1153
- amount_tax_included = fields.Monetary(
1154
- compute="_compute_tax_fields",
1155
- store=True,
1156
- precompute=True,
1157
- readonly=False,
1158
- )
320
+ amount_tax_included = fields.Monetary()
1159
321
 
1160
- amount_tax_not_included = fields.Monetary(
1161
- compute="_compute_tax_fields",
1162
- store=True,
1163
- precompute=True,
1164
- readonly=False,
1165
- )
322
+ amount_tax_not_included = fields.Monetary()
1166
323
 
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
- )
324
+ amount_tax_withholding = fields.Monetary(string="Tax Withholding")
1174
325
 
1175
326
  fiscal_genre_id = fields.Many2one(
1176
327
  comodel_name="l10n_br_fiscal.product.genre",
@@ -1197,15 +348,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1197
348
 
1198
349
  city_taxation_code_id = fields.Many2one(
1199
350
  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",
351
+ string="City Taxation Code",
1209
352
  compute="_compute_product_fiscal_fields",
1210
353
  store=True,
1211
354
  readonly=False,
@@ -1229,9 +372,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1229
372
 
1230
373
  issqn_fg_city_id = fields.Many2one(
1231
374
  comodel_name="res.city",
1232
- related="city_taxation_code_id.city_id",
1233
375
  string="ISSQN City",
376
+ compute="_compute_product_fiscal_fields",
1234
377
  store=True,
378
+ readonly=False,
1235
379
  precompute=True,
1236
380
  )
1237
381
 
@@ -1381,6 +525,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1381
525
  icms_base_type = fields.Selection(
1382
526
  selection=ICMS_BASE_TYPE,
1383
527
  string="ICMS Base Type",
528
+ default=ICMS_BASE_TYPE_DEFAULT,
1384
529
  compute="_compute_tax_fields",
1385
530
  store=True,
1386
531
  precompute=True,
@@ -1467,6 +612,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1467
612
  icmsst_base_type = fields.Selection(
1468
613
  selection=ICMS_ST_BASE_TYPE,
1469
614
  string="ICMS ST Base Type",
615
+ default=ICMS_ST_BASE_TYPE_DEFAULT,
1470
616
  compute="_compute_tax_fields",
1471
617
  store=True,
1472
618
  precompute=True,
@@ -1762,6 +908,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1762
908
  ipi_base_type = fields.Selection(
1763
909
  selection=TAX_BASE_TYPE,
1764
910
  string="IPI Base Type",
911
+ default=TAX_BASE_TYPE_PERCENT,
1765
912
  compute="_compute_tax_fields",
1766
913
  store=True,
1767
914
  precompute=True,
@@ -1815,171 +962,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
1815
962
 
1816
963
  ipi_devol_value = fields.Monetary(string="Valor do IPI devolvido")
1817
964
 
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
-
1983
965
  # II Fields
1984
966
  ii_tax_id = fields.Many2one(
1985
967
  comodel_name="l10n_br_fiscal.tax",
@@ -2050,6 +1032,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
2050
1032
  cofins_base_type = fields.Selection(
2051
1033
  selection=TAX_BASE_TYPE,
2052
1034
  string="COFINS Base Type",
1035
+ default=TAX_BASE_TYPE_PERCENT,
2053
1036
  compute="_compute_tax_fields",
2054
1037
  store=True,
2055
1038
  precompute=True,
@@ -2126,6 +1109,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
2126
1109
  cofinsst_base_type = fields.Selection(
2127
1110
  selection=TAX_BASE_TYPE,
2128
1111
  string="COFINS ST Base Type",
1112
+ default=TAX_BASE_TYPE_PERCENT,
2129
1113
  compute="_compute_tax_fields",
2130
1114
  store=True,
2131
1115
  precompute=True,
@@ -2177,6 +1161,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
2177
1161
  cofins_wh_base_type = fields.Selection(
2178
1162
  selection=TAX_BASE_TYPE,
2179
1163
  string="COFINS WH Base Type",
1164
+ default=TAX_BASE_TYPE_PERCENT,
2180
1165
  compute="_compute_tax_fields",
2181
1166
  store=True,
2182
1167
  precompute=True,
@@ -2245,6 +1230,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
2245
1230
  pis_base_type = fields.Selection(
2246
1231
  selection=TAX_BASE_TYPE,
2247
1232
  string="PIS Base Type",
1233
+ default=TAX_BASE_TYPE_PERCENT,
2248
1234
  compute="_compute_tax_fields",
2249
1235
  store=True,
2250
1236
  precompute=True,
@@ -2321,6 +1307,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
2321
1307
  pisst_base_type = fields.Selection(
2322
1308
  selection=TAX_BASE_TYPE,
2323
1309
  string="PIS ST Base Type",
1310
+ default=TAX_BASE_TYPE_PERCENT,
2324
1311
  compute="_compute_tax_fields",
2325
1312
  store=True,
2326
1313
  precompute=True,
@@ -2372,6 +1359,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
2372
1359
  pis_wh_base_type = fields.Selection(
2373
1360
  selection=TAX_BASE_TYPE,
2374
1361
  string="PIS WH Base Type",
1362
+ default=TAX_BASE_TYPE_PERCENT,
2375
1363
  compute="_compute_tax_fields",
2376
1364
  store=True,
2377
1365
  precompute=True,
@@ -2693,20 +1681,11 @@ class FiscalDocumentLineMixin(models.AbstractModel):
2693
1681
  help="Additional data manually entered by user"
2694
1682
  )
2695
1683
 
2696
- estimate_tax = fields.Monetary(
2697
- compute="_compute_tax_fields",
2698
- store=True,
2699
- precompute=True,
2700
- readonly=False,
2701
- )
1684
+ estimate_tax = fields.Monetary()
2702
1685
 
2703
1686
  cnae_id = fields.Many2one(
2704
- related="city_taxation_code_id.cnae_id",
2705
1687
  comodel_name="l10n_br_fiscal.cnae",
2706
1688
  string="CNAE Code",
2707
- store=True,
2708
- precompute=True,
2709
- readonly=False,
2710
1689
  )
2711
1690
 
2712
1691
  @api.depends("company_id")