odoo-addon-l10n-br-fiscal 16.0.2.17.0__py3-none-any.whl → 16.0.19.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- odoo/addons/l10n_br_fiscal/README.rst +11 -4
- odoo/addons/l10n_br_fiscal/__manifest__.py +20 -12
- 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.cfop.csv +620 -620
- 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.legal.nature.csv +82 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.nbs.csv +791 -764
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.operation.indicator.csv +27 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.partner.profile.csv +11 -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 +32 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.group.csv +3 -0
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal_icms_tax_definition_data.xml +340 -352
- odoo/addons/l10n_br_fiscal/data/operation_data.xml +1 -1
- odoo/addons/l10n_br_fiscal/data/simplified_tax_data.xml +5 -5
- odoo/addons/l10n_br_fiscal/data/uom.alias.csv +25 -0
- odoo/addons/l10n_br_fiscal/data/uom_data.xml +104 -33
- odoo/addons/l10n_br_fiscal/demo/__init__.py +21 -15
- odoo/addons/l10n_br_fiscal/demo/company_demo.xml +6 -0
- odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +3 -377
- odoo/addons/l10n_br_fiscal/demo/fiscal_document_nfse_demo.xml +0 -12
- odoo/addons/l10n_br_fiscal/demo/fiscal_operation_demo.xml +2 -2
- odoo/addons/l10n_br_fiscal/demo/icms_tax_definition_demo.xml +5 -2
- odoo/addons/l10n_br_fiscal/demo/res_users_demo.xml +2 -2
- odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +1161 -804
- odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +22 -22
- odoo/addons/l10n_br_fiscal/migrations/16.0.13.0.0/pre-migration.py +25 -0
- odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.0/pre-migration.py +30 -0
- odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.5/pre-migration.py +15 -0
- odoo/addons/l10n_br_fiscal/migrations/16.0.4.0.0/pre-migration.py +220 -0
- odoo/addons/l10n_br_fiscal/migrations/16.0.5.0.0/pre-migration.py +33 -0
- odoo/addons/l10n_br_fiscal/migrations/16.0.5.2.0/pre-migration.py +21 -0
- odoo/addons/l10n_br_fiscal/models/__init__.py +3 -8
- odoo/addons/l10n_br_fiscal/models/cest.py +0 -8
- odoo/addons/l10n_br_fiscal/models/cfop.py +91 -0
- odoo/addons/l10n_br_fiscal/models/city_taxation_code.py +1 -3
- odoo/addons/l10n_br_fiscal/models/comment.py +2 -2
- odoo/addons/l10n_br_fiscal/models/cst.py +0 -1
- odoo/addons/l10n_br_fiscal/models/data_abstract.py +26 -0
- odoo/addons/l10n_br_fiscal/models/data_ncm_nbs_abstract.py +1 -1
- odoo/addons/l10n_br_fiscal/models/document.py +131 -222
- odoo/addons/l10n_br_fiscal/models/document_line.py +82 -5
- odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +1952 -138
- odoo/addons/l10n_br_fiscal/models/document_mixin.py +741 -6
- odoo/addons/l10n_br_fiscal/models/document_related.py +12 -9
- odoo/addons/l10n_br_fiscal/models/document_serie.py +33 -0
- odoo/addons/l10n_br_fiscal/models/document_type.py +0 -6
- odoo/addons/l10n_br_fiscal/models/ibpt.py +1 -1
- odoo/addons/l10n_br_fiscal/models/icms_regulation.py +2 -2
- odoo/addons/l10n_br_fiscal/models/invalidate_number.py +4 -5
- odoo/addons/l10n_br_fiscal/models/legal_nature.py +20 -0
- odoo/addons/l10n_br_fiscal/models/nbm.py +0 -8
- odoo/addons/l10n_br_fiscal/models/ncm.py +0 -12
- odoo/addons/l10n_br_fiscal/models/operation.py +49 -15
- 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 +75 -6
- odoo/addons/l10n_br_fiscal/models/partner_profile.py +6 -0
- odoo/addons/l10n_br_fiscal/models/product_mixin.py +24 -21
- odoo/addons/l10n_br_fiscal/models/product_template.py +23 -13
- odoo/addons/l10n_br_fiscal/models/res_company.py +31 -9
- odoo/addons/l10n_br_fiscal/models/res_partner.py +38 -6
- odoo/addons/l10n_br_fiscal/models/simplified_tax.py +0 -3
- odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +8 -0
- odoo/addons/l10n_br_fiscal/models/tax.py +144 -55
- odoo/addons/l10n_br_fiscal/models/tax_classification.py +81 -0
- odoo/addons/l10n_br_fiscal/models/tax_definition.py +72 -23
- odoo/addons/l10n_br_fiscal/models/tax_pis_cofins.py +0 -3
- odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_base.py +1 -1
- odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_credit.py +1 -1
- odoo/addons/l10n_br_fiscal/models/uom_uom.py +15 -30
- odoo/addons/l10n_br_fiscal/security/fiscal_security.xml +11 -27
- odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +11 -10
- odoo/addons/l10n_br_fiscal/static/description/index.html +27 -21
- odoo/addons/l10n_br_fiscal/static/src/js/list_renderer_with_button.esm.js +38 -0
- odoo/addons/l10n_br_fiscal/tests/__init__.py +3 -2
- odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +308 -0
- odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +23 -129
- odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +5 -15
- odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_serie.py +60 -0
- odoo/addons/l10n_br_fiscal/tests/test_ibpt.py +4 -3
- odoo/addons/l10n_br_fiscal/tests/test_icms_regulation.py +2 -2
- odoo/addons/l10n_br_fiscal/tests/test_ncm.py +4 -1
- odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +17 -22
- odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +110 -0
- odoo/addons/l10n_br_fiscal/tools.py +1 -1
- odoo/addons/l10n_br_fiscal/views/cest_view.xml +2 -4
- odoo/addons/l10n_br_fiscal/views/cfop_view.xml +25 -5
- odoo/addons/l10n_br_fiscal/views/city_taxation_code.xml +1 -4
- odoo/addons/l10n_br_fiscal/views/cnae_view.xml +2 -4
- odoo/addons/l10n_br_fiscal/views/comment_view.xml +2 -4
- odoo/addons/l10n_br_fiscal/views/cst_view.xml +6 -8
- odoo/addons/l10n_br_fiscal/views/{document_fiscal_line_mixin_view.xml → document_line_mixin_view.xml} +525 -385
- odoo/addons/l10n_br_fiscal/views/document_line_view.xml +101 -82
- odoo/addons/l10n_br_fiscal/views/document_related_view.xml +44 -46
- odoo/addons/l10n_br_fiscal/views/document_serie_view.xml +2 -6
- odoo/addons/l10n_br_fiscal/views/document_type_view.xml +0 -8
- odoo/addons/l10n_br_fiscal/views/document_view.xml +303 -370
- odoo/addons/l10n_br_fiscal/views/icms_regulation_view.xml +14 -16
- odoo/addons/l10n_br_fiscal/views/icms_relief_view.xml +8 -10
- odoo/addons/l10n_br_fiscal/views/invalidate_number_view.xml +46 -48
- odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +166 -280
- odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +25 -99
- odoo/addons/l10n_br_fiscal/views/legal_nature_view.xml +40 -0
- odoo/addons/l10n_br_fiscal/views/nbm_view.xml +5 -6
- odoo/addons/l10n_br_fiscal/views/nbs_view.xml +5 -6
- odoo/addons/l10n_br_fiscal/views/ncm_view.xml +12 -15
- odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +13 -12
- odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +75 -0
- odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +22 -21
- odoo/addons/l10n_br_fiscal/views/operation_view.xml +4 -19
- odoo/addons/l10n_br_fiscal/views/partner_profile_view.xml +3 -6
- odoo/addons/l10n_br_fiscal/views/product_genre_view.xml +7 -9
- odoo/addons/l10n_br_fiscal/views/product_product_view.xml +37 -14
- odoo/addons/l10n_br_fiscal/views/product_template_view.xml +34 -14
- odoo/addons/l10n_br_fiscal/views/res_company_view.xml +55 -52
- odoo/addons/l10n_br_fiscal/views/res_config_settings_view.xml +23 -28
- odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +22 -2
- odoo/addons/l10n_br_fiscal/views/service_type_view.xml +7 -8
- odoo/addons/l10n_br_fiscal/views/simplified_tax_range_view.xml +0 -2
- odoo/addons/l10n_br_fiscal/views/simplified_tax_view.xml +0 -2
- odoo/addons/l10n_br_fiscal/views/tax_classification.xml +110 -0
- odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +157 -129
- odoo/addons/l10n_br_fiscal/views/tax_estimate_view.xml +0 -2
- odoo/addons/l10n_br_fiscal/views/tax_group_view.xml +3 -6
- odoo/addons/l10n_br_fiscal/views/tax_ipi_control_seal_view.xml +0 -2
- odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_class_view.xml +0 -2
- odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_view.xml +2 -4
- odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_base_view.xml +2 -4
- odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_credit_view.xml +2 -4
- odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_view.xml +5 -7
- odoo/addons/l10n_br_fiscal/views/tax_view.xml +5 -7
- odoo/addons/l10n_br_fiscal/views/uom_uom.xml +24 -17
- odoo/addons/l10n_br_fiscal/wizards/__init__.py +1 -0
- odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +1 -1
- odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +129 -0
- odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.xml +41 -0
- {odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/METADATA +15 -6
- odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info/RECORD +210 -0
- {odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/WHEEL +1 -1
- odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal_email_template.xml +0 -68
- odoo/addons/l10n_br_fiscal/data/partner_profile_data.xml +0 -96
- odoo/addons/l10n_br_fiscal/data/uom_alternative_data.xml +0 -58
- odoo/addons/l10n_br_fiscal/demo/l10n_br_fiscal_document_email.xml +0 -54
- odoo/addons/l10n_br_fiscal/demo/subsequent_operation_demo.xml +0 -10
- odoo/addons/l10n_br_fiscal/models/document_email.py +0 -74
- odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +0 -913
- odoo/addons/l10n_br_fiscal/models/document_mixin_fields.py +0 -473
- odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +0 -269
- odoo/addons/l10n_br_fiscal/models/document_move_mixin.py +0 -261
- odoo/addons/l10n_br_fiscal/models/subsequent_document.py +0 -203
- odoo/addons/l10n_br_fiscal/models/subsequent_operation.py +0 -54
- odoo/addons/l10n_br_fiscal/models/uom_uom_alternative.py +0 -22
- odoo/addons/l10n_br_fiscal/tests/test_subsequent_operation.py +0 -71
- odoo/addons/l10n_br_fiscal/tests/test_uom_uom.py +0 -22
- odoo/addons/l10n_br_fiscal/views/document_email_view.xml +0 -48
- odoo/addons/l10n_br_fiscal/views/subsequent_document_view.xml +0 -43
- odoo/addons/l10n_br_fiscal/views/subsequent_operation_view.xml +0 -21
- odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info/RECORD +0 -205
- {odoo_addon_l10n_br_fiscal-16.0.2.17.0.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/top_level.txt +0 -0
|
@@ -56,7 +56,7 @@ class DocumentRelated(models.Model):
|
|
|
56
56
|
default="cnpj",
|
|
57
57
|
)
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
l10n_br_ie_code = fields.Char(string="Inscr. Estadual/RG", size=16)
|
|
60
60
|
|
|
61
61
|
document_date = fields.Date(string="Data")
|
|
62
62
|
|
|
@@ -87,11 +87,14 @@ class DocumentRelated(models.Model):
|
|
|
87
87
|
for record in self:
|
|
88
88
|
check_cnpj_cpf(record.env, record.cnpj_cpf, self.env.ref("base.br"))
|
|
89
89
|
|
|
90
|
-
@api.constrains("
|
|
90
|
+
@api.constrains("l10n_br_ie_code", "state_id")
|
|
91
91
|
def _check_ie(self):
|
|
92
92
|
for record in self:
|
|
93
93
|
check_ie(
|
|
94
|
-
record.env,
|
|
94
|
+
record.env,
|
|
95
|
+
record.l10n_br_ie_code,
|
|
96
|
+
record.state_id,
|
|
97
|
+
self.env.ref("base.br"),
|
|
95
98
|
)
|
|
96
99
|
|
|
97
100
|
@api.onchange("document_related_id")
|
|
@@ -101,7 +104,7 @@ class DocumentRelated(models.Model):
|
|
|
101
104
|
return False
|
|
102
105
|
|
|
103
106
|
self.document_type_id = related.document_type_id
|
|
104
|
-
self.document_total_amount = related.
|
|
107
|
+
self.document_total_amount = related.fiscal_amount_total
|
|
105
108
|
self.document_total_weight = related.total_weight
|
|
106
109
|
|
|
107
110
|
if related.document_type_id.electronic:
|
|
@@ -112,10 +115,10 @@ class DocumentRelated(models.Model):
|
|
|
112
115
|
self.cnpj_cpf = False
|
|
113
116
|
self.cpfcnpj_type = False
|
|
114
117
|
self.document_date = False
|
|
115
|
-
self.
|
|
118
|
+
self.l10n_br_ie_code = False
|
|
116
119
|
|
|
117
120
|
if related.document_type_id.code in ("01", "04"):
|
|
118
|
-
self.
|
|
121
|
+
self.document_key = False
|
|
119
122
|
self.document_serie = related.document_serie
|
|
120
123
|
self.document_number = related.document_number
|
|
121
124
|
self.state_id = (
|
|
@@ -125,7 +128,7 @@ class DocumentRelated(models.Model):
|
|
|
125
128
|
or False
|
|
126
129
|
)
|
|
127
130
|
|
|
128
|
-
self.cnpj_cpf = related.partner_id and related.partner_id.
|
|
131
|
+
self.cnpj_cpf = related.partner_id and related.partner_id.vat or False
|
|
129
132
|
|
|
130
133
|
if related.partner_id.is_company:
|
|
131
134
|
self.cpfcnpj_type = "cnpj"
|
|
@@ -135,8 +138,8 @@ class DocumentRelated(models.Model):
|
|
|
135
138
|
self.document_date = related.document_date
|
|
136
139
|
|
|
137
140
|
if related.document_type_id.code == "04":
|
|
138
|
-
self.
|
|
139
|
-
related.partner_id and related.partner_id.
|
|
141
|
+
self.l10n_br_ie_code = (
|
|
142
|
+
related.partner_id and related.partner_id.l10n_br_ie_code or False
|
|
140
143
|
)
|
|
141
144
|
|
|
142
145
|
@api.onchange("cnpj_cpf", "cpfcnpj_type")
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
|
4
4
|
|
|
5
5
|
from odoo import _, api, fields, models
|
|
6
|
+
from odoo.exceptions import ValidationError
|
|
6
7
|
|
|
7
8
|
from ..constants.fiscal import (
|
|
8
9
|
DOCUMENT_ISSUER_COMPANY,
|
|
9
10
|
FISCAL_IN_OUT,
|
|
10
11
|
FISCAL_IN_OUT_DEFAULT,
|
|
12
|
+
SITUACAO_EDOC_EM_DIGITACAO,
|
|
11
13
|
)
|
|
12
14
|
|
|
13
15
|
|
|
@@ -55,6 +57,14 @@ class DocumentSerie(models.Model):
|
|
|
55
57
|
string="Invalidate Number Range",
|
|
56
58
|
)
|
|
57
59
|
|
|
60
|
+
_sql_constraints = [
|
|
61
|
+
(
|
|
62
|
+
"document_serie_unique",
|
|
63
|
+
"unique(code, document_type_id, company_id)",
|
|
64
|
+
"A Fiscal Document Serie already exists for this document type.",
|
|
65
|
+
)
|
|
66
|
+
]
|
|
67
|
+
|
|
58
68
|
@api.model
|
|
59
69
|
def _create_sequence(self, values):
|
|
60
70
|
"""Create new no_gap entry sequence for every
|
|
@@ -78,6 +88,29 @@ class DocumentSerie(models.Model):
|
|
|
78
88
|
vals.update({"internal_sequence_id": self._create_sequence(vals)})
|
|
79
89
|
return super().create(vals_list)
|
|
80
90
|
|
|
91
|
+
def write(self, vals):
|
|
92
|
+
if "internal_sequence_id" in vals:
|
|
93
|
+
raise ValidationError(_("You cannot change the internal sequence."))
|
|
94
|
+
if "code" in vals:
|
|
95
|
+
for serie in self:
|
|
96
|
+
if serie.code == vals["code"]:
|
|
97
|
+
continue
|
|
98
|
+
if self.env["l10n_br_fiscal.document"].search_count(
|
|
99
|
+
[
|
|
100
|
+
("document_serie_id", "=", serie.id),
|
|
101
|
+
("state_edoc", "not in", [SITUACAO_EDOC_EM_DIGITACAO]),
|
|
102
|
+
],
|
|
103
|
+
limit=1,
|
|
104
|
+
):
|
|
105
|
+
raise ValidationError(
|
|
106
|
+
_(
|
|
107
|
+
"You cannot change the code of a document "
|
|
108
|
+
"serie %(name)s that is already in use.",
|
|
109
|
+
name=serie.name,
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
return super().write(vals)
|
|
113
|
+
|
|
81
114
|
def name_get(self):
|
|
82
115
|
return [(r.id, f"{r.name}") for r in self]
|
|
83
116
|
|
|
@@ -35,12 +35,6 @@ class DocumentType(models.Model):
|
|
|
35
35
|
required=True,
|
|
36
36
|
)
|
|
37
37
|
|
|
38
|
-
document_email_ids = fields.One2many(
|
|
39
|
-
comodel_name="l10n_br_fiscal.document.email",
|
|
40
|
-
inverse_name="document_type_id",
|
|
41
|
-
string="Email Template Definition",
|
|
42
|
-
)
|
|
43
|
-
|
|
44
38
|
document_serie_ids = fields.One2many(
|
|
45
39
|
comodel_name="l10n_br_fiscal.document.serie",
|
|
46
40
|
inverse_name="document_type_id",
|
|
@@ -45,7 +45,7 @@ def _request(ws_url, params, ibpt_request_timeout=30):
|
|
|
45
45
|
elif response.status_code == requests.codes.service_unavailable:
|
|
46
46
|
raise UserError(_("IBPT Service Unavailable - {!r}").format(ws_url))
|
|
47
47
|
except Exception as e:
|
|
48
|
-
raise UserError(
|
|
48
|
+
raise UserError(f"Error in the request: {e}") from e
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
def get_ibpt_product(
|
|
@@ -50,7 +50,7 @@ class ICMSRegulation(models.Model):
|
|
|
50
50
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
|
51
51
|
_description = "Tax ICMS Regulation"
|
|
52
52
|
|
|
53
|
-
name = fields.
|
|
53
|
+
name = fields.Char(required=True, index=True)
|
|
54
54
|
|
|
55
55
|
icms_imported_tax_id = fields.Many2one(
|
|
56
56
|
comodel_name="l10n_br_fiscal.tax",
|
|
@@ -2101,7 +2101,7 @@ class ICMSRegulation(models.Model):
|
|
|
2101
2101
|
company.state_id != partner.state_id
|
|
2102
2102
|
and partner.ind_ie_dest == NFE_IND_IE_DEST_9
|
|
2103
2103
|
and operation_line.fiscal_operation_type == FISCAL_OUT
|
|
2104
|
-
or operation_line.fiscal_operation_id.fiscal_type
|
|
2104
|
+
or operation_line.fiscal_operation_id.fiscal_type != "return_in"
|
|
2105
2105
|
and operation_line.fiscal_operation_type == FISCAL_IN
|
|
2106
2106
|
):
|
|
2107
2107
|
domain = self._build_map_tax_def_domain(
|
|
@@ -105,11 +105,10 @@ class InvalidateNumber(models.Model):
|
|
|
105
105
|
@api.depends("document_type_id", "document_serie_id", "number_start", "number_end")
|
|
106
106
|
def _compute_name(self):
|
|
107
107
|
for record in self:
|
|
108
|
-
record.name =
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
end=record.number_end,
|
|
108
|
+
record.name = (
|
|
109
|
+
f"{record.document_type_id.type}/"
|
|
110
|
+
f"({record.document_serie_id.name}): "
|
|
111
|
+
f"{record.number_start} - {record.number_end}"
|
|
113
112
|
)
|
|
114
113
|
|
|
115
114
|
def unlink(self):
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright (C) 2025 Renato Lima - Akretion <renato.lima@akretion.com.br>
|
|
2
|
+
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
|
3
|
+
|
|
4
|
+
from odoo import fields, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class LegalNature(models.Model):
|
|
8
|
+
_name = "l10n_br_fiscal.legal.nature"
|
|
9
|
+
_inherit = "l10n_br_fiscal.data.abstract"
|
|
10
|
+
_description = "Legal Nature"
|
|
11
|
+
|
|
12
|
+
code = fields.Char(size=5)
|
|
13
|
+
|
|
14
|
+
_sql_constraints = [
|
|
15
|
+
(
|
|
16
|
+
"fiscal_legal_nature_code_uniq",
|
|
17
|
+
"unique (code)",
|
|
18
|
+
"Legal Nature already exists with this code !",
|
|
19
|
+
)
|
|
20
|
+
]
|
|
@@ -15,26 +15,18 @@ class Nbm(models.Model):
|
|
|
15
15
|
|
|
16
16
|
code_unmasked = fields.Char(size=10, unaccent=False)
|
|
17
17
|
|
|
18
|
-
name = fields.Text(required=True, index=True)
|
|
19
|
-
|
|
20
18
|
product_tmpl_ids = fields.One2many(inverse_name="nbm_id")
|
|
21
19
|
|
|
22
20
|
ncms = fields.Char(string="NCM")
|
|
23
21
|
|
|
24
22
|
ncm_ids = fields.Many2many(
|
|
25
23
|
comodel_name="l10n_br_fiscal.ncm",
|
|
26
|
-
relation="fiscal_nbm_ncm_rel",
|
|
27
|
-
column1="nbm_id",
|
|
28
|
-
column2="ncm_id",
|
|
29
24
|
readonly=True,
|
|
30
25
|
string="NCMs",
|
|
31
26
|
)
|
|
32
27
|
|
|
33
28
|
tax_definition_ids = fields.Many2many(
|
|
34
29
|
comodel_name="l10n_br_fiscal.tax.definition",
|
|
35
|
-
relation="tax_definition_nbm_rel",
|
|
36
|
-
column1="nbm_id",
|
|
37
|
-
column2="tax_definition_id",
|
|
38
30
|
readonly=True,
|
|
39
31
|
string="Tax Definition",
|
|
40
32
|
)
|
|
@@ -44,36 +44,24 @@ class Ncm(models.Model):
|
|
|
44
44
|
|
|
45
45
|
tax_definition_ids = fields.Many2many(
|
|
46
46
|
comodel_name="l10n_br_fiscal.tax.definition",
|
|
47
|
-
relation="tax_definition_ncm_rel",
|
|
48
|
-
column1="ncm_id",
|
|
49
|
-
column2="tax_definition_id",
|
|
50
47
|
readonly=True,
|
|
51
48
|
string="Tax Definition",
|
|
52
49
|
)
|
|
53
50
|
|
|
54
51
|
cest_ids = fields.Many2many(
|
|
55
52
|
comodel_name="l10n_br_fiscal.cest",
|
|
56
|
-
relation="fiscal_cest_ncm_rel",
|
|
57
|
-
column1="ncm_id",
|
|
58
|
-
column2="cest_id",
|
|
59
53
|
readonly=True,
|
|
60
54
|
string="CESTs",
|
|
61
55
|
)
|
|
62
56
|
|
|
63
57
|
nbm_ids = fields.Many2many(
|
|
64
58
|
comodel_name="l10n_br_fiscal.nbm",
|
|
65
|
-
relation="fiscal_nbm_ncm_rel",
|
|
66
|
-
column1="ncm_id",
|
|
67
|
-
column2="nbm_id",
|
|
68
59
|
readonly=True,
|
|
69
60
|
string="NBMs",
|
|
70
61
|
)
|
|
71
62
|
|
|
72
63
|
piscofins_ids = fields.Many2many(
|
|
73
64
|
comodel_name="l10n_br_fiscal.tax.pis.cofins",
|
|
74
|
-
relation="fiscal_pis_cofins_ncm_rel",
|
|
75
|
-
column1="ncm_id",
|
|
76
|
-
column2="piscofins_id",
|
|
77
65
|
readonly=True,
|
|
78
66
|
string="PIS/COFINS",
|
|
79
67
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Copyright (C) 2013 Renato Lima - Akretion
|
|
2
2
|
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
|
3
3
|
|
|
4
|
-
from odoo import _,
|
|
4
|
+
from odoo import _, fields, models
|
|
5
5
|
from odoo.exceptions import UserError
|
|
6
6
|
|
|
7
7
|
from ..constants.fiscal import (
|
|
@@ -17,6 +17,54 @@ from ..constants.fiscal import (
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class Operation(models.Model):
|
|
20
|
+
"""
|
|
21
|
+
Defines a Fiscal Operation, representing the nature and fiscal intent of
|
|
22
|
+
a transaction (e.g., Sale, Return, Import, Industrialization).
|
|
23
|
+
|
|
24
|
+
A Fiscal Operation is a core configuration entity in the Brazilian
|
|
25
|
+
fiscal localization. It serves as a central point to orchestrate how
|
|
26
|
+
fiscal documents and their lines are processed by determining:
|
|
27
|
+
|
|
28
|
+
1. **Transaction Type**: Specifies if the operation is an Inbound
|
|
29
|
+
(e.g., purchase, return from customer), Outbound (e.g., sale,
|
|
30
|
+
return to supplier), or Other type of fiscal movement.
|
|
31
|
+
|
|
32
|
+
2. **Operation Lines (`line_ids`)**: Each Fiscal Operation contains
|
|
33
|
+
one or more `l10n_br_fiscal.operation.line` records. These lines
|
|
34
|
+
define specific rules or conditions (based on partner profiles,
|
|
35
|
+
product types, company tax regime, etc.) under which a
|
|
36
|
+
particular set of fiscal treatments apply. The system selects
|
|
37
|
+
the "best match" operation line based on the context of a
|
|
38
|
+
transaction.
|
|
39
|
+
|
|
40
|
+
3. **CFOP (Código Fiscal de Operações e Prestações)**: The selected
|
|
41
|
+
`operation.line` determines the appropriate CFOP codes
|
|
42
|
+
(internal, external, export) for the transaction line. The CFOP
|
|
43
|
+
itself carries significant fiscal meaning and influences tax
|
|
44
|
+
calculations and reporting.
|
|
45
|
+
|
|
46
|
+
4. **Tax Definitions (`tax_definition_ids` on `operation.line` and `cfop`)**:
|
|
47
|
+
The selected `operation.line` and the determined `cfop` can both
|
|
48
|
+
hold `l10n_br_fiscal.tax.definition` records. These tax
|
|
49
|
+
definitions specify which taxes (ICMS, IPI, PIS, COFINS, etc.)
|
|
50
|
+
apply, along with their respective CST/CSOSN codes and other
|
|
51
|
+
parameters. This linkage allows the Fiscal Operation to drive
|
|
52
|
+
the tax calculation engine.
|
|
53
|
+
|
|
54
|
+
5. **Document Characteristics**: It can also define default behaviors
|
|
55
|
+
or properties for documents generated under this operation, such
|
|
56
|
+
as the electronic document purpose (`edoc_purpose`), default
|
|
57
|
+
price type (sale vs. cost), and links to inverse or return
|
|
58
|
+
operations.
|
|
59
|
+
|
|
60
|
+
Essentially, when a fiscal document is created, the user selects a
|
|
61
|
+
Fiscal Operation. The system then uses this operation and the
|
|
62
|
+
transactional context (partner, product, company) to find the most
|
|
63
|
+
suitable `operation.line`. This line, in turn, provides the CFOP
|
|
64
|
+
and a set of tax definitions, which are then used by the tax engine
|
|
65
|
+
to calculate all applicable taxes.
|
|
66
|
+
"""
|
|
67
|
+
|
|
20
68
|
_name = "l10n_br_fiscal.operation"
|
|
21
69
|
_description = "Fiscal Operation"
|
|
22
70
|
_inherit = ["mail.thread", "mail.activity.mixin"]
|
|
@@ -128,19 +176,10 @@ class Operation(models.Model):
|
|
|
128
176
|
|
|
129
177
|
comment_ids = fields.Many2many(
|
|
130
178
|
comodel_name="l10n_br_fiscal.comment",
|
|
131
|
-
relation="l10n_br_fiscal_operation_comment_rel",
|
|
132
|
-
column1="fiscal_operation_id",
|
|
133
|
-
column2="comment_id",
|
|
134
179
|
domain=[("object", "=", FISCAL_COMMENT_DOCUMENT)],
|
|
135
180
|
string="Comment",
|
|
136
181
|
)
|
|
137
182
|
|
|
138
|
-
operation_subsequent_ids = fields.One2many(
|
|
139
|
-
comodel_name="l10n_br_fiscal.subsequent.operation",
|
|
140
|
-
inverse_name="fiscal_operation_id",
|
|
141
|
-
string="Subsequent Operation",
|
|
142
|
-
)
|
|
143
|
-
|
|
144
183
|
_sql_constraints = [
|
|
145
184
|
(
|
|
146
185
|
"fiscal_operation_code_uniq",
|
|
@@ -265,11 +304,6 @@ class Operation(models.Model):
|
|
|
265
304
|
best_line = max(lines, key=score)
|
|
266
305
|
return best_line
|
|
267
306
|
|
|
268
|
-
@api.onchange("operation_subsequent_ids")
|
|
269
|
-
def _onchange_operation_subsequent_ids(self):
|
|
270
|
-
for sub_operation in self.operation_subsequent_ids:
|
|
271
|
-
sub_operation.fiscal_operation_id = self.id
|
|
272
|
-
|
|
273
307
|
def copy(self, default=None):
|
|
274
308
|
"""
|
|
275
309
|
Inherit copy to edit field code. This is needed because the field is
|
|
@@ -127,7 +127,7 @@ class Operation(models.Model):
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
def open_action(self):
|
|
130
|
-
"""
|
|
130
|
+
"""Return action based on type for related journals"""
|
|
131
131
|
|
|
132
132
|
_fiscal_type_map = {
|
|
133
133
|
"purchase": "in",
|
|
@@ -157,7 +157,8 @@ class Operation(models.Model):
|
|
|
157
157
|
}
|
|
158
158
|
)
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
xmlid = f"l10n_br_fiscal.{action_name}"
|
|
161
|
+
[action] = self.env.ref(xmlid).read()
|
|
161
162
|
action["context"] = ctx
|
|
162
163
|
action["domain"] = self._context.get("use_domain", [])
|
|
163
164
|
action["domain"] += [
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright (C) 2025 Marcel Savegnago <https://escodoo.com.br>
|
|
2
|
+
# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html
|
|
3
|
+
|
|
4
|
+
from odoo import fields, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OperationIndicator(models.Model):
|
|
8
|
+
"""Operation Indicator
|
|
9
|
+
|
|
10
|
+
This model stores the Operation Indicators (cIndOp) table according to
|
|
11
|
+
Annex VII of Technical Note No. 004/2025 from NFS-e Nacional, which is
|
|
12
|
+
part of the Brazilian Tax Reform (Reforma Tributária do Consumo).
|
|
13
|
+
|
|
14
|
+
The cIndOp field is used in the Service Provision Declaration (DPS)
|
|
15
|
+
to categorize consumption operations, as required by Art. 11 of
|
|
16
|
+
Complementary Law No. 214/2025.
|
|
17
|
+
|
|
18
|
+
This table will become mandatory from January 1, 2026.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
_name = "l10n_br_fiscal.operation.indicator"
|
|
22
|
+
_inherit = "l10n_br_fiscal.data.abstract"
|
|
23
|
+
_description = "Operation Indicator"
|
|
24
|
+
_order = "code"
|
|
25
|
+
|
|
26
|
+
code = fields.Char(
|
|
27
|
+
string="Operation Indicator Code",
|
|
28
|
+
required=True,
|
|
29
|
+
index=True,
|
|
30
|
+
size=6,
|
|
31
|
+
help="Operation indicator code according to Annex VII of NT 004/2025 "
|
|
32
|
+
"(e.g., 020101, 030101)",
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
operation_type = fields.Text(
|
|
36
|
+
required=True,
|
|
37
|
+
help="Type of operation according to Art. 11 of Complementary Law "
|
|
38
|
+
"No. 214/2025",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
operation_location = fields.Text(
|
|
42
|
+
string="Operation Location Consideration",
|
|
43
|
+
help="Where the operation is considered to take place according to "
|
|
44
|
+
"the legislation",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
supply_characteristic = fields.Text(
|
|
48
|
+
help="Specific characteristic of the supply execution that determines "
|
|
49
|
+
"the place of supply",
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
supply_location = fields.Text(
|
|
53
|
+
string="DFe Supply Location",
|
|
54
|
+
required=True,
|
|
55
|
+
help="Place of supply to be identified in the Digital Fiscal Document "
|
|
56
|
+
"(DFe), such as supplier establishment, acquirer address, "
|
|
57
|
+
"recipient address, or other locations depending on the operation",
|
|
58
|
+
)
|
|
@@ -37,6 +37,11 @@ class OperationLine(models.Model):
|
|
|
37
37
|
|
|
38
38
|
document_type_id = fields.Many2one(comodel_name="l10n_br_fiscal.document.type")
|
|
39
39
|
|
|
40
|
+
tax_classification_id = fields.Many2one(
|
|
41
|
+
comodel_name="l10n_br_fiscal.tax.classification",
|
|
42
|
+
string="Tax Classification",
|
|
43
|
+
)
|
|
44
|
+
|
|
40
45
|
cfop_internal_id = fields.Many2one(
|
|
41
46
|
comodel_name="l10n_br_fiscal.cfop",
|
|
42
47
|
string="CFOP Internal",
|
|
@@ -65,14 +70,12 @@ class OperationLine(models.Model):
|
|
|
65
70
|
related="fiscal_operation_id.fiscal_operation_type",
|
|
66
71
|
string="Fiscal Operation Type",
|
|
67
72
|
store=True,
|
|
68
|
-
readonly=True,
|
|
69
73
|
)
|
|
70
74
|
|
|
71
75
|
fiscal_type = fields.Selection(
|
|
72
76
|
related="fiscal_operation_id.fiscal_type",
|
|
73
77
|
string="Fiscal Type",
|
|
74
78
|
store=True,
|
|
75
|
-
readonly=True,
|
|
76
79
|
)
|
|
77
80
|
|
|
78
81
|
tax_icms_or_issqn = fields.Selection(
|
|
@@ -120,9 +123,6 @@ class OperationLine(models.Model):
|
|
|
120
123
|
|
|
121
124
|
comment_ids = fields.Many2many(
|
|
122
125
|
comodel_name="l10n_br_fiscal.comment",
|
|
123
|
-
relation="l10n_br_fiscal_operation_line_comment_rel",
|
|
124
|
-
column1="fiscal_operation_line_id",
|
|
125
|
-
column2="comment_id",
|
|
126
126
|
domain=[("object", "=", FISCAL_COMMENT_LINE)],
|
|
127
127
|
string="Comment",
|
|
128
128
|
)
|
|
@@ -155,7 +155,7 @@ class OperationLine(models.Model):
|
|
|
155
155
|
else:
|
|
156
156
|
if not company.document_type_id:
|
|
157
157
|
raise UserError(
|
|
158
|
-
_("You need set a default fiscal document
|
|
158
|
+
_("You need to set a default fiscal document in your company!")
|
|
159
159
|
)
|
|
160
160
|
|
|
161
161
|
document_type = company.document_type_id
|
|
@@ -172,6 +172,13 @@ class OperationLine(models.Model):
|
|
|
172
172
|
cfop = self.cfop_export_id
|
|
173
173
|
return cfop
|
|
174
174
|
|
|
175
|
+
def _get_tax_classification(self, company):
|
|
176
|
+
if self.tax_classification_id:
|
|
177
|
+
return self.tax_classification_id
|
|
178
|
+
elif company.tax_classification_id:
|
|
179
|
+
return company.tax_classification_id
|
|
180
|
+
return self.env["l10n_br_fiscal.tax.classification"]
|
|
181
|
+
|
|
175
182
|
def _build_mapping_result_ipi(self, mapping_result, tax_definition):
|
|
176
183
|
if tax_definition and tax_definition.ipi_guideline_id:
|
|
177
184
|
mapping_result["ipi_guideline"] = tax_definition.ipi_guideline_id
|
|
@@ -206,11 +213,60 @@ class OperationLine(models.Model):
|
|
|
206
213
|
service_type=None,
|
|
207
214
|
ind_final=None,
|
|
208
215
|
):
|
|
216
|
+
"""
|
|
217
|
+
Map and determine the applicable fiscal taxes, CFOP, IPI guideline,
|
|
218
|
+
and ICMS tax benefit for a given context.
|
|
219
|
+
|
|
220
|
+
The method aggregates tax definitions from various sources, applying a
|
|
221
|
+
precedence order:
|
|
222
|
+
1. Company-level tax definitions.
|
|
223
|
+
2. NCM-defined taxes (IPI, II).
|
|
224
|
+
3. ICMS Regulation specific taxes.
|
|
225
|
+
4. Taxes defined directly on this fiscal operation line.
|
|
226
|
+
5. Taxes defined on the determined CFOP.
|
|
227
|
+
6. Taxes from the partner's fiscal profile.
|
|
228
|
+
|
|
229
|
+
It also filters taxes based on whether the product is subject to
|
|
230
|
+
ICMS or ISSQN.
|
|
231
|
+
|
|
232
|
+
:param company: The company record (res.company).
|
|
233
|
+
:param partner: The partner record (res.partner).
|
|
234
|
+
:param product: Optional product record (product.product).
|
|
235
|
+
:param fiscal_price: (Unused in direct logic; kept for signature
|
|
236
|
+
consistency for overrides/extensions)
|
|
237
|
+
:param fiscal_quantity: (Unused in direct logic; kept for signature
|
|
238
|
+
consistency for overrides/extensions)
|
|
239
|
+
:param ncm: Optional NCM record (l10n_br_fiscal.ncm);
|
|
240
|
+
defaults to product's NCM.
|
|
241
|
+
:param nbm: Optional NBM record (l10n_br_fiscal.nbm);
|
|
242
|
+
defaults to product's NBM.
|
|
243
|
+
:param nbs: Optional NBS record (l10n_br_fiscal.nbs);
|
|
244
|
+
defaults to product's NBS.
|
|
245
|
+
:param cest: Optional CEST record (l10n_br_fiscal.cest);
|
|
246
|
+
defaults to product's CEST.
|
|
247
|
+
:param city_taxation_code: Optional City Taxation Code record
|
|
248
|
+
(l10n_br_fiscal.city.taxation.code).
|
|
249
|
+
:param service_type: Optional Service Type record
|
|
250
|
+
(l10n_br_fiscal.service.type).
|
|
251
|
+
:param ind_final: (Passed to icms_regulation_id.map_tax; not directly
|
|
252
|
+
used for tax calculation here)
|
|
253
|
+
:return: A dictionary containing:
|
|
254
|
+
- 'taxes': A dictionary of applicable tax records
|
|
255
|
+
(l10n_br_fiscal.tax) keyed by their tax_domain.
|
|
256
|
+
- 'cfop': The determined CFOP record (l10n_br_fiscal.cfop).
|
|
257
|
+
- 'ipi_guideline': The determined IPI guideline record
|
|
258
|
+
(l10n_br_fiscal.tax.ipi.guideline).
|
|
259
|
+
- 'icms_tax_benefit_id': The determined ICMS tax benefit record
|
|
260
|
+
ID (l10n_br_fiscal.tax.definition) or False.
|
|
261
|
+
- 'tax_classification': The determined Tax Classification record
|
|
262
|
+
(l10n_br_fiscal.tax.classification).
|
|
263
|
+
"""
|
|
209
264
|
mapping_result = {
|
|
210
265
|
"taxes": {},
|
|
211
266
|
"cfop": False,
|
|
212
267
|
"ipi_guideline": self.env.ref("l10n_br_fiscal.tax_guideline_999"),
|
|
213
268
|
"icms_tax_benefit_id": False,
|
|
269
|
+
"tax_classification": False,
|
|
214
270
|
}
|
|
215
271
|
|
|
216
272
|
self.ensure_one()
|
|
@@ -218,6 +274,9 @@ class OperationLine(models.Model):
|
|
|
218
274
|
# Define CFOP
|
|
219
275
|
mapping_result["cfop"] = self._get_cfop(company, partner)
|
|
220
276
|
|
|
277
|
+
# Define Tax Classification
|
|
278
|
+
mapping_result["tax_classification"] = self._get_tax_classification(company)
|
|
279
|
+
|
|
221
280
|
# 1 Get Tax Defs from Company
|
|
222
281
|
for tax_definition in company.tax_definition_ids.map_tax_definition(
|
|
223
282
|
company,
|
|
@@ -232,6 +291,16 @@ class OperationLine(models.Model):
|
|
|
232
291
|
):
|
|
233
292
|
self._build_mapping_result(mapping_result, tax_definition)
|
|
234
293
|
|
|
294
|
+
# 1_5 From Tax Classification
|
|
295
|
+
if mapping_result["tax_classification"]:
|
|
296
|
+
mapping_result["taxes"][
|
|
297
|
+
mapping_result["tax_classification"].tax_cbs_id.tax_domain
|
|
298
|
+
] = mapping_result["tax_classification"].tax_cbs_id
|
|
299
|
+
|
|
300
|
+
mapping_result["taxes"][
|
|
301
|
+
mapping_result["tax_classification"].tax_ibs_id.tax_domain
|
|
302
|
+
] = mapping_result["tax_classification"].tax_ibs_id
|
|
303
|
+
|
|
235
304
|
# 2 From NCM
|
|
236
305
|
if not ncm and product:
|
|
237
306
|
ncm = product.ncm_id
|
|
@@ -8,6 +8,7 @@ from odoo.exceptions import ValidationError
|
|
|
8
8
|
from ..constants.fiscal import (
|
|
9
9
|
NFE_IND_IE_DEST,
|
|
10
10
|
NFE_IND_IE_DEST_DEFAULT,
|
|
11
|
+
PUBLIC_ENTIRY_TYPE,
|
|
11
12
|
TAX_FRAMEWORK,
|
|
12
13
|
TAX_FRAMEWORK_NORMAL,
|
|
13
14
|
)
|
|
@@ -32,6 +33,11 @@ class PartnerProfile(models.Model):
|
|
|
32
33
|
"other government-controlled organizations.",
|
|
33
34
|
)
|
|
34
35
|
|
|
36
|
+
public_entity_type = fields.Selection(
|
|
37
|
+
selection=PUBLIC_ENTIRY_TYPE,
|
|
38
|
+
string="Tipo de Entidade Governamental",
|
|
39
|
+
)
|
|
40
|
+
|
|
35
41
|
default = fields.Boolean(string="Default Profile", default=True)
|
|
36
42
|
|
|
37
43
|
ind_ie_dest = fields.Selection(
|
|
@@ -15,26 +15,29 @@ class ProductMixin(models.AbstractModel):
|
|
|
15
15
|
_name = "l10n_br_fiscal.product.mixin"
|
|
16
16
|
_description = "Fiscal Product Mixin"
|
|
17
17
|
|
|
18
|
-
@api.
|
|
19
|
-
def
|
|
20
|
-
for
|
|
21
|
-
if
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
@api.depends("fiscal_type", "fiscal_genre_id")
|
|
19
|
+
def _compute_ncm_id(self):
|
|
20
|
+
for product in self:
|
|
21
|
+
if product.fiscal_type == PRODUCT_FISCAL_TYPE_SERVICE:
|
|
22
|
+
product.ncm_id = self.env.ref(NCM_FOR_SERVICE_REF)
|
|
23
|
+
elif product.fiscal_genre_id and product.ncm_id:
|
|
24
|
+
if product.fiscal_genre_id.code != product.ncm_id.code[0:2]:
|
|
25
|
+
product.ncm_id = False
|
|
26
|
+
elif product.ncm_id is None:
|
|
27
|
+
product.ncm_id = False
|
|
26
28
|
|
|
27
|
-
@api.
|
|
28
|
-
def
|
|
29
|
-
for
|
|
30
|
-
if
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
29
|
+
@api.depends("ncm_id")
|
|
30
|
+
def _compute_fiscal_genre_id(self):
|
|
31
|
+
for product in self:
|
|
32
|
+
if product.ncm_id:
|
|
33
|
+
product.fiscal_genre_id = self.env[
|
|
34
|
+
"l10n_br_fiscal.product.genre"
|
|
35
|
+
].search([("code", "=", product.ncm_id.code[0:2])])
|
|
34
36
|
|
|
35
|
-
@api.
|
|
36
|
-
def
|
|
37
|
-
for
|
|
38
|
-
if
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
@api.depends("fiscal_type")
|
|
38
|
+
def _compute_tax_icms_or_issqn(self):
|
|
39
|
+
for product in self:
|
|
40
|
+
if product.fiscal_type == PRODUCT_FISCAL_TYPE_SERVICE:
|
|
41
|
+
product.tax_icms_or_issqn = TAX_DOMAIN_ISSQN
|
|
42
|
+
else:
|
|
43
|
+
product.tax_icms_or_issqn = TAX_DOMAIN_ICMS
|