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
|
@@ -12,6 +12,23 @@ from odoo.osv import expression
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class DataAbstract(models.AbstractModel):
|
|
15
|
+
"""
|
|
16
|
+
Abstract base model for fiscal master data in Brazilian localization.
|
|
17
|
+
|
|
18
|
+
This model provides common structure and functionality for fiscal
|
|
19
|
+
data entities (NCM, CFOP, CST, etc.). It includes:
|
|
20
|
+
- Standard fields: `code`, `name`, `active`, and a computed
|
|
21
|
+
`code_unmasked` (for searching codes without punctuation).
|
|
22
|
+
- Default ordering by `code`.
|
|
23
|
+
- Enhanced search: Modifies search views and `_name_search`
|
|
24
|
+
to allow searching by `code`, `code_unmasked`, and `name`
|
|
25
|
+
simultaneously.
|
|
26
|
+
- Standardized display name format in `name_get`
|
|
27
|
+
(`<code> - <name>`).
|
|
28
|
+
- Permission control for archiving/unarchanging, restricted
|
|
29
|
+
to users in 'l10n_br_fiscal.group_manager' group.
|
|
30
|
+
"""
|
|
31
|
+
|
|
15
32
|
_name = "l10n_br_fiscal.data.abstract"
|
|
16
33
|
_description = "Fiscal Data Abstract"
|
|
17
34
|
_order = "code"
|
|
@@ -46,6 +63,15 @@ class DataAbstract(models.AbstractModel):
|
|
|
46
63
|
def fields_view_get(
|
|
47
64
|
self, view_id=None, view_type="form", toolbar=False, submenu=False
|
|
48
65
|
):
|
|
66
|
+
"""
|
|
67
|
+
Modify search view architecture to enhance 'code' field filtering.
|
|
68
|
+
|
|
69
|
+
Intercept the search view definition, altering `filter_domain`
|
|
70
|
+
for the 'code' field. This lets users search by raw 'code',
|
|
71
|
+
'code_unmasked' (code without punctuation), or 'name' of the
|
|
72
|
+
record when typing into the 'code' filter in the search panel.
|
|
73
|
+
"""
|
|
74
|
+
|
|
49
75
|
model_view = super().fields_view_get(view_id, view_type, toolbar, submenu)
|
|
50
76
|
|
|
51
77
|
if view_type == "search":
|
|
@@ -89,7 +89,7 @@ class DataNcmNbsAbstract(models.AbstractModel):
|
|
|
89
89
|
|
|
90
90
|
config = DeOlhoNoImposto(
|
|
91
91
|
company.ibpt_token,
|
|
92
|
-
misc.punctuation_rm(company.
|
|
92
|
+
misc.punctuation_rm(company.vat),
|
|
93
93
|
company.state_id.code,
|
|
94
94
|
odooconfig.get("ibpt_request_timeout")
|
|
95
95
|
or self.env["ir.config_parameter"]
|
|
@@ -10,17 +10,21 @@ from odoo import _, api, fields, models
|
|
|
10
10
|
from odoo.exceptions import ValidationError
|
|
11
11
|
|
|
12
12
|
from ..constants.fiscal import (
|
|
13
|
-
|
|
13
|
+
COMMENT_TYPE_COMMERCIAL,
|
|
14
|
+
COMMENT_TYPE_FISCAL,
|
|
14
15
|
DOCUMENT_ISSUER_COMPANY,
|
|
15
16
|
DOCUMENT_ISSUER_DICT,
|
|
16
17
|
DOCUMENT_ISSUER_PARTNER,
|
|
17
18
|
EDOC_PURPOSE,
|
|
18
19
|
EDOC_PURPOSE_NORMAL,
|
|
20
|
+
EDOC_REFUND_CREDIT_TYPE,
|
|
21
|
+
EDOC_REFUND_DEBIT_TYPE,
|
|
19
22
|
FISCAL_IN_OUT_DICT,
|
|
20
23
|
MODELO_FISCAL_CTE,
|
|
21
24
|
MODELO_FISCAL_NFCE,
|
|
22
25
|
MODELO_FISCAL_NFE,
|
|
23
26
|
MODELO_FISCAL_NFSE,
|
|
27
|
+
PUBLIC_ENTIRY_TYPE,
|
|
24
28
|
SITUACAO_EDOC,
|
|
25
29
|
SITUACAO_EDOC_AUTORIZADA,
|
|
26
30
|
SITUACAO_EDOC_CANCELADA,
|
|
@@ -32,29 +36,37 @@ from ..constants.fiscal import (
|
|
|
32
36
|
|
|
33
37
|
|
|
34
38
|
class Document(models.Model):
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
39
|
+
"""
|
|
40
|
+
Base implementation for Brazilian fiscal documents.
|
|
41
|
+
|
|
42
|
+
This model serves as the foundational structure for various fiscal
|
|
43
|
+
documents within the Brazilian localization. It's designed to be
|
|
44
|
+
extensible, allowing other OCA modules to build upon it, ideally
|
|
45
|
+
minimizing the need for additional custom coding for common fiscal
|
|
46
|
+
document functionalities.
|
|
47
|
+
|
|
48
|
+
Key aspects to note:
|
|
49
|
+
- The fiscal document manages two primary states:
|
|
50
|
+
- Electronic Document State (`state_edoc`): Reflects the status
|
|
51
|
+
of the document in its electronic lifecycle (e.g., Draft,
|
|
52
|
+
Authorized, Cancelled).
|
|
53
|
+
- Fiscal State (`state_fiscal`): Represents the document's status
|
|
54
|
+
from a purely fiscal accounting perspective (e.g., Regular,
|
|
55
|
+
Cancelled for fiscal purposes). This state is less automated
|
|
56
|
+
and often managed by the fiscal responsible to ensure correct
|
|
57
|
+
reporting, such as in SPED Fiscal.
|
|
58
|
+
|
|
59
|
+
This model inherits common fields and methods from
|
|
60
|
+
`l10n_br_fiscal.document.mixin` and includes features for document
|
|
61
|
+
numbering, key validation, partner and company fiscal details, line
|
|
62
|
+
items and returns.
|
|
51
63
|
"""
|
|
52
64
|
|
|
53
65
|
_name = "l10n_br_fiscal.document"
|
|
54
66
|
_inherit = [
|
|
55
|
-
"l10n_br_fiscal.document.mixin
|
|
56
|
-
"l10n_br_fiscal.document.move.mixin",
|
|
67
|
+
"l10n_br_fiscal.document.mixin",
|
|
57
68
|
"mail.thread",
|
|
69
|
+
"mail.activity.mixin",
|
|
58
70
|
]
|
|
59
71
|
_description = "Fiscal Document"
|
|
60
72
|
_check_company_auto = True
|
|
@@ -85,9 +97,9 @@ class Document(models.Model):
|
|
|
85
97
|
)
|
|
86
98
|
|
|
87
99
|
fiscal_operation_id = fields.Many2one(
|
|
88
|
-
|
|
89
|
-
"
|
|
90
|
-
"
|
|
100
|
+
"l10n_br_fiscal.operation",
|
|
101
|
+
string="Fiscal Operation",
|
|
102
|
+
domain="[('state', '=', 'approved')]",
|
|
91
103
|
)
|
|
92
104
|
|
|
93
105
|
fiscal_operation_type = fields.Selection(
|
|
@@ -112,10 +124,6 @@ class Document(models.Model):
|
|
|
112
124
|
default=lambda self: self.env.user,
|
|
113
125
|
)
|
|
114
126
|
|
|
115
|
-
operation_name = fields.Char(
|
|
116
|
-
copy=False,
|
|
117
|
-
)
|
|
118
|
-
|
|
119
127
|
document_electronic = fields.Boolean(
|
|
120
128
|
related="document_type_id.electronic",
|
|
121
129
|
string="Electronic?",
|
|
@@ -136,8 +144,16 @@ class Document(models.Model):
|
|
|
136
144
|
partner_id = fields.Many2one(
|
|
137
145
|
comodel_name="res.partner",
|
|
138
146
|
string="Partner",
|
|
147
|
+
inverse="_inverse_partner_id",
|
|
139
148
|
)
|
|
140
149
|
|
|
150
|
+
@api.onchange("partner_id")
|
|
151
|
+
def _inverse_partner_id(self):
|
|
152
|
+
for doc in self:
|
|
153
|
+
for line in doc.fiscal_line_ids:
|
|
154
|
+
if line.partner_id != doc.partner_id:
|
|
155
|
+
line.partner_id = doc.partner_id
|
|
156
|
+
|
|
141
157
|
partner_shipping_id = fields.Many2one(
|
|
142
158
|
comodel_name="res.partner",
|
|
143
159
|
string="Shipping Address",
|
|
@@ -161,6 +177,24 @@ class Document(models.Model):
|
|
|
161
177
|
selection=EDOC_PURPOSE,
|
|
162
178
|
string="Finalidade",
|
|
163
179
|
default=EDOC_PURPOSE_NORMAL,
|
|
180
|
+
compute="_compute_edoc_purpose",
|
|
181
|
+
store=True,
|
|
182
|
+
precompute=True,
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
edoc_refund_debit_type = fields.Selection(
|
|
186
|
+
selection=EDOC_REFUND_DEBIT_TYPE,
|
|
187
|
+
string="Tipo de Nota de Débito",
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
edoc_refund_credit_type = fields.Selection(
|
|
191
|
+
selection=EDOC_REFUND_CREDIT_TYPE,
|
|
192
|
+
string="Tipo de Nota de Crédito",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
public_entity_type = fields.Selection(
|
|
196
|
+
selection=PUBLIC_ENTIRY_TYPE,
|
|
197
|
+
string="Tipo de Entidade Governamental",
|
|
164
198
|
)
|
|
165
199
|
|
|
166
200
|
document_type = fields.Char(
|
|
@@ -178,9 +212,9 @@ class Document(models.Model):
|
|
|
178
212
|
)
|
|
179
213
|
|
|
180
214
|
currency_id = fields.Many2one(
|
|
215
|
+
related="company_id.currency_id",
|
|
181
216
|
comodel_name="res.currency",
|
|
182
217
|
string="Currency",
|
|
183
|
-
compute="_compute_currency_id",
|
|
184
218
|
)
|
|
185
219
|
|
|
186
220
|
# this related "state" field is required for the status bar widget
|
|
@@ -188,23 +222,6 @@ class Document(models.Model):
|
|
|
188
222
|
# of objects where the fiscal mixin might be injected.
|
|
189
223
|
state = fields.Selection(related="state_edoc", string="State")
|
|
190
224
|
|
|
191
|
-
issuer = fields.Selection(
|
|
192
|
-
selection=DOCUMENT_ISSUER,
|
|
193
|
-
default=DOCUMENT_ISSUER_COMPANY,
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
document_subsequent_ids = fields.One2many(
|
|
197
|
-
comodel_name="l10n_br_fiscal.subsequent.document",
|
|
198
|
-
inverse_name="source_document_id",
|
|
199
|
-
copy=True,
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
document_subsequent_generated = fields.Boolean(
|
|
203
|
-
string="Subsequent documents generated?",
|
|
204
|
-
compute="_compute_document_subsequent_generated",
|
|
205
|
-
default=False,
|
|
206
|
-
)
|
|
207
|
-
|
|
208
225
|
transport_modal = fields.Selection(
|
|
209
226
|
selection=[
|
|
210
227
|
("01", "Rodoviário"),
|
|
@@ -227,6 +244,29 @@ class Document(models.Model):
|
|
|
227
244
|
],
|
|
228
245
|
string="Tomador do Serviço",
|
|
229
246
|
)
|
|
247
|
+
partner_legal_name = fields.Char(
|
|
248
|
+
string="Legal Name",
|
|
249
|
+
related="partner_id.legal_name",
|
|
250
|
+
)
|
|
251
|
+
partner_cnpj_cpf = fields.Char(
|
|
252
|
+
string="CNPJ",
|
|
253
|
+
related="partner_id.vat",
|
|
254
|
+
)
|
|
255
|
+
partner_l10n_br_ie_code = fields.Char(
|
|
256
|
+
string="State Tax Number",
|
|
257
|
+
related="partner_id.l10n_br_ie_code",
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
processador_edoc = fields.Selection(
|
|
261
|
+
related="company_id.processador_edoc",
|
|
262
|
+
)
|
|
263
|
+
company_l10n_br_ie_code_st = fields.Char(
|
|
264
|
+
string="Company ST State Tax Number",
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
fiscal_additional_data = fields.Text()
|
|
268
|
+
|
|
269
|
+
customer_additional_data = fields.Text()
|
|
230
270
|
|
|
231
271
|
@api.constrains("document_key")
|
|
232
272
|
def _check_key(self):
|
|
@@ -256,9 +296,9 @@ class Document(models.Model):
|
|
|
256
296
|
|
|
257
297
|
if documents:
|
|
258
298
|
raise ValidationError(
|
|
259
|
-
_(
|
|
260
|
-
|
|
261
|
-
)
|
|
299
|
+
_("There is already a fiscal document with this key: {} !").format(
|
|
300
|
+
record.document_key
|
|
301
|
+
)
|
|
262
302
|
)
|
|
263
303
|
else:
|
|
264
304
|
ChaveEdoc(chave=record.document_key, validar=True)
|
|
@@ -299,10 +339,18 @@ class Document(models.Model):
|
|
|
299
339
|
)
|
|
300
340
|
)
|
|
301
341
|
|
|
302
|
-
@api.
|
|
303
|
-
def
|
|
304
|
-
|
|
305
|
-
|
|
342
|
+
@api.onchange("fiscal_operation_type")
|
|
343
|
+
def _onchange_fiscal_operation_type(self):
|
|
344
|
+
domain = [("state", "=", "approved")]
|
|
345
|
+
if self.fiscal_operation_type:
|
|
346
|
+
domain.append(("fiscal_operation_type", "=", self.fiscal_operation_type))
|
|
347
|
+
if (
|
|
348
|
+
self.fiscal_operation_id
|
|
349
|
+
and self.fiscal_operation_id.fiscal_operation_type
|
|
350
|
+
!= self.fiscal_operation_type
|
|
351
|
+
):
|
|
352
|
+
self.fiscal_operation_id = False
|
|
353
|
+
return {"domain": {"fiscal_operation_id": domain}}
|
|
306
354
|
|
|
307
355
|
def _compute_document_name(self):
|
|
308
356
|
self.ensure_one()
|
|
@@ -323,19 +371,19 @@ class Document(models.Model):
|
|
|
323
371
|
name += "/" + type_serie_number
|
|
324
372
|
if self.document_date:
|
|
325
373
|
name += " - " + self.document_date.strftime("%d/%m/%Y")
|
|
326
|
-
if not self.
|
|
374
|
+
if not self.partner_id.vat:
|
|
327
375
|
name += " - " + _("Unidentified Consumer")
|
|
328
|
-
elif self.
|
|
329
|
-
name += " - " + self.
|
|
330
|
-
name += " - " + self.
|
|
376
|
+
elif self.partner_id.legal_name:
|
|
377
|
+
name += " - " + self.partner_id.legal_name
|
|
378
|
+
name += " - " + self.partner_id.vat
|
|
331
379
|
else:
|
|
332
|
-
name += " - " + self.
|
|
333
|
-
name += " - " + self.
|
|
380
|
+
name += " - " + self.partner_id.name
|
|
381
|
+
name += " - " + self.partner_id.vat
|
|
334
382
|
elif self._context.get("fiscal_document_no_company"):
|
|
335
383
|
name += type_serie_number
|
|
336
384
|
else:
|
|
337
385
|
name += "{name}/{type_serie_number}".format(
|
|
338
|
-
name=self.
|
|
386
|
+
name=self.company_id.name or "",
|
|
339
387
|
type_serie_number=type_serie_number,
|
|
340
388
|
)
|
|
341
389
|
return name
|
|
@@ -359,22 +407,9 @@ class Document(models.Model):
|
|
|
359
407
|
for r in self:
|
|
360
408
|
r.name = r._compute_document_name()
|
|
361
409
|
|
|
362
|
-
@api.
|
|
363
|
-
|
|
364
|
-
"fiscal_line_ids
|
|
365
|
-
"fiscal_line_ids.amount_untaxed",
|
|
366
|
-
"fiscal_line_ids.amount_tax",
|
|
367
|
-
"fiscal_line_ids.amount_taxed",
|
|
368
|
-
"fiscal_line_ids.amount_total",
|
|
369
|
-
"fiscal_line_ids.financial_total",
|
|
370
|
-
"fiscal_line_ids.financial_total_gross",
|
|
371
|
-
"fiscal_line_ids.financial_discount_value",
|
|
372
|
-
"fiscal_line_ids.amount_tax_included",
|
|
373
|
-
"fiscal_line_ids.amount_tax_not_included",
|
|
374
|
-
"fiscal_line_ids.amount_tax_withholding",
|
|
375
|
-
)
|
|
376
|
-
def _compute_fiscal_amount(self):
|
|
377
|
-
return super()._compute_fiscal_amount()
|
|
410
|
+
@api.model
|
|
411
|
+
def _get_fiscal_lines_field_name(self):
|
|
412
|
+
return "fiscal_line_ids"
|
|
378
413
|
|
|
379
414
|
def unlink(self):
|
|
380
415
|
forbidden_states_unlink = [
|
|
@@ -403,14 +438,12 @@ class Document(models.Model):
|
|
|
403
438
|
if not fsc_op:
|
|
404
439
|
raise ValidationError(
|
|
405
440
|
_(
|
|
406
|
-
"The fiscal operation {} has no return Fiscal "
|
|
407
|
-
"Operation defined"
|
|
441
|
+
"The fiscal operation {} has no return Fiscal Operation defined"
|
|
408
442
|
).format(record.fiscal_operation_id)
|
|
409
443
|
)
|
|
410
444
|
|
|
411
445
|
new_doc = record.copy()
|
|
412
446
|
new_doc.fiscal_operation_id = fsc_op
|
|
413
|
-
new_doc._onchange_fiscal_operation_id()
|
|
414
447
|
|
|
415
448
|
for line in new_doc.fiscal_line_ids:
|
|
416
449
|
fsc_op_line = line.fiscal_operation_id.return_fiscal_operation_id
|
|
@@ -422,9 +455,6 @@ class Document(models.Model):
|
|
|
422
455
|
).format(line.fiscal_operation_id)
|
|
423
456
|
)
|
|
424
457
|
line.fiscal_operation_id = fsc_op_line
|
|
425
|
-
line._onchange_fiscal_operation_id()
|
|
426
|
-
line._onchange_fiscal_operation_line_id()
|
|
427
|
-
|
|
428
458
|
return_docs |= new_doc
|
|
429
459
|
return return_docs
|
|
430
460
|
|
|
@@ -469,152 +499,31 @@ class Document(models.Model):
|
|
|
469
499
|
# see https://github.com/OCA/l10n-brazil/pull/3272
|
|
470
500
|
pass
|
|
471
501
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
"|",
|
|
477
|
-
("state_edoc", "=", False),
|
|
478
|
-
("state_edoc", "=", state),
|
|
479
|
-
("issuer", "=", self.issuer),
|
|
480
|
-
"|",
|
|
481
|
-
("document_type_id", "=", False),
|
|
482
|
-
("document_type_id", "=", self.document_type_id.id),
|
|
483
|
-
],
|
|
484
|
-
limit=1,
|
|
485
|
-
order="state_edoc, document_type_id",
|
|
486
|
-
).mapped("email_template_id")
|
|
487
|
-
|
|
488
|
-
def send_email(self, state):
|
|
489
|
-
self.ensure_one()
|
|
490
|
-
email_template = self._get_email_template(state)
|
|
491
|
-
if email_template:
|
|
492
|
-
email_template.with_context(
|
|
493
|
-
default_attachment_ids=self._get_mail_attachment()
|
|
494
|
-
).send_mail(self.id)
|
|
495
|
-
|
|
496
|
-
def _after_change_state(self, old_state, new_state):
|
|
497
|
-
self.ensure_one()
|
|
498
|
-
result = super()._after_change_state(old_state, new_state)
|
|
499
|
-
self.send_email(new_state)
|
|
500
|
-
return result
|
|
501
|
-
|
|
502
|
-
@api.onchange("fiscal_operation_id")
|
|
503
|
-
def _onchange_fiscal_operation_id(self):
|
|
504
|
-
result = super()._onchange_fiscal_operation_id()
|
|
505
|
-
if self.fiscal_operation_id:
|
|
506
|
-
self.fiscal_operation_type = self.fiscal_operation_id.fiscal_operation_type
|
|
507
|
-
self.edoc_purpose = self.fiscal_operation_id.edoc_purpose
|
|
508
|
-
|
|
509
|
-
if self.issuer == DOCUMENT_ISSUER_COMPANY and not self.document_type_id:
|
|
510
|
-
self.document_type_id = self.company_id.document_type_id
|
|
511
|
-
|
|
512
|
-
subsequent_documents = [(6, 0, {})]
|
|
513
|
-
for subsequent_id in self.fiscal_operation_id.mapped(
|
|
514
|
-
"operation_subsequent_ids"
|
|
515
|
-
):
|
|
516
|
-
subsequent_documents.append(
|
|
517
|
-
(
|
|
518
|
-
0,
|
|
519
|
-
0,
|
|
520
|
-
{
|
|
521
|
-
"source_document_id": self.id,
|
|
522
|
-
"subsequent_operation_id": subsequent_id.id,
|
|
523
|
-
"fiscal_operation_id": subsequent_id.subsequent_operation_id.id,
|
|
524
|
-
},
|
|
525
|
-
)
|
|
526
|
-
)
|
|
527
|
-
self.document_subsequent_ids = subsequent_documents
|
|
528
|
-
return result
|
|
502
|
+
@api.depends("fiscal_operation_id")
|
|
503
|
+
def _compute_edoc_purpose(self):
|
|
504
|
+
for record in self:
|
|
505
|
+
record.edoc_purpose = record.fiscal_operation_id.edoc_purpose
|
|
529
506
|
|
|
530
|
-
def
|
|
531
|
-
self.ensure_one()
|
|
507
|
+
def __document_comment_vals(self):
|
|
532
508
|
return {
|
|
533
|
-
"
|
|
534
|
-
"
|
|
535
|
-
"
|
|
536
|
-
"document_serie": doc_referenced.document_serie,
|
|
537
|
-
"document_number": doc_referenced.document_number,
|
|
538
|
-
"document_date": doc_referenced.document_date,
|
|
539
|
-
"document_key": doc_referenced.document_key,
|
|
509
|
+
"user": self.env.user,
|
|
510
|
+
"ctx": self._context,
|
|
511
|
+
"doc": self,
|
|
540
512
|
}
|
|
541
513
|
|
|
542
|
-
def
|
|
543
|
-
self
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
514
|
+
def _document_comment(self):
|
|
515
|
+
for d in self:
|
|
516
|
+
# Fiscal Comments
|
|
517
|
+
d.fiscal_additional_data = d.comment_ids.filtered(
|
|
518
|
+
lambda c: c.comment_type == COMMENT_TYPE_FISCAL
|
|
519
|
+
).compute_message(
|
|
520
|
+
d.__document_comment_vals(), d.manual_fiscal_additional_data
|
|
547
521
|
)
|
|
548
522
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
else:
|
|
555
|
-
document.document_subsequent_generated = all(
|
|
556
|
-
subsequent_id.operation_performed
|
|
557
|
-
for subsequent_id in document.document_subsequent_ids
|
|
558
|
-
)
|
|
559
|
-
|
|
560
|
-
def _generates_subsequent_operations(self):
|
|
561
|
-
for record in self.filtered(lambda doc: not doc.document_subsequent_generated):
|
|
562
|
-
for subsequent_id in record.document_subsequent_ids.filtered(
|
|
563
|
-
lambda doc_sub: doc_sub._confirms_document_generation()
|
|
564
|
-
):
|
|
565
|
-
subsequent_id.generate_subsequent_document()
|
|
566
|
-
|
|
567
|
-
def cancel_edoc(self):
|
|
568
|
-
self.ensure_one()
|
|
569
|
-
if any(
|
|
570
|
-
doc.state_edoc == SITUACAO_EDOC_AUTORIZADA
|
|
571
|
-
for doc in self.document_subsequent_ids.mapped("document_subsequent_ids")
|
|
572
|
-
):
|
|
573
|
-
message = _(
|
|
574
|
-
"Canceling the document is not allowed: one or more "
|
|
575
|
-
"associated documents have already been authorized."
|
|
523
|
+
# Commercial Comments
|
|
524
|
+
d.customer_additional_data = d.comment_ids.filtered(
|
|
525
|
+
lambda c: c.comment_type == COMMENT_TYPE_COMMERCIAL
|
|
526
|
+
).compute_message(
|
|
527
|
+
d.__document_comment_vals(), d.manual_customer_additional_data
|
|
576
528
|
)
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
def _get_mail_attachment(self):
|
|
580
|
-
self.ensure_one()
|
|
581
|
-
attachment_ids = []
|
|
582
|
-
if self.state_edoc == SITUACAO_EDOC_AUTORIZADA:
|
|
583
|
-
if self.file_report_id:
|
|
584
|
-
attachment_ids.append(self.file_report_id.id)
|
|
585
|
-
if self.authorization_file_id:
|
|
586
|
-
attachment_ids.append(self.authorization_file_id.id)
|
|
587
|
-
return attachment_ids
|
|
588
|
-
|
|
589
|
-
def action_send_email(self):
|
|
590
|
-
"""Open a window to compose an email, with the fiscal document_type
|
|
591
|
-
template message loaded by default
|
|
592
|
-
"""
|
|
593
|
-
self.ensure_one()
|
|
594
|
-
template = self._get_email_template(self.state)
|
|
595
|
-
compose_form = self.env.ref("mail.email_compose_message_wizard_form", False)
|
|
596
|
-
lang = self.env.context.get("lang")
|
|
597
|
-
if template and template.lang:
|
|
598
|
-
lang = template._render_template(template.lang, self._name, [self.id])
|
|
599
|
-
self = self.with_context(lang=lang)
|
|
600
|
-
ctx = dict(
|
|
601
|
-
default_model="l10n_br_fiscal.document",
|
|
602
|
-
default_res_id=self.id,
|
|
603
|
-
default_use_template=bool(template),
|
|
604
|
-
default_attachment_ids=self._get_mail_attachment(),
|
|
605
|
-
default_template_id=template and template.id or False,
|
|
606
|
-
default_composition_mode="comment",
|
|
607
|
-
model_description=self.document_type_id.name or self._name,
|
|
608
|
-
force_email=True,
|
|
609
|
-
)
|
|
610
|
-
return {
|
|
611
|
-
"name": _("Send Fiscal Document Email Notification"),
|
|
612
|
-
"type": "ir.actions.act_window",
|
|
613
|
-
"view_type": "form",
|
|
614
|
-
"view_mode": "form",
|
|
615
|
-
"res_model": "mail.compose.message",
|
|
616
|
-
"views": [(compose_form.id, "form")],
|
|
617
|
-
"view_id": compose_form.id,
|
|
618
|
-
"target": "new",
|
|
619
|
-
"context": ctx,
|
|
620
|
-
}
|
|
529
|
+
d.fiscal_line_ids._document_comment()
|
|
@@ -1,10 +1,25 @@
|
|
|
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 fields, models
|
|
4
|
+
from odoo import api, fields, models
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class DocumentLine(models.Model):
|
|
8
|
+
"""
|
|
9
|
+
Represents a line item within a Brazilian fiscal document.
|
|
10
|
+
|
|
11
|
+
This model defines the core structure of a fiscal document line,
|
|
12
|
+
primarily linking it to its parent document (`l10n_br_fiscal.document`)
|
|
13
|
+
and holding essential line-specific data like quantity and a
|
|
14
|
+
descriptive name.
|
|
15
|
+
|
|
16
|
+
The vast majority of detailed fiscal fields (e.g., product, NCM,
|
|
17
|
+
CFOP, various tax bases and values) and their complex computation
|
|
18
|
+
logic are inherited from `l10n_br_fiscal.document.line.mixin`.
|
|
19
|
+
This delegation ensures code reusability and keeps this model
|
|
20
|
+
focused on its direct relationships and core line properties.
|
|
21
|
+
"""
|
|
22
|
+
|
|
8
23
|
_name = "l10n_br_fiscal.document.line"
|
|
9
24
|
_inherit = "l10n_br_fiscal.document.line.mixin"
|
|
10
25
|
_description = "Fiscal Document Line"
|
|
@@ -15,12 +30,18 @@ class DocumentLine(models.Model):
|
|
|
15
30
|
ondelete="cascade",
|
|
16
31
|
)
|
|
17
32
|
|
|
18
|
-
name = fields.
|
|
33
|
+
name = fields.Char(
|
|
34
|
+
compute="_compute_name",
|
|
35
|
+
store=True,
|
|
36
|
+
precompute=True,
|
|
37
|
+
readonly=False,
|
|
38
|
+
)
|
|
19
39
|
|
|
20
40
|
company_id = fields.Many2one(
|
|
21
41
|
comodel_name="res.company",
|
|
22
42
|
related="document_id.company_id",
|
|
23
43
|
store=True,
|
|
44
|
+
precompute=True,
|
|
24
45
|
string="Company",
|
|
25
46
|
)
|
|
26
47
|
|
|
@@ -29,13 +50,36 @@ class DocumentLine(models.Model):
|
|
|
29
50
|
)
|
|
30
51
|
|
|
31
52
|
partner_id = fields.Many2one(
|
|
32
|
-
|
|
53
|
+
comodel_name="res.partner",
|
|
54
|
+
compute="_compute_partner_id",
|
|
33
55
|
store=True,
|
|
56
|
+
precompute=True,
|
|
57
|
+
readonly=False,
|
|
34
58
|
)
|
|
35
59
|
|
|
36
|
-
|
|
60
|
+
# Do not depend on `document_id.partner_id`, the inverse is taking care of that
|
|
61
|
+
def _compute_partner_id(self):
|
|
62
|
+
for line in self:
|
|
63
|
+
line.partner_id = line.document_id.partner_id
|
|
64
|
+
|
|
65
|
+
uom_id = fields.Many2one(
|
|
66
|
+
comodel_name="uom.uom",
|
|
67
|
+
string="UOM",
|
|
68
|
+
compute="_compute_uom_id",
|
|
69
|
+
store=True,
|
|
70
|
+
readonly=False,
|
|
71
|
+
precompute=True,
|
|
72
|
+
)
|
|
37
73
|
|
|
38
|
-
|
|
74
|
+
price_unit = fields.Float(
|
|
75
|
+
digits="Product Price",
|
|
76
|
+
compute="_compute_price_unit_fiscal",
|
|
77
|
+
store=True,
|
|
78
|
+
precompute=True,
|
|
79
|
+
readonly=False,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
quantity = fields.Float(default=1.0)
|
|
39
83
|
|
|
40
84
|
# Usado para tornar Somente Leitura os campos dos custos
|
|
41
85
|
# de entrega quando a definição for por Total
|
|
@@ -50,3 +94,36 @@ class DocumentLine(models.Model):
|
|
|
50
94
|
edoc_purpose = fields.Selection(
|
|
51
95
|
related="document_id.edoc_purpose",
|
|
52
96
|
)
|
|
97
|
+
|
|
98
|
+
additional_data = fields.Text()
|
|
99
|
+
|
|
100
|
+
@api.depends("product_id")
|
|
101
|
+
def _compute_name(self):
|
|
102
|
+
for line in self:
|
|
103
|
+
if line.product_id:
|
|
104
|
+
line.name = line.product_id.display_name
|
|
105
|
+
else:
|
|
106
|
+
line.name = False
|
|
107
|
+
|
|
108
|
+
@api.depends("product_id")
|
|
109
|
+
def _compute_uom_id(self):
|
|
110
|
+
for line in self:
|
|
111
|
+
if line.fiscal_operation_type == "in":
|
|
112
|
+
line.uom_id = line.product_id.uom_po_id
|
|
113
|
+
else:
|
|
114
|
+
line.uom_id = line.product_id.uom_id
|
|
115
|
+
|
|
116
|
+
def __document_comment_vals(self):
|
|
117
|
+
self.ensure_one()
|
|
118
|
+
return {
|
|
119
|
+
"user": self.env.user,
|
|
120
|
+
"ctx": self._context,
|
|
121
|
+
"doc": self.document_id if hasattr(self, "document_id") else None,
|
|
122
|
+
"item": self,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
def _document_comment(self):
|
|
126
|
+
for line in self:
|
|
127
|
+
line.additional_data = line.comment_ids.compute_message(
|
|
128
|
+
line.__document_comment_vals(), line.manual_additional_data
|
|
129
|
+
)
|