odoo-addon-l10n-br-fiscal 16.0.8.0.2__py3-none-any.whl → 16.0.19.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. odoo/addons/l10n_br_fiscal/README.rst +1 -1
  2. odoo/addons/l10n_br_fiscal/__manifest__.py +10 -3
  3. odoo/addons/l10n_br_fiscal/constants/fiscal.py +64 -18
  4. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cest.csv +1043 -983
  5. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.cst.csv +58 -0
  6. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.document.type.csv +1 -0
  7. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.operation.indicator.csv +27 -0
  8. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.classification.csv +163 -0
  9. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.csv +31 -0
  10. odoo/addons/l10n_br_fiscal/data/l10n_br_fiscal.tax.group.csv +3 -0
  11. odoo/addons/l10n_br_fiscal/data/operation_data.xml +1 -1
  12. odoo/addons/l10n_br_fiscal/data/uom_data.xml +186 -33
  13. odoo/addons/l10n_br_fiscal/demo/fiscal_document_demo.xml +3 -377
  14. odoo/addons/l10n_br_fiscal/demo/fiscal_document_nfse_demo.xml +0 -12
  15. odoo/addons/l10n_br_fiscal/demo/fiscal_operation_demo.xml +2 -2
  16. odoo/addons/l10n_br_fiscal/i18n/l10n_br_fiscal.pot +902 -304
  17. odoo/addons/l10n_br_fiscal/i18n/pt_BR.po +22 -22
  18. odoo/addons/l10n_br_fiscal/migrations/16.0.13.0.0/pre-migration.py +25 -0
  19. odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.0/pre-migration.py +30 -0
  20. odoo/addons/l10n_br_fiscal/migrations/16.0.14.0.5/pre-migration.py +15 -0
  21. odoo/addons/l10n_br_fiscal/models/__init__.py +3 -2
  22. odoo/addons/l10n_br_fiscal/models/comment.py +2 -2
  23. odoo/addons/l10n_br_fiscal/models/data_ncm_nbs_abstract.py +1 -1
  24. odoo/addons/l10n_br_fiscal/models/document.py +83 -226
  25. odoo/addons/l10n_br_fiscal/models/document_line.py +67 -5
  26. odoo/addons/l10n_br_fiscal/models/document_line_mixin.py +1932 -136
  27. odoo/addons/l10n_br_fiscal/models/document_mixin.py +248 -17
  28. odoo/addons/l10n_br_fiscal/models/document_related.py +11 -8
  29. odoo/addons/l10n_br_fiscal/models/document_serie.py +33 -0
  30. odoo/addons/l10n_br_fiscal/models/ibpt.py +1 -1
  31. odoo/addons/l10n_br_fiscal/models/icms_regulation.py +1 -1
  32. odoo/addons/l10n_br_fiscal/models/invalidate_number.py +4 -5
  33. odoo/addons/l10n_br_fiscal/models/operation_dashboard.py +3 -2
  34. odoo/addons/l10n_br_fiscal/models/operation_indicator.py +58 -0
  35. odoo/addons/l10n_br_fiscal/models/operation_line.py +28 -0
  36. odoo/addons/l10n_br_fiscal/models/partner_profile.py +6 -0
  37. odoo/addons/l10n_br_fiscal/models/product_template.py +5 -1
  38. odoo/addons/l10n_br_fiscal/models/res_company.py +18 -0
  39. odoo/addons/l10n_br_fiscal/models/res_partner.py +27 -6
  40. odoo/addons/l10n_br_fiscal/models/simplified_tax_range.py +8 -0
  41. odoo/addons/l10n_br_fiscal/models/tax.py +7 -3
  42. odoo/addons/l10n_br_fiscal/models/tax_classification.py +81 -0
  43. odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_base.py +1 -1
  44. odoo/addons/l10n_br_fiscal/models/tax_pis_cofins_credit.py +1 -1
  45. odoo/addons/l10n_br_fiscal/models/uom_uom.py +24 -0
  46. odoo/addons/l10n_br_fiscal/security/fiscal_security.xml +6 -16
  47. odoo/addons/l10n_br_fiscal/security/ir.model.access.csv +8 -2
  48. odoo/addons/l10n_br_fiscal/static/description/index.html +1 -1
  49. odoo/addons/l10n_br_fiscal/tests/__init__.py +3 -0
  50. odoo/addons/l10n_br_fiscal/tests/test_document_edition.py +308 -0
  51. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_generic.py +23 -111
  52. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_nfse.py +5 -13
  53. odoo/addons/l10n_br_fiscal/tests/test_fiscal_document_serie.py +60 -0
  54. odoo/addons/l10n_br_fiscal/tests/test_ibpt.py +2 -2
  55. odoo/addons/l10n_br_fiscal/tests/test_icms_regulation.py +2 -2
  56. odoo/addons/l10n_br_fiscal/tests/test_tax_benefit.py +14 -20
  57. odoo/addons/l10n_br_fiscal/tests/test_tax_classification.py +110 -0
  58. odoo/addons/l10n_br_fiscal/tools.py +1 -1
  59. odoo/addons/l10n_br_fiscal/views/cest_view.xml +2 -4
  60. odoo/addons/l10n_br_fiscal/views/cfop_view.xml +3 -5
  61. odoo/addons/l10n_br_fiscal/views/city_taxation_code.xml +1 -4
  62. odoo/addons/l10n_br_fiscal/views/cnae_view.xml +2 -4
  63. odoo/addons/l10n_br_fiscal/views/comment_view.xml +2 -4
  64. odoo/addons/l10n_br_fiscal/views/cst_view.xml +6 -8
  65. odoo/addons/l10n_br_fiscal/views/{document_fiscal_line_mixin_view.xml → document_line_mixin_view.xml} +525 -388
  66. odoo/addons/l10n_br_fiscal/views/document_line_view.xml +101 -82
  67. odoo/addons/l10n_br_fiscal/views/document_related_view.xml +44 -46
  68. odoo/addons/l10n_br_fiscal/views/document_serie_view.xml +2 -6
  69. odoo/addons/l10n_br_fiscal/views/document_type_view.xml +0 -2
  70. odoo/addons/l10n_br_fiscal/views/document_view.xml +304 -346
  71. odoo/addons/l10n_br_fiscal/views/icms_regulation_view.xml +14 -16
  72. odoo/addons/l10n_br_fiscal/views/icms_relief_view.xml +8 -10
  73. odoo/addons/l10n_br_fiscal/views/invalidate_number_view.xml +46 -48
  74. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +162 -244
  75. odoo/addons/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +16 -72
  76. odoo/addons/l10n_br_fiscal/views/legal_nature_view.xml +0 -2
  77. odoo/addons/l10n_br_fiscal/views/nbm_view.xml +5 -6
  78. odoo/addons/l10n_br_fiscal/views/nbs_view.xml +5 -6
  79. odoo/addons/l10n_br_fiscal/views/ncm_view.xml +12 -15
  80. odoo/addons/l10n_br_fiscal/views/operation_dashboard_view.xml +13 -12
  81. odoo/addons/l10n_br_fiscal/views/operation_indicator_view.xml +75 -0
  82. odoo/addons/l10n_br_fiscal/views/operation_line_view.xml +22 -21
  83. odoo/addons/l10n_br_fiscal/views/operation_view.xml +3 -6
  84. odoo/addons/l10n_br_fiscal/views/partner_profile_view.xml +3 -6
  85. odoo/addons/l10n_br_fiscal/views/product_genre_view.xml +7 -9
  86. odoo/addons/l10n_br_fiscal/views/product_product_view.xml +37 -14
  87. odoo/addons/l10n_br_fiscal/views/product_template_view.xml +34 -14
  88. odoo/addons/l10n_br_fiscal/views/res_company_view.xml +40 -38
  89. odoo/addons/l10n_br_fiscal/views/res_config_settings_view.xml +23 -28
  90. odoo/addons/l10n_br_fiscal/views/res_partner_view.xml +13 -2
  91. odoo/addons/l10n_br_fiscal/views/service_type_view.xml +7 -8
  92. odoo/addons/l10n_br_fiscal/views/simplified_tax_range_view.xml +0 -2
  93. odoo/addons/l10n_br_fiscal/views/simplified_tax_view.xml +0 -2
  94. odoo/addons/l10n_br_fiscal/views/tax_classification.xml +110 -0
  95. odoo/addons/l10n_br_fiscal/views/tax_definition_view.xml +157 -129
  96. odoo/addons/l10n_br_fiscal/views/tax_estimate_view.xml +0 -2
  97. odoo/addons/l10n_br_fiscal/views/tax_group_view.xml +3 -6
  98. odoo/addons/l10n_br_fiscal/views/tax_ipi_control_seal_view.xml +0 -2
  99. odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_class_view.xml +0 -2
  100. odoo/addons/l10n_br_fiscal/views/tax_ipi_guideline_view.xml +2 -4
  101. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_base_view.xml +2 -4
  102. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_credit_view.xml +2 -4
  103. odoo/addons/l10n_br_fiscal/views/tax_pis_cofins_view.xml +5 -7
  104. odoo/addons/l10n_br_fiscal/views/tax_view.xml +5 -7
  105. odoo/addons/l10n_br_fiscal/views/uom_uom.xml +52 -0
  106. odoo/addons/l10n_br_fiscal/wizards/__init__.py +1 -0
  107. odoo/addons/l10n_br_fiscal/wizards/base_wizard_mixin.py +1 -1
  108. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.py +129 -0
  109. odoo/addons/l10n_br_fiscal/wizards/document_import_wizard_mixin.xml +41 -0
  110. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/METADATA +3 -3
  111. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/RECORD +113 -99
  112. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/WHEEL +1 -1
  113. odoo/addons/l10n_br_fiscal/models/document_line_mixin_methods.py +0 -814
  114. odoo/addons/l10n_br_fiscal/models/document_mixin_methods.py +0 -363
  115. {odoo_addon_l10n_br_fiscal-16.0.8.0.2.dist-info → odoo_addon_l10n_br_fiscal-16.0.19.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,308 @@
1
+ # Copyright 2025-TODAY Akretion - Raphaël Valyi
2
+ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
3
+
4
+ from unittest import mock
5
+
6
+ from odoo.tests import TransactionCase
7
+ from odoo.tests.common import Form, tagged
8
+
9
+
10
+ @tagged("post_install", "-at_install")
11
+ class TestDocumentEdition(TransactionCase):
12
+ @classmethod
13
+ def setUpClass(cls):
14
+ super().setUpClass()
15
+ cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
16
+ cls.user = cls.env.user
17
+ cls.company = cls.env.ref("l10n_br_base.empresa_lucro_presumido")
18
+ cls.user.company_ids |= cls.company
19
+ cls.user.company_id = cls.company.id
20
+
21
+ def test_basic_doc_edition(self):
22
+ doc_form = Form(
23
+ self.env["l10n_br_fiscal.document"].with_context(
24
+ default_fiscal_operation_type="out",
25
+ )
26
+ )
27
+ doc_form.company_id = self.env.ref("l10n_br_base.empresa_lucro_presumido")
28
+ doc_form.partner_id = self.env.ref("l10n_br_base.res_partner_cliente1_sp")
29
+ doc_form.fiscal_operation_id = self.env.ref("l10n_br_fiscal.fo_venda")
30
+ doc_form.ind_final = "1"
31
+ product_id = self.env.ref("product.product_product_6")
32
+ product_id.list_price = 150 # we will later check we can set price_unit to 100
33
+ with doc_form.fiscal_line_ids.new() as line_form:
34
+ original_method = type(
35
+ self.env["l10n_br_fiscal.operation.line"]
36
+ ).map_fiscal_taxes
37
+
38
+ def wrapped_method(self, *args, **kwargs):
39
+ return original_method(self, *args, **kwargs)
40
+
41
+ with mock.patch.object(
42
+ type(self.env["l10n_br_fiscal.operation.line"]),
43
+ "map_fiscal_taxes",
44
+ side_effect=wrapped_method,
45
+ autospec=True,
46
+ ) as mocked:
47
+ line_form.product_id = product_id
48
+
49
+ # ensure the tax engine is called with the proper
50
+ # parameters, especially ind_final
51
+ # as it is related=document_id.ind_final
52
+ # which is converted to move_id.ind_final to work live
53
+ mocked.assert_called_with(
54
+ self.env.ref("l10n_br_fiscal.fo_venda_revenda"),
55
+ company=doc_form.company_id,
56
+ partner=doc_form.partner_id,
57
+ product=product_id,
58
+ ncm=product_id.ncm_id,
59
+ nbm=self.env["l10n_br_fiscal.nbm"],
60
+ nbs=self.env["l10n_br_fiscal.nbs"],
61
+ cest=self.env["l10n_br_fiscal.cest"],
62
+ city_taxation_code=self.env["l10n_br_fiscal.city.taxation.code"],
63
+ service_type=self.env["l10n_br_fiscal.service.type"],
64
+ ind_final="1",
65
+ )
66
+
67
+ line_form.price_unit = 50
68
+ line_form.quantity = 2
69
+ self.assertEqual(len(line_form.fiscal_tax_ids), 4)
70
+ self.assertEqual(
71
+ line_form.icms_tax_id, self.env.ref("l10n_br_fiscal.tax_icms_12")
72
+ )
73
+ self.assertEqual(line_form.icms_value, 12.0)
74
+ line_form.price_unit = 100
75
+ self.assertEqual(
76
+ line_form.icms_tax_id, self.env.ref("l10n_br_fiscal.tax_icms_12")
77
+ )
78
+ self.assertEqual(line_form.icms_value, 24.0)
79
+ self.assertEqual(
80
+ line_form.fiscal_operation_line_id,
81
+ self.env.ref("l10n_br_fiscal.fo_venda_revenda"),
82
+ )
83
+ self.assertEqual(
84
+ line_form.ipi_tax_id, self.env.ref("l10n_br_fiscal.tax_ipi_nt")
85
+ )
86
+
87
+ line_form.fiscal_operation_line_id = self.env.ref(
88
+ "l10n_br_fiscal.fo_venda_venda"
89
+ )
90
+ self.assertEqual(
91
+ line_form.ipi_tax_id, self.env.ref("l10n_br_fiscal.tax_ipi_3_25")
92
+ )
93
+
94
+ # ensure manually setting a xx_tax_id is properly saved (not recomputed):
95
+ line_form.icms_tax_id = self.env.ref("l10n_br_fiscal.tax_icms_18")
96
+ self.assertEqual(line_form.icms_value, 37.17)
97
+ self.assertEqual(
98
+ line_form.ipi_tax_id, self.env.ref("l10n_br_fiscal.tax_ipi_3_25")
99
+ )
100
+ line_form.icmsfcp_base = line_form.price_unit
101
+ line_form.icmsfcp_value = 3 # ensure manually setting FCP value works
102
+
103
+ doc = doc_form.save()
104
+ line = doc.fiscal_line_ids[0]
105
+ self.assertEqual(line.price_unit, 100)
106
+ self.assertEqual(line.fiscal_price, 100)
107
+ self.assertEqual(line.quantity, 2)
108
+ self.assertEqual(line.fiscal_quantity, 2)
109
+ self.assertEqual(len(line.fiscal_tax_ids), 4)
110
+
111
+ self.assertEqual(
112
+ line.fiscal_operation_line_id,
113
+ self.env.ref("l10n_br_fiscal.fo_venda_venda"),
114
+ )
115
+ self.assertEqual(
116
+ line.icms_tax_id.id,
117
+ self.ref("l10n_br_fiscal.tax_icms_18"),
118
+ )
119
+ self.assertEqual(line.ipi_tax_id, self.env.ref("l10n_br_fiscal.tax_ipi_3_25"))
120
+ self.assertEqual(line.icms_value, 37.17)
121
+ self.assertEqual(line.icmsfcp_base, line.price_unit)
122
+ self.assertEqual(line.icmsfcp_value, 3)
123
+
124
+ def test_product_fiscal_factor(self):
125
+ doc_form = Form(
126
+ self.env["l10n_br_fiscal.document"].with_context(
127
+ default_fiscal_operation_type="out",
128
+ )
129
+ )
130
+ doc_form.company_id = self.env.ref("l10n_br_base.empresa_lucro_presumido")
131
+ doc_form.partner_id = self.env.ref("l10n_br_base.res_partner_cliente1_sp")
132
+ doc_form.fiscal_operation_id = self.env.ref("l10n_br_fiscal.fo_venda")
133
+ doc_form.ind_final = "1"
134
+ product_id = self.env.ref("product.product_product_6")
135
+ product_id.uot_factor = 2
136
+ with doc_form.fiscal_line_ids.new() as line_form:
137
+ line_form.product_id = product_id
138
+ line_form.price_unit = 100
139
+ line_form.quantity = 10
140
+
141
+ doc = doc_form.save()
142
+ self.assertEqual(doc.fiscal_line_ids[0].price_unit, 100)
143
+ self.assertEqual(doc.fiscal_line_ids[0].fiscal_price, 50)
144
+ self.assertEqual(doc.fiscal_line_ids[0].quantity, 10)
145
+ self.assertEqual(doc.fiscal_line_ids[0].fiscal_quantity, 20)
146
+
147
+ def test_product_fiscal_price_and_qty_edition(self):
148
+ doc_form = Form(
149
+ self.env["l10n_br_fiscal.document"].with_context(
150
+ default_fiscal_operation_type="out",
151
+ )
152
+ )
153
+ doc_form.company_id = self.env.ref("l10n_br_base.empresa_lucro_presumido")
154
+ doc_form.partner_id = self.env.ref("l10n_br_base.res_partner_cliente1_sp")
155
+ doc_form.fiscal_operation_id = self.env.ref("l10n_br_fiscal.fo_venda")
156
+ doc_form.ind_final = "1"
157
+ product_id = self.env.ref("product.product_product_6")
158
+ product_id.list_price = 100
159
+ with doc_form.fiscal_line_ids.new() as line_form:
160
+ line_form.product_id = product_id
161
+ line_form.price_unit = 110
162
+ line_form.quantity = 10
163
+ line_form.fiscal_price = 112
164
+ line_form.fiscal_quantity = 5
165
+ self.assertEqual(line_form.price_unit, 110)
166
+ self.assertEqual(line_form.fiscal_price, 112)
167
+ self.assertEqual(line_form.quantity, 10)
168
+ self.assertEqual(line_form.fiscal_quantity, 5)
169
+
170
+ doc = doc_form.save()
171
+ self.assertEqual(doc.fiscal_line_ids[0].price_unit, 110)
172
+ self.assertEqual(doc.fiscal_line_ids[0].fiscal_price, 112)
173
+ self.assertEqual(doc.fiscal_line_ids[0].quantity, 10)
174
+ self.assertEqual(doc.fiscal_line_ids[0].fiscal_quantity, 5)
175
+
176
+ def test_landed_costs_by_line_and_by_total(self):
177
+ """
178
+ Tests both landed cost scenarios: 'by line' and 'by total'.
179
+ 1. By Line: Enters costs on lines and verifies the header totals.
180
+ 2. By Total: Enters costs on the header and verifies lines distribution.
181
+ """
182
+ self.env.user.groups_id |= self.env.ref("l10n_br_fiscal.group_user")
183
+ product1 = self.env.ref("product.product_product_6")
184
+ product2 = self.env.ref("product.product_product_7")
185
+
186
+ # Part 1: Test with delivery_costs = 'line'
187
+ # ----------------------------------------------------
188
+ self.company.delivery_costs = "line"
189
+ doc_form = Form(self.env["l10n_br_fiscal.document"])
190
+ doc_form.company_id = self.company
191
+ doc_form.partner_id = self.env.ref("l10n_br_base.res_partner_cliente1_sp")
192
+ doc_form.fiscal_operation_id = self.env.ref("l10n_br_fiscal.fo_venda")
193
+
194
+ with doc_form.fiscal_line_ids.new() as line1:
195
+ line1.product_id = product1
196
+ line1.fiscal_operation_line_id = self.env.ref(
197
+ "l10n_br_fiscal.fo_venda_venda"
198
+ )
199
+ line1.price_unit = 1000.0
200
+ line1.quantity = 2.0 # Gross: 2000
201
+ line1.freight_value = 10.0
202
+ line1.insurance_value = 20.0
203
+ line1.other_value = 5.0
204
+
205
+ with doc_form.fiscal_line_ids.new() as line2:
206
+ line2.product_id = product2
207
+ line2.fiscal_operation_line_id = self.env.ref(
208
+ "l10n_br_fiscal.fo_venda_venda"
209
+ )
210
+ line2.price_unit = 500.0
211
+ line2.quantity = 1.0 # Gross: 500
212
+ line2.freight_value = 4.0
213
+ line2.insurance_value = 6.0
214
+ line2.other_value = 2.0
215
+
216
+ doc = doc_form.save()
217
+
218
+ self.assertEqual(doc.company_id.delivery_costs, "line")
219
+ # Assert header totals are the SUM of line values
220
+ self.assertAlmostEqual(doc.amount_freight_value, 14.0) # 10.0 + 4.0
221
+ self.assertAlmostEqual(doc.amount_insurance_value, 26.0) # 20.0 + 6.0
222
+ self.assertAlmostEqual(doc.amount_other_value, 7.0) # 5.0 + 2.0
223
+
224
+ # Assert final fiscal totals (bottom-up calculation)
225
+ # price_gross = (1000*2) + (500*1) = 2500
226
+ # landed_costs = 14 + 26 + 7 = 47
227
+ # fiscal_amount_untaxed (IPI Base) = 2500 + 47 = 2547
228
+ self.assertAlmostEqual(doc.fiscal_amount_untaxed, 2547.00)
229
+ # fiscal_amount_tax (IPI) = (2035 * 3.25%) + (512 * 5%) = 66.14 + 25.60 = 91.74
230
+ self.assertAlmostEqual(doc.fiscal_amount_tax, 91.74, places=2)
231
+ # fiscal_amount_total = 2547.00 + 91.74 = 2638.74
232
+ self.assertAlmostEqual(doc.fiscal_amount_total, 2638.74, places=2)
233
+
234
+ # Part 2: Test with delivery_costs = 'total'
235
+ # ----------------------------------------------------
236
+ self.company.delivery_costs = "total"
237
+ doc_form_edit = Form(doc)
238
+ # Set new header totals, which should trigger inverse methods to distribute
239
+ doc_form_edit.amount_freight_value = 30.0
240
+ doc_form_edit.amount_insurance_value = 60.0
241
+ doc_form_edit.amount_other_value = 90.0
242
+ doc_after_total_update = doc_form_edit.save()
243
+
244
+ line1 = doc_after_total_update.fiscal_line_ids[0]
245
+ line2 = doc_after_total_update.fiscal_line_ids[1]
246
+
247
+ # Assert values were distributed proportionally to price_gross
248
+ # (2000 vs 500 -> 80% vs 20%)
249
+ # Freight: 30.0 * 0.8 = 24.0 | 30.0 * 0.2 = 6.0
250
+ self.assertAlmostEqual(line1.freight_value, 24.0)
251
+ self.assertAlmostEqual(line2.freight_value, 6.0)
252
+ # Insurance: 60.0 * 0.8 = 48.0 | 60.0 * 0.2 = 12.0
253
+ self.assertAlmostEqual(line1.insurance_value, 48.0)
254
+ self.assertAlmostEqual(line2.insurance_value, 12.0)
255
+ # Other: 90.0 * 0.8 = 72.0 | 90.0 * 0.2 = 18.0
256
+ self.assertAlmostEqual(line1.other_value, 72.0)
257
+ self.assertAlmostEqual(line2.other_value, 18.0)
258
+
259
+ # Assert final fiscal totals are recomputed correctly (top-down calculation)
260
+ # price_gross = 2500
261
+ # landed_costs = 30 + 60 + 90 = 180
262
+ # fiscal_amount_untaxed (IPI Base) = 2500 + 180 = 2680
263
+ self.assertAlmostEqual(doc_after_total_update.fiscal_amount_untaxed, 2680.00)
264
+ # Line 1 IPI Base = 2000 (product) + 24 (freight) + 48 (insurance)
265
+ # + 72 (other) = 2144
266
+ # Line 1 IPI Value = 2144 * 3.25% = 69.68
267
+ self.assertAlmostEqual(line1.ipi_base, 2144.00)
268
+ self.assertAlmostEqual(line1.ipi_value, 69.68, places=2)
269
+
270
+ # Line 2 IPI Base = 500 (product) + 6 (freight) + 12 (insurance)
271
+ # + 18 (other) = 536
272
+ # Line 2 IPI Value = 536 * 5% = 26.80
273
+ self.assertAlmostEqual(line2.ipi_base, 536.00)
274
+ self.assertAlmostEqual(line2.ipi_value, 26.80, places=2)
275
+
276
+ # fiscal_amount_tax (IPI) = 69.68 + 26.80 = 96.48
277
+ self.assertAlmostEqual(
278
+ doc_after_total_update.fiscal_amount_tax, 96.48, places=2
279
+ )
280
+ # fiscal_amount_total = 2680.00 + 96.48 = 2776.48
281
+ self.assertAlmostEqual(
282
+ doc_after_total_update.fiscal_amount_total, 2776.48, places=2
283
+ )
284
+
285
+ def test_difal_calculation(self):
286
+ partner = self.env.ref("l10n_br_base.res_partner_cliente5_pe")
287
+ partner.ind_ie_dest = "9"
288
+ doc_form = Form(
289
+ self.env["l10n_br_fiscal.document"].with_context(
290
+ default_fiscal_operation_type="out",
291
+ )
292
+ )
293
+ doc_form.company_id = self.company
294
+ doc_form.partner_id = partner
295
+ doc_form.fiscal_operation_id = self.env.ref("l10n_br_fiscal.fo_venda")
296
+
297
+ product = self.env.ref("product.product_product_6")
298
+ with doc_form.fiscal_line_ids.new() as line_form:
299
+ line_form.product_id = product
300
+ line_form.price_unit = 100.0
301
+ line_form.quantity = 1.0
302
+
303
+ doc = doc_form.save()
304
+ line = doc.fiscal_line_ids[0]
305
+ self.assertEqual(line.icms_destination_base, 100.0)
306
+ self.assertEqual(line.icms_origin_percent, 7.0)
307
+ self.assertEqual(line.icms_destination_percent, 20.5)
308
+ self.assertEqual(line.icms_destination_value, 13.5)
@@ -2,7 +2,6 @@
2
2
  # Magno Costa <magno.costa@akretion.com.br>
3
3
  # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
4
4
 
5
-
6
5
  from odoo.tests import TransactionCase
7
6
 
8
7
  from ..constants.icms import ICMS_ORIGIN_TAX_IMPORTED
@@ -12,6 +11,8 @@ class TestFiscalDocumentGeneric(TransactionCase):
12
11
  @classmethod
13
12
  def setUpClass(cls):
14
13
  super().setUpClass()
14
+ cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
15
+
15
16
  # Contribuinte
16
17
  cls.nfe_same_state = cls.env.ref("l10n_br_fiscal.demo_nfe_same_state")
17
18
  cls.nfe_other_state = cls.env.ref("l10n_br_fiscal.demo_nfe_other_state")
@@ -38,24 +39,10 @@ class TestFiscalDocumentGeneric(TransactionCase):
38
39
 
39
40
  def test_nfe_same_state(self):
40
41
  """Test NFe same state."""
41
-
42
- self.nfe_same_state._onchange_fiscal_operation_id()
43
-
44
42
  for line in self.nfe_same_state.fiscal_line_ids:
45
- # Save the original price_unit value of the line as defined in
46
- # the NFe demo data.
47
- original_price_unit = line.price_unit
48
-
49
- line._onchange_product_id_fiscal()
50
-
51
43
  # Restore the original price_unit value,
52
44
  # as the product change might have altered it.
53
- line.price_unit = original_price_unit
54
-
55
- line._onchange_commercial_quantity()
56
- line._onchange_fiscal_operation_id()
57
- line._onchange_fiscal_operation_line_id()
58
- line._onchange_fiscal_taxes()
45
+ line.price_unit = 100
59
46
 
60
47
  if "Revenda" in line.fiscal_operation_line_id.name:
61
48
  self.assertEqual(
@@ -85,9 +72,10 @@ class TestFiscalDocumentGeneric(TransactionCase):
85
72
  # ICMS
86
73
  self.assertTrue(
87
74
  is_icms_internal,
88
- "Error to mapping ICMS Inernal for {}"
75
+ "Error to mapping ICMS Inernal for "
76
+ f"{self.nfe_same_state.partner_id.state_id.name}"
89
77
  " for Venda de Contribuinte Dentro do "
90
- "Estado.".format(self.nfe_same_state.partner_id.state_id.name),
78
+ "Estado.",
91
79
  )
92
80
  self.assertEqual(
93
81
  line.icms_cst_id.code,
@@ -169,16 +157,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
169
157
 
170
158
  def test_nfe_other_state(self):
171
159
  """Test NFe other state."""
172
-
173
- self.nfe_other_state._onchange_fiscal_operation_id()
174
-
175
160
  for line in self.nfe_other_state.fiscal_line_ids:
176
- line._onchange_product_id_fiscal()
177
- line._onchange_commercial_quantity()
178
- line._onchange_fiscal_operation_id()
179
- line._onchange_fiscal_operation_line_id()
180
- line._onchange_fiscal_taxes()
181
-
182
161
  if "Revenda" in line.fiscal_operation_line_id.name:
183
162
  self.assertEqual(
184
163
  line.cfop_id.code,
@@ -289,16 +268,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
289
268
 
290
269
  def test_nfe_not_taxpayer(self):
291
270
  """Test NFe not taxpayer."""
292
-
293
- self.nfe_not_taxpayer._onchange_fiscal_operation_id()
294
-
295
271
  for line in self.nfe_not_taxpayer.fiscal_line_ids:
296
- line._onchange_product_id_fiscal()
297
- line._onchange_commercial_quantity()
298
- line._onchange_fiscal_operation_id()
299
- line._onchange_fiscal_operation_line_id()
300
- line._onchange_fiscal_taxes()
301
-
302
272
  if "Revenda" in line.fiscal_operation_line_id.name:
303
273
  self.assertEqual(
304
274
  line.cfop_id.code,
@@ -396,16 +366,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
396
366
 
397
367
  def test_nfe_not_taxpayer_not_company(self):
398
368
  """Test NFe not taxpayer not Company."""
399
-
400
- self.nfe_not_taxpayer_pf._onchange_fiscal_operation_id()
401
-
402
369
  for line in self.nfe_not_taxpayer_pf.fiscal_line_ids:
403
- line._onchange_product_id_fiscal()
404
- line._onchange_commercial_quantity()
405
- line._onchange_fiscal_operation_id()
406
- line._onchange_fiscal_operation_line_id()
407
- line._onchange_fiscal_taxes()
408
-
409
370
  if "Revenda" in line.fiscal_operation_line_id.name:
410
371
  self.assertEqual(
411
372
  line.cfop_id.code,
@@ -503,16 +464,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
503
464
 
504
465
  def test_nfe_export(self):
505
466
  """Test NFe export."""
506
-
507
- self.nfe_export._onchange_fiscal_operation_id()
508
-
509
467
  for line in self.nfe_export.fiscal_line_ids:
510
- line._onchange_product_id_fiscal()
511
- line._onchange_commercial_quantity()
512
- line._onchange_fiscal_operation_id()
513
- line._onchange_fiscal_operation_line_id()
514
- line._onchange_fiscal_taxes()
515
-
516
468
  if "Revenda" in line.fiscal_operation_line_id.name:
517
469
  self.assertEqual(
518
470
  line.cfop_id.code,
@@ -576,8 +528,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
576
528
  self.assertEqual(
577
529
  line.pis_tax_id.name,
578
530
  "PIS 0,65%",
579
- "Error to mapping PIS 0,65%"
580
- " for Venda de Contribuinte p/ o Exterior.",
531
+ "Error to mapping PIS 0,65% for Venda de Contribuinte p/ o Exterior.",
581
532
  )
582
533
  self.assertEqual(
583
534
  line.pis_cst_id.code,
@@ -591,8 +542,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
591
542
  self.assertEqual(
592
543
  line.cofins_tax_id.name,
593
544
  "COFINS 3%",
594
- "Error to mapping COFINS 3%"
595
- " for Venda de Contribuinte p/ o Exterior.",
545
+ "Error to mapping COFINS 3% for Venda de Contribuinte p/ o Exterior.",
596
546
  )
597
547
  self.assertEqual(
598
548
  line.cofins_cst_id.code,
@@ -604,13 +554,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
604
554
 
605
555
  def test_nfe_sn_same_state(self):
606
556
  """Test NFe Simples Nacional same state."""
607
-
608
- self.nfe_sn_same_state._onchange_fiscal_operation_id()
609
-
610
557
  for line in self.nfe_sn_same_state.fiscal_line_ids:
611
- line._onchange_product_id_fiscal()
612
- line._onchange_commercial_quantity()
613
-
614
558
  # set fake estimate tax
615
559
  line.ncm_id.tax_estimate_ids.create(
616
560
  {
@@ -621,10 +565,9 @@ class TestFiscalDocumentGeneric(TransactionCase):
621
565
  "federal_taxes_national": 33.00,
622
566
  }
623
567
  )
624
-
625
- line._onchange_fiscal_operation_id()
626
- line._onchange_fiscal_operation_line_id()
627
- line._onchange_fiscal_taxes()
568
+ # força o compute, pois não é chamado automaticamente
569
+ # quando uma informação externa muda.
570
+ line._compute_tax_fields()
628
571
 
629
572
  if "Revenda" in line.fiscal_operation_line_id.name:
630
573
  self.assertEqual(
@@ -722,16 +665,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
722
665
 
723
666
  def test_nfe_sn_other_state(self):
724
667
  """Test NFe SN other state."""
725
-
726
- self.nfe_sn_other_state._onchange_fiscal_operation_id()
727
-
728
668
  for line in self.nfe_sn_other_state.fiscal_line_ids:
729
- line._onchange_product_id_fiscal()
730
- line._onchange_commercial_quantity()
731
- line._onchange_fiscal_operation_id()
732
- line._onchange_fiscal_operation_line_id()
733
- line._onchange_fiscal_taxes()
734
-
735
669
  if "Revenda" in line.fiscal_operation_line_id.name:
736
670
  self.assertEqual(
737
671
  line.cfop_id.code,
@@ -825,16 +759,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
825
759
 
826
760
  def test_nfe_sn_not_taxpayer(self):
827
761
  """Test NFe SN not taxpayer."""
828
-
829
- self.nfe_sn_not_taxpayer._onchange_fiscal_operation_id()
830
-
831
762
  for line in self.nfe_sn_not_taxpayer.fiscal_line_ids:
832
- line._onchange_product_id_fiscal()
833
- line._onchange_commercial_quantity()
834
- line._onchange_fiscal_operation_id()
835
- line._onchange_fiscal_operation_line_id()
836
- line._onchange_fiscal_taxes()
837
-
838
763
  if "Revenda" in line.fiscal_operation_line_id.name:
839
764
  self.assertEqual(
840
765
  line.cfop_id.code,
@@ -874,8 +799,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
874
799
  self.assertEqual(
875
800
  line.ipi_tax_id.name,
876
801
  "IPI 5%",
877
- "Erro ao mapear IPI 5%"
878
- " para Venda de Simples Nacional Fora do Estado.",
802
+ "Erro ao mapear IPI 5% para Venda de Simples Nacional Fora do Estado.",
879
803
  )
880
804
  self.assertEqual(
881
805
  line.ipi_cst_id.code,
@@ -916,16 +840,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
916
840
 
917
841
  def test_nfe_sn_export(self):
918
842
  """Test NFe SN export."""
919
-
920
- self.nfe_sn_export._onchange_fiscal_operation_id()
921
-
922
843
  for line in self.nfe_sn_export.fiscal_line_ids:
923
- line._onchange_product_id_fiscal()
924
- line._onchange_commercial_quantity()
925
- line._onchange_fiscal_operation_id()
926
- line._onchange_fiscal_operation_line_id()
927
- line._onchange_fiscal_taxes()
928
-
929
844
  if "Revenda" in line.fiscal_operation_line_id.name:
930
845
  self.assertEqual(
931
846
  line.cfop_id.code,
@@ -1035,7 +950,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
1035
950
  additional_data = self.nfe_not_taxpayer.fiscal_line_ids[0].additional_data
1036
951
  self.assertEqual(
1037
952
  additional_data,
1038
- "manual comment test",
953
+ "manual comment test - Valor Aprox. dos Tributos: R$\xa00,00",
1039
954
  )
1040
955
 
1041
956
  def test_fields_freight_insurance_other_costs(self):
@@ -1045,6 +960,7 @@ class TestFiscalDocumentGeneric(TransactionCase):
1045
960
 
1046
961
  # Teste definindo os valores Por Linha
1047
962
  for line in self.nfe_same_state.fiscal_line_ids:
963
+ line.price_unit = 100
1048
964
  line.freight_value = 10.0
1049
965
  line.insurance_value = 10.0
1050
966
  line.other_value = 10.0
@@ -1052,19 +968,17 @@ class TestFiscalDocumentGeneric(TransactionCase):
1052
968
  self.assertEqual(
1053
969
  self.nfe_same_state.amount_freight_value,
1054
970
  20.0,
1055
- "Unexpected value for the field" " Amount Freight in Fiscal Document line",
971
+ "Unexpected value for the field Amount Freight in Fiscal Document line",
1056
972
  )
1057
973
  self.assertEqual(
1058
974
  self.nfe_same_state.amount_insurance_value,
1059
975
  20.0,
1060
- "Unexpected value for the field"
1061
- " Amount Insurance in Fiscal Document line",
976
+ "Unexpected value for the field Amount Insurance in Fiscal Document line",
1062
977
  )
1063
978
  self.assertEqual(
1064
979
  self.nfe_same_state.amount_other_value,
1065
980
  20.0,
1066
- "Unexpected value for the field"
1067
- " Amount Other Value in Fiscal Document line",
981
+ "Unexpected value for the field Amount Other Value in Fiscal Document line",
1068
982
  )
1069
983
 
1070
984
  # Teste definindo os valores Por Total
@@ -1080,18 +994,17 @@ class TestFiscalDocumentGeneric(TransactionCase):
1080
994
  self.assertEqual(
1081
995
  line.freight_value,
1082
996
  5.0,
1083
- "Unexpected value for the field" " Freight in Fiscal Document line",
997
+ "Unexpected value for the field Freight in Fiscal Document line",
1084
998
  )
1085
999
  self.assertEqual(
1086
1000
  line.insurance_value,
1087
1001
  5.0,
1088
- "Unexpected value for the field" " Insurance in Fiscal Document line",
1002
+ "Unexpected value for the field Insurance in Fiscal Document line",
1089
1003
  )
1090
1004
  self.assertEqual(
1091
1005
  line.other_value,
1092
1006
  5.0,
1093
- "Unexpected value for the field"
1094
- " Other Values in Fiscal Document line",
1007
+ "Unexpected value for the field Other Values in Fiscal Document line",
1095
1008
  )
1096
1009
 
1097
1010
  # Caso que os Campos na Linha não tem valor
@@ -1108,16 +1021,15 @@ class TestFiscalDocumentGeneric(TransactionCase):
1108
1021
  self.assertEqual(
1109
1022
  line.freight_value,
1110
1023
  10.0,
1111
- "Unexpected value for the field" " Freight in Fiscal Document line",
1024
+ "Unexpected value for the field Freight in Fiscal Document line",
1112
1025
  )
1113
1026
  self.assertEqual(
1114
1027
  line.insurance_value,
1115
1028
  10.0,
1116
- "Unexpected value for the field" " Insurance in Fiscal Document line",
1029
+ "Unexpected value for the field Insurance in Fiscal Document line",
1117
1030
  )
1118
1031
  self.assertEqual(
1119
1032
  line.other_value,
1120
1033
  10.0,
1121
- "Unexpected value for the field"
1122
- " Other Values in Fiscal Document line",
1034
+ "Unexpected value for the field Other Values in Fiscal Document line",
1123
1035
  )
@@ -5,23 +5,15 @@ from odoo.tests.common import TransactionCase
5
5
 
6
6
 
7
7
  class TestFiscalDocumentNFSe(TransactionCase):
8
- def setUp(self):
9
- super().setUp()
10
-
11
- self.nfse_same_state = self.env.ref("l10n_br_fiscal.demo_nfse_same_state")
8
+ @classmethod
9
+ def setUpClass(cls):
10
+ super().setUpClass()
11
+ cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
12
+ cls.nfse_same_state = cls.env.ref("l10n_br_fiscal.demo_nfse_same_state")
12
13
 
13
14
  def test_nfse_same_state(self):
14
15
  """Test NFSe same state."""
15
-
16
- self.nfse_same_state._onchange_fiscal_operation_id()
17
-
18
16
  for line in self.nfse_same_state.fiscal_line_ids:
19
- line._onchange_product_id_fiscal()
20
- line._onchange_commercial_quantity()
21
- line._onchange_fiscal_operation_id()
22
- line._onchange_fiscal_operation_line_id()
23
- line._onchange_fiscal_taxes()
24
-
25
17
  self.assertEqual(
26
18
  line.fiscal_operation_line_id.name,
27
19
  "Prestação de Serviço",