odoo-addon-l10n-br-fiscal 18.0.2.0.0.10__py3-none-any.whl → 18.0.7.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of odoo-addon-l10n-br-fiscal might be problematic. Click here for more details.
- odoo/addons/l10n_br_fiscal/README.rst +1 -1
- odoo/addons/l10n_br_fiscal/__manifest__.py +7 -3
- odoo/addons/l10n_br_fiscal/constants/fiscal.py +64 -18
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cest.csv +1043 -983
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cst.csv +58 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.document.type.csv +1 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.operation.indicator.csv +27 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.classification.csv +163 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.csv +31 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.group.csv +3 -0
- odoo/addons/l10n_br_fiscal/data/operation_data.xml +1 -1
- odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +3 -179
- odoo/addons/l10n_br_fiscal/demo/fiscal_document_nfse_demo.xml +0 -4
- odoo/addons/l10n_br_fiscal/demo/fiscal_operation_demo.xml +2 -2
- odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +665 -79
- odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +713 -102
- odoo/addons/l10n_br_fiscal/migrations/18.0.3.0.0/pre-migration.py +30 -0
- odoo/addons/l10n_br_fiscal/models/__init__.py +2 -2
- odoo/addons/l10n_br_fiscal/models/comment.py +3 -1
- odoo/addons/l10n_br_fiscal/models/data_abstract.py +9 -6
- odoo/addons/l10n_br_fiscal/models/document.py +27 -8
- odoo/addons/l10n_br_fiscal/models/document_line.py +51 -8
- odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +1107 -35
- odoo/addons/l10n_br_fiscal/models/document_mixin.py +244 -6
- odoo/addons/l10n_br_fiscal/models/document_related.py +1 -1
- odoo/addons/l10n_br_fiscal/models/document_serie.py +33 -0
- odoo/addons/l10n_br_fiscal/models/icms_regulation.py +1 -1
- odoo/addons/l10n_br_fiscal/models/operation_dashboard.py +3 -2
- odoo/addons/l10n_br_fiscal/models/operation_indicator.py +58 -0
- odoo/addons/l10n_br_fiscal/models/operation_line.py +28 -0
- odoo/addons/l10n_br_fiscal/models/partner_profile.py +6 -0
- odoo/addons/l10n_br_fiscal/models/product_template.py +4 -0
- odoo/addons/l10n_br_fiscal/models/res_company.py +17 -0
- odoo/addons/l10n_br_fiscal/models/res_partner.py +17 -0
- odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +8 -0
- odoo/addons/l10n_br_fiscal/models/tax.py +7 -3
- odoo/addons/l10n_br_fiscal/models/tax_classification.py +81 -0
- odoo/addons/l10n_br_fiscal/security/fiscal_security.xml +6 -16
- odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +7 -2
- odoo/addons/l10n_br_fiscal/static/description/index.html +1 -1
- odoo/addons/l10n_br_fiscal/tests/__init__.py +2 -0
- odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +175 -10
- odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +13 -42
- odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +0 -5
- odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_serie.py +60 -0
- odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +2 -5
- odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +110 -0
- odoo/addons/l10n_br_fiscal/views/document_line_mixin_view.xml +107 -4
- odoo/addons/l10n_br_fiscal/views/document_line_view.xml +7 -3
- odoo/addons/l10n_br_fiscal/views/document_view.xml +34 -15
- odoo/addons/l10n_br_fiscal/views/icms_regulation_view.xml +1 -5
- odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +30 -0
- odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +16 -9
- odoo/addons/l10n_br_fiscal/views/nbs_view.xml +1 -5
- odoo/addons/l10n_br_fiscal/views/ncm_view.xml +1 -5
- odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +3 -3
- odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +75 -0
- odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +4 -5
- odoo/addons/l10n_br_fiscal/views/operation_view.xml +1 -5
- odoo/addons/l10n_br_fiscal/views/product_product_view.xml +33 -6
- odoo/addons/l10n_br_fiscal/views/product_template_view.xml +22 -4
- odoo/addons/l10n_br_fiscal/views/res_company_view.xml +6 -0
- odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +10 -0
- odoo/addons/l10n_br_fiscal/views/service_type_view.xml +1 -5
- odoo/addons/l10n_br_fiscal/views/tax_classification.xml +108 -0
- odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +1 -5
- odoo/addons/l10n_br_fiscal/views/tax_view.xml +2 -2
- odoo/addons/l10n_br_fiscal/wizards/__init__.py +1 -1
- odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +1 -1
- odoo/addons/l10n_br_fiscal/wizards/document_import_wizard.py +234 -0
- odoo/addons/l10n_br_fiscal/wizards/{document_import_wizard_mixin.xml → document_import_wizard.xml} +26 -7
- {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/METADATA +3 -3
- {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/RECORD +75 -68
- odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +0 -837
- odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +0 -349
- odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +0 -129
- {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/WHEEL +0 -0
- {odoo_addon_l10n_br_fiscal-18.0.2.0.0.10.dist-info → odoo_addon_l10n_br_fiscal-18.0.7.1.0.dist-info}/top_level.txt +0 -0
|
@@ -1,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
|
|
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,
|
|
@@ -66,16 +77,9 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
66
77
|
ISSQN, etc.), covering their respective bases, rates, and
|
|
67
78
|
calculated values.
|
|
68
79
|
- Line-level totals and cost components.
|
|
69
|
-
|
|
70
|
-
It inherits computational logic, onchange handlers, and other complex
|
|
71
|
-
methods from `l10n_br_fiscal.document.line.mixin.methods`. Models
|
|
72
|
-
that represent actual document lines (e.g.,
|
|
73
|
-
`l10n_br_fiscal.document.line`) should inherit this mixin to
|
|
74
|
-
acquire the necessary fiscal field definitions and associated behaviors.
|
|
75
80
|
"""
|
|
76
81
|
|
|
77
82
|
_name = "l10n_br_fiscal.document.line.mixin"
|
|
78
|
-
_inherit = "l10n_br_fiscal.document.line.mixin.methods"
|
|
79
83
|
_description = "Document Fiscal Mixin"
|
|
80
84
|
|
|
81
85
|
@api.model
|
|
@@ -98,6 +102,810 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
98
102
|
domain = [("state", "=", "approved")]
|
|
99
103
|
return domain
|
|
100
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
|
+
|
|
101
909
|
currency_id = fields.Many2one(
|
|
102
910
|
comodel_name="res.currency",
|
|
103
911
|
string="Currency",
|
|
@@ -113,7 +921,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
113
921
|
tax_icms_or_issqn = fields.Selection(
|
|
114
922
|
selection=TAX_ICMS_OR_ISSQN,
|
|
115
923
|
string="ICMS or ISSQN Tax",
|
|
116
|
-
|
|
924
|
+
compute="_compute_product_fiscal_fields",
|
|
925
|
+
store=True,
|
|
926
|
+
readonly=False,
|
|
927
|
+
precompute=True,
|
|
117
928
|
)
|
|
118
929
|
|
|
119
930
|
partner_is_public_entity = fields.Boolean(related="partner_id.is_public_entity")
|
|
@@ -125,26 +936,58 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
125
936
|
|
|
126
937
|
price_unit = fields.Float(
|
|
127
938
|
digits="Product Price",
|
|
128
|
-
|
|
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",
|
|
129
953
|
store=True,
|
|
130
954
|
precompute=True,
|
|
131
955
|
readonly=False,
|
|
132
956
|
)
|
|
133
957
|
|
|
134
|
-
|
|
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
|
|
135
963
|
|
|
136
964
|
partner_company_type = fields.Selection(related="partner_id.company_type")
|
|
137
965
|
|
|
138
|
-
uom_id = fields.Many2one(
|
|
966
|
+
uom_id = fields.Many2one(
|
|
967
|
+
comodel_name="uom.uom",
|
|
968
|
+
string="UOM",
|
|
969
|
+
)
|
|
139
970
|
|
|
140
971
|
quantity = fields.Float(
|
|
141
972
|
digits="Product Unit of Measure",
|
|
142
973
|
)
|
|
143
974
|
|
|
144
|
-
fiscal_type = fields.Selection(
|
|
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
|
+
)
|
|
145
982
|
|
|
146
983
|
ncm_id = fields.Many2one(
|
|
147
|
-
comodel_name="l10n_br_fiscal.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,
|
|
148
991
|
)
|
|
149
992
|
|
|
150
993
|
nbm_id = fields.Many2one(
|
|
@@ -152,6 +995,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
152
995
|
index=True,
|
|
153
996
|
string="NBM",
|
|
154
997
|
domain="[('ncm_ids', '=', ncm_id)]",
|
|
998
|
+
compute="_compute_product_fiscal_fields",
|
|
999
|
+
store=True,
|
|
1000
|
+
readonly=False,
|
|
1001
|
+
precompute=True,
|
|
155
1002
|
)
|
|
156
1003
|
|
|
157
1004
|
cest_id = fields.Many2one(
|
|
@@ -159,10 +1006,20 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
159
1006
|
index=True,
|
|
160
1007
|
string="CEST",
|
|
161
1008
|
domain="[('ncm_ids', '=', ncm_id)]",
|
|
1009
|
+
compute="_compute_product_fiscal_fields",
|
|
1010
|
+
store=True,
|
|
1011
|
+
readonly=False,
|
|
1012
|
+
precompute=True,
|
|
162
1013
|
)
|
|
163
1014
|
|
|
164
1015
|
nbs_id = fields.Many2one(
|
|
165
|
-
comodel_name="l10n_br_fiscal.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,
|
|
166
1023
|
)
|
|
167
1024
|
|
|
168
1025
|
fiscal_operation_id = fields.Many2one(
|
|
@@ -184,8 +1041,12 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
184
1041
|
fiscal_operation_line_id = fields.Many2one(
|
|
185
1042
|
comodel_name="l10n_br_fiscal.operation.line",
|
|
186
1043
|
string="Operation Line",
|
|
1044
|
+
compute="_compute_fiscal_operation_line_id",
|
|
187
1045
|
domain="[('fiscal_operation_id', '=', fiscal_operation_id), "
|
|
188
1046
|
"('state', '=', 'approved')]",
|
|
1047
|
+
store=True,
|
|
1048
|
+
precompute=True,
|
|
1049
|
+
readonly=False,
|
|
189
1050
|
)
|
|
190
1051
|
|
|
191
1052
|
cfop_id = fields.Many2one(
|
|
@@ -258,11 +1119,11 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
258
1119
|
compute="_compute_fiscal_amounts",
|
|
259
1120
|
)
|
|
260
1121
|
|
|
261
|
-
|
|
1122
|
+
fiscal_amount_untaxed = fields.Monetary(
|
|
262
1123
|
compute="_compute_fiscal_amounts",
|
|
263
1124
|
)
|
|
264
1125
|
|
|
265
|
-
|
|
1126
|
+
fiscal_amount_tax = fields.Monetary(
|
|
266
1127
|
compute="_compute_fiscal_amounts",
|
|
267
1128
|
)
|
|
268
1129
|
|
|
@@ -270,7 +1131,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
270
1131
|
compute="_compute_fiscal_amounts",
|
|
271
1132
|
)
|
|
272
1133
|
|
|
273
|
-
|
|
1134
|
+
fiscal_amount_total = fields.Monetary(
|
|
274
1135
|
compute="_compute_fiscal_amounts",
|
|
275
1136
|
)
|
|
276
1137
|
|
|
@@ -289,14 +1150,35 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
289
1150
|
compute="_compute_fiscal_amounts",
|
|
290
1151
|
)
|
|
291
1152
|
|
|
292
|
-
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
|
+
)
|
|
293
1159
|
|
|
294
|
-
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
|
+
)
|
|
295
1166
|
|
|
296
|
-
amount_tax_withholding = fields.Monetary(
|
|
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
|
+
)
|
|
297
1174
|
|
|
298
1175
|
fiscal_genre_id = fields.Many2one(
|
|
299
|
-
comodel_name="l10n_br_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,
|
|
300
1182
|
)
|
|
301
1183
|
|
|
302
1184
|
fiscal_genre_code = fields.Char(
|
|
@@ -307,10 +1189,27 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
307
1189
|
comodel_name="l10n_br_fiscal.service.type",
|
|
308
1190
|
string="Service Type LC 166",
|
|
309
1191
|
domain="[('internal_type', '=', 'normal')]",
|
|
1192
|
+
compute="_compute_product_fiscal_fields",
|
|
1193
|
+
store=True,
|
|
1194
|
+
readonly=False,
|
|
1195
|
+
precompute=True,
|
|
310
1196
|
)
|
|
311
1197
|
|
|
312
1198
|
city_taxation_code_id = fields.Many2one(
|
|
313
|
-
comodel_name="l10n_br_fiscal.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,
|
|
314
1213
|
)
|
|
315
1214
|
|
|
316
1215
|
partner_order = fields.Char(string="Partner Order (xPed)", size=15)
|
|
@@ -330,7 +1229,10 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
330
1229
|
|
|
331
1230
|
issqn_fg_city_id = fields.Many2one(
|
|
332
1231
|
comodel_name="res.city",
|
|
1232
|
+
related="city_taxation_code_id.city_id",
|
|
333
1233
|
string="ISSQN City",
|
|
1234
|
+
store=True,
|
|
1235
|
+
precompute=True,
|
|
334
1236
|
)
|
|
335
1237
|
|
|
336
1238
|
# vDeducao
|
|
@@ -479,7 +1381,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
479
1381
|
icms_base_type = fields.Selection(
|
|
480
1382
|
selection=ICMS_BASE_TYPE,
|
|
481
1383
|
string="ICMS Base Type",
|
|
482
|
-
default=ICMS_BASE_TYPE_DEFAULT,
|
|
483
1384
|
compute="_compute_tax_fields",
|
|
484
1385
|
store=True,
|
|
485
1386
|
precompute=True,
|
|
@@ -487,7 +1388,12 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
487
1388
|
)
|
|
488
1389
|
|
|
489
1390
|
icms_origin = fields.Selection(
|
|
490
|
-
selection=ICMS_ORIGIN,
|
|
1391
|
+
selection=ICMS_ORIGIN,
|
|
1392
|
+
string="ICMS Origin",
|
|
1393
|
+
compute="_compute_product_fiscal_fields",
|
|
1394
|
+
store=True,
|
|
1395
|
+
readonly=False,
|
|
1396
|
+
precompute=True,
|
|
491
1397
|
)
|
|
492
1398
|
|
|
493
1399
|
# vBC - Valor da base de cálculo do ICMS
|
|
@@ -561,7 +1467,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
561
1467
|
icmsst_base_type = fields.Selection(
|
|
562
1468
|
selection=ICMS_ST_BASE_TYPE,
|
|
563
1469
|
string="ICMS ST Base Type",
|
|
564
|
-
default=ICMS_ST_BASE_TYPE_DEFAULT,
|
|
565
1470
|
compute="_compute_tax_fields",
|
|
566
1471
|
store=True,
|
|
567
1472
|
precompute=True,
|
|
@@ -857,7 +1762,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
857
1762
|
ipi_base_type = fields.Selection(
|
|
858
1763
|
selection=TAX_BASE_TYPE,
|
|
859
1764
|
string="IPI Base Type",
|
|
860
|
-
default=TAX_BASE_TYPE_PERCENT,
|
|
861
1765
|
compute="_compute_tax_fields",
|
|
862
1766
|
store=True,
|
|
863
1767
|
precompute=True,
|
|
@@ -911,6 +1815,171 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
911
1815
|
|
|
912
1816
|
ipi_devol_value = fields.Monetary(string="Valor do IPI devolvido")
|
|
913
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
|
+
|
|
914
1983
|
# II Fields
|
|
915
1984
|
ii_tax_id = fields.Many2one(
|
|
916
1985
|
comodel_name="l10n_br_fiscal.tax",
|
|
@@ -981,7 +2050,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
981
2050
|
cofins_base_type = fields.Selection(
|
|
982
2051
|
selection=TAX_BASE_TYPE,
|
|
983
2052
|
string="COFINS Base Type",
|
|
984
|
-
default=TAX_BASE_TYPE_PERCENT,
|
|
985
2053
|
compute="_compute_tax_fields",
|
|
986
2054
|
store=True,
|
|
987
2055
|
precompute=True,
|
|
@@ -1058,7 +2126,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
1058
2126
|
cofinsst_base_type = fields.Selection(
|
|
1059
2127
|
selection=TAX_BASE_TYPE,
|
|
1060
2128
|
string="COFINS ST Base Type",
|
|
1061
|
-
default=TAX_BASE_TYPE_PERCENT,
|
|
1062
2129
|
compute="_compute_tax_fields",
|
|
1063
2130
|
store=True,
|
|
1064
2131
|
precompute=True,
|
|
@@ -1110,7 +2177,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
1110
2177
|
cofins_wh_base_type = fields.Selection(
|
|
1111
2178
|
selection=TAX_BASE_TYPE,
|
|
1112
2179
|
string="COFINS WH Base Type",
|
|
1113
|
-
default=TAX_BASE_TYPE_PERCENT,
|
|
1114
2180
|
compute="_compute_tax_fields",
|
|
1115
2181
|
store=True,
|
|
1116
2182
|
precompute=True,
|
|
@@ -1179,7 +2245,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
1179
2245
|
pis_base_type = fields.Selection(
|
|
1180
2246
|
selection=TAX_BASE_TYPE,
|
|
1181
2247
|
string="PIS Base Type",
|
|
1182
|
-
default=TAX_BASE_TYPE_PERCENT,
|
|
1183
2248
|
compute="_compute_tax_fields",
|
|
1184
2249
|
store=True,
|
|
1185
2250
|
precompute=True,
|
|
@@ -1256,7 +2321,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
1256
2321
|
pisst_base_type = fields.Selection(
|
|
1257
2322
|
selection=TAX_BASE_TYPE,
|
|
1258
2323
|
string="PIS ST Base Type",
|
|
1259
|
-
default=TAX_BASE_TYPE_PERCENT,
|
|
1260
2324
|
compute="_compute_tax_fields",
|
|
1261
2325
|
store=True,
|
|
1262
2326
|
precompute=True,
|
|
@@ -1308,7 +2372,6 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
1308
2372
|
pis_wh_base_type = fields.Selection(
|
|
1309
2373
|
selection=TAX_BASE_TYPE,
|
|
1310
2374
|
string="PIS WH Base Type",
|
|
1311
|
-
default=TAX_BASE_TYPE_PERCENT,
|
|
1312
2375
|
compute="_compute_tax_fields",
|
|
1313
2376
|
store=True,
|
|
1314
2377
|
precompute=True,
|
|
@@ -1620,7 +2683,7 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
1620
2683
|
comodel_name="l10n_br_fiscal.comment",
|
|
1621
2684
|
string="Comments",
|
|
1622
2685
|
domain=[("object", "=", FISCAL_COMMENT_LINE)],
|
|
1623
|
-
compute="
|
|
2686
|
+
compute="_compute_comment_ids",
|
|
1624
2687
|
store=True,
|
|
1625
2688
|
precompute=True,
|
|
1626
2689
|
readonly=False,
|
|
@@ -1630,11 +2693,20 @@ class FiscalDocumentLineMixin(models.AbstractModel):
|
|
|
1630
2693
|
help="Additional data manually entered by user"
|
|
1631
2694
|
)
|
|
1632
2695
|
|
|
1633
|
-
estimate_tax = fields.Monetary(
|
|
2696
|
+
estimate_tax = fields.Monetary(
|
|
2697
|
+
compute="_compute_tax_fields",
|
|
2698
|
+
store=True,
|
|
2699
|
+
precompute=True,
|
|
2700
|
+
readonly=False,
|
|
2701
|
+
)
|
|
1634
2702
|
|
|
1635
2703
|
cnae_id = fields.Many2one(
|
|
2704
|
+
related="city_taxation_code_id.cnae_id",
|
|
1636
2705
|
comodel_name="l10n_br_fiscal.cnae",
|
|
1637
2706
|
string="CNAE Code",
|
|
2707
|
+
store=True,
|
|
2708
|
+
precompute=True,
|
|
2709
|
+
readonly=False,
|
|
1638
2710
|
)
|
|
1639
2711
|
|
|
1640
2712
|
@api.depends("company_id")
|