From cdf444743f0646c8751d7e90d4900b4811fc0829 Mon Sep 17 00:00:00 2001 From: Luis Felipe Mileo Date: Mon, 25 Mar 2024 11:33:44 -0300 Subject: [PATCH 1/5] [IMP] l10n_br_fiscal: adds icms st demo data --- l10n_br_fiscal/data/operation_data.xml | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/l10n_br_fiscal/data/operation_data.xml b/l10n_br_fiscal/data/operation_data.xml index 9834da0c743c..402ddc5ec934 100644 --- a/l10n_br_fiscal/data/operation_data.xml +++ b/l10n_br_fiscal/data/operation_data.xml @@ -42,6 +42,49 @@ 00 + + + Venda ST contribuinte substituto + 1 + + + approved + 04 + + + + + Revenda ST contribuinte substituto + 1 + + + approved + 00 + + + + + Revenda ST contribuinte substituído + 1 + + + approved + 00 + + + + + Revenda ST contribuinte substituído SN + 1 + + + approved + 00 + + Venda não Contribuinte From d27b6ef4f93810e3ead9e9b42e16cb31708d4dae Mon Sep 17 00:00:00 2001 From: Tiago Amaral Date: Fri, 1 Nov 2024 17:14:46 -0300 Subject: [PATCH 2/5] [IMP] l10n_br_pos: fix POS config test. --- l10n_br_pos/tests/test_l10n_br_pos_config.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/l10n_br_pos/tests/test_l10n_br_pos_config.py b/l10n_br_pos/tests/test_l10n_br_pos_config.py index 8b54e9b5254d..427fb2f84470 100644 --- a/l10n_br_pos/tests/test_l10n_br_pos_config.py +++ b/l10n_br_pos/tests/test_l10n_br_pos_config.py @@ -16,8 +16,7 @@ def test_pos_config_sales_fiscal_operation(self): "l10n_br_fiscal.fo_venda" ) self.pos_config._compute_allowed_tax() - self.assertEqual( - 4, + self.assertTrue( len(self.pos_config.out_pos_fiscal_operation_line_ids), "Tax operations lines were not found.", ) From c949d2ba77201102df5d3a5819c534a9cdb57b60 Mon Sep 17 00:00:00 2001 From: Diego Paradeda Date: Fri, 4 Oct 2024 15:53:24 -0300 Subject: [PATCH 3/5] [IMP] l10n_br_fiscal: use operation line/product tags --- l10n_br_fiscal/models/__init__.py | 1 + l10n_br_fiscal/models/operation.py | 7 +++++++ l10n_br_fiscal/models/operation_line.py | 8 ++++++++ l10n_br_fiscal/models/product_tag.py | 19 +++++++++++++++++++ l10n_br_fiscal/models/product_template.py | 4 ++++ l10n_br_fiscal/security/ir.model.access.csv | 3 +++ l10n_br_fiscal/views/operation_line_view.xml | 5 +++++ l10n_br_fiscal/views/product_product_view.xml | 5 +++++ .../views/product_template_view.xml | 5 +++++ 9 files changed, 57 insertions(+) create mode 100644 l10n_br_fiscal/models/product_tag.py diff --git a/l10n_br_fiscal/models/__init__.py b/l10n_br_fiscal/models/__init__.py index e0562968855e..3e487b7450de 100644 --- a/l10n_br_fiscal/models/__init__.py +++ b/l10n_br_fiscal/models/__init__.py @@ -20,6 +20,7 @@ from . import ncm from . import nbm from . import cest +from . import product_tag from . import tax_group from . import tax from . import tax_pis_cofins diff --git a/l10n_br_fiscal/models/operation.py b/l10n_br_fiscal/models/operation.py index afff7df9249b..34b95f2526c5 100644 --- a/l10n_br_fiscal/models/operation.py +++ b/l10n_br_fiscal/models/operation.py @@ -235,6 +235,12 @@ def _line_domain(self, company, partner, product): ("icms_origin", "=", False), ] + domain += [ + "|", + ("product_fiscal_tag_ids", "in", product.operation_line_tag_ids.ids), + ("product_fiscal_tag_ids", "=", False), + ] + return domain def line_definition(self, company, partner, product): @@ -258,6 +264,7 @@ def score(line): "product_type", "tax_icms_or_issqn", "icms_origin", + "product_fiscal_tag_ids", ] return sum(1 for field in fields if getattr(line, field)) diff --git a/l10n_br_fiscal/models/operation_line.py b/l10n_br_fiscal/models/operation_line.py index e2cde39e3b8b..9805b628b655 100644 --- a/l10n_br_fiscal/models/operation_line.py +++ b/l10n_br_fiscal/models/operation_line.py @@ -105,6 +105,14 @@ class OperationLine(models.Model): selection=PRODUCT_FISCAL_TYPE, string="Product Fiscal Type" ) + product_fiscal_tag_ids = fields.Many2many( + comodel_name="l10n_br_fiscal.product.tag", + string="Fiscal Product Tags", + help="If enabled, only products that share a product tag with this line can " + "auto-select this operation line. When other factors are equal, a match will " + "be preferred over a line without this setting.", + ) + company_tax_framework = fields.Selection(selection=TAX_FRAMEWORK) add_to_amount = fields.Boolean(string="Add to Document Amount?", default=True) diff --git a/l10n_br_fiscal/models/product_tag.py b/l10n_br_fiscal/models/product_tag.py new file mode 100644 index 000000000000..77156293918d --- /dev/null +++ b/l10n_br_fiscal/models/product_tag.py @@ -0,0 +1,19 @@ +# Copyright (C) 2024 Diego Paradeda - KMEE +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html + +from odoo import _, fields, models + + +class ProductTag(models.Model): + _name = "l10n_br_fiscal.product.tag" + _description = "Fiscal Product Tags" + + name = fields.Char() + + _sql_constraints = [ + ( + "fiscal_tag_name_uniq", + "unique (name)", + _("Fiscal Product Tag already exists with this code !"), + ) + ] diff --git a/l10n_br_fiscal/models/product_template.py b/l10n_br_fiscal/models/product_template.py index 1214a494aeaf..17d135f18b09 100644 --- a/l10n_br_fiscal/models/product_template.py +++ b/l10n_br_fiscal/models/product_template.py @@ -67,6 +67,10 @@ def _get_default_ncm_id(self): comodel_name="l10n_br_fiscal.product.genre", string="Fiscal Product Genre" ) + operation_line_tag_ids = fields.Many2many( + comodel_name="l10n_br_fiscal.product.tag", string="Operation Line Tags" + ) + service_type_id = fields.Many2one( comodel_name="l10n_br_fiscal.service.type", string="Service Type LC 166", diff --git a/l10n_br_fiscal/security/ir.model.access.csv b/l10n_br_fiscal/security/ir.model.access.csv index 5242c8d02d2f..bced9e78b2ac 100644 --- a/l10n_br_fiscal/security/ir.model.access.csv +++ b/l10n_br_fiscal/security/ir.model.access.csv @@ -38,6 +38,9 @@ "l10n_br_fiscal_product_genre_user","Fiscal Fiscal Product Genre for User","model_l10n_br_fiscal_product_genre","l10n_br_fiscal.group_user",1,0,0,0 "l10n_br_fiscal_product_genre_manager","Fiscal Fiscal Product Genre for Manager","model_l10n_br_fiscal_product_genre","l10n_br_fiscal.group_manager",1,0,0,0 "l10n_br_fiscal_product_genre_maintenance","Fiscal Fiscal Product Genre for Maintenance","model_l10n_br_fiscal_product_genre","l10n_br_fiscal.group_data_maintenance",1,1,1,1 +"l10n_br_fiscal_product_tag_user","Fiscal Fiscal Product Tag for User","model_l10n_br_fiscal_product_tag","l10n_br_fiscal.group_user",1,0,0,0 +"l10n_br_fiscal_product_tag_manager","Fiscal Fiscal Product Tag for Manager","model_l10n_br_fiscal_product_tag","l10n_br_fiscal.group_manager",1,1,1,1 +"l10n_br_fiscal_product_tag_maintenance","Fiscal Fiscal Product Tag for Maintenance","model_l10n_br_fiscal_product_tag","l10n_br_fiscal.group_data_maintenance",1,1,1,1 "l10n_br_fiscal_document_type_user","Fiscal Document Type for User","model_l10n_br_fiscal_document_type","l10n_br_fiscal.group_user",1,0,0,0 "l10n_br_fiscal_document_type_manager","Fiscal Document Type for Manager","model_l10n_br_fiscal_document_type","l10n_br_fiscal.group_manager",1,0,0,0 "l10n_br_fiscal_document_type_maintenance","Fiscal Document Type for Maintenance","model_l10n_br_fiscal_document_type","l10n_br_fiscal.group_data_maintenance",1,1,1,1 diff --git a/l10n_br_fiscal/views/operation_line_view.xml b/l10n_br_fiscal/views/operation_line_view.xml index 3a2120a3d11f..1dc539e95b6f 100644 --- a/l10n_br_fiscal/views/operation_line_view.xml +++ b/l10n_br_fiscal/views/operation_line_view.xml @@ -49,6 +49,11 @@ + diff --git a/l10n_br_fiscal/views/product_product_view.xml b/l10n_br_fiscal/views/product_product_view.xml index 1907a2e538ac..ba0ec63adf79 100644 --- a/l10n_br_fiscal/views/product_product_view.xml +++ b/l10n_br_fiscal/views/product_product_view.xml @@ -102,6 +102,11 @@ name="ipi_control_seal_id" attrs="{'invisible': [('fiscal_type', '=', '09')]}" /> + diff --git a/l10n_br_fiscal/views/product_template_view.xml b/l10n_br_fiscal/views/product_template_view.xml index e04ff3ab07a2..9676c2d14c00 100644 --- a/l10n_br_fiscal/views/product_template_view.xml +++ b/l10n_br_fiscal/views/product_template_view.xml @@ -123,6 +123,11 @@ attrs="{'invisible': [('fiscal_type', '!=', '09')]}" options="{'no_create': True, 'no_create_edit': True}" /> + Date: Fri, 4 Oct 2024 17:45:10 -0300 Subject: [PATCH 4/5] [IMP] l10n_br_fiscal: add product.tag view --- l10n_br_fiscal/__manifest__.py | 1 + .../views/l10n_br_fiscal_action.xml | 17 ++++++++++ l10n_br_fiscal/views/l10n_br_fiscal_menu.xml | 9 ++++++ l10n_br_fiscal/views/product_tag_view.xml | 31 +++++++++++++++++++ 4 files changed, 58 insertions(+) create mode 100644 l10n_br_fiscal/views/product_tag_view.xml diff --git a/l10n_br_fiscal/__manifest__.py b/l10n_br_fiscal/__manifest__.py index 48b7a2a466e4..8b66b61e9cdd 100644 --- a/l10n_br_fiscal/__manifest__.py +++ b/l10n_br_fiscal/__manifest__.py @@ -57,6 +57,7 @@ "views/ncm_view.xml", "views/nbm_view.xml", "views/nbs_view.xml", + "views/product_tag_view.xml", "views/service_type_view.xml", "views/cest_view.xml", "views/product_genre_view.xml", diff --git a/l10n_br_fiscal/views/l10n_br_fiscal_action.xml b/l10n_br_fiscal/views/l10n_br_fiscal_action.xml index 94f398b5a926..5ed1b8531455 100644 --- a/l10n_br_fiscal/views/l10n_br_fiscal_action.xml +++ b/l10n_br_fiscal/views/l10n_br_fiscal_action.xml @@ -516,6 +516,23 @@ + + + Product Tag + ir.actions.act_window + l10n_br_fiscal.product.tag + tree + + + +

+ Create a new Product Tag +

+ Product Tags assist in matching Operation Lines with their corresponding products, ensuring accurate identification and organization within the system. +

+
+
+ Subsequent Document diff --git a/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml b/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml index ac59172b5f2d..2c156c3f170a 100644 --- a/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml +++ b/l10n_br_fiscal/views/l10n_br_fiscal_menu.xml @@ -524,6 +524,15 @@ sequence="30" /> + + + + + + + + l10n_br_fiscal.product_tag.search + l10n_br_fiscal.product.tag + + + + + + + + + l10n_br_fiscal.product_tag.tree + l10n_br_fiscal.product.tag + + + + + + + + + + From ed9cbb02ee357d5d983a4f68c2a6085c19ea2909 Mon Sep 17 00:00:00 2001 From: Tiago Amaral Date: Wed, 6 Nov 2024 09:23:19 -0300 Subject: [PATCH 5/5] [IMP] l10n_br_fiscal: add product.tag test --- l10n_br_fiscal/data/operation_data.xml | 60 +++++++++ l10n_br_fiscal/demo/fiscal_document_demo.xml | 117 ++++++++++++++++- l10n_br_fiscal/demo/product_demo.xml | 122 ++++++++++++++++++ .../tests/test_fiscal_document_generic.py | 96 ++++++++++++++ 4 files changed, 392 insertions(+), 3 deletions(-) diff --git a/l10n_br_fiscal/data/operation_data.xml b/l10n_br_fiscal/data/operation_data.xml index 402ddc5ec934..52d6fb79451a 100644 --- a/l10n_br_fiscal/data/operation_data.xml +++ b/l10n_br_fiscal/data/operation_data.xml @@ -42,6 +42,36 @@ 00 + + ST CFOP 6404 + + + ST CFOP 6401 + + + + + + + + + approved + + + + + + + + approved + + Venda ST contribuinte substituto @@ -50,6 +80,15 @@ approved 04 + + icms + @@ -62,6 +101,18 @@ 00 + + + + + + + approved + + Revenda ST contribuinte substituído @@ -70,6 +121,15 @@ approved 00 + + icms + out - + @@ -285,7 +285,7 @@ /> 1 - + out @@ -385,7 +385,7 @@ /> 1 - + out @@ -946,5 +946,116 @@ + + + + + + + 1 + + + out + + + + + Teste ST + + + 100 + 1 + out + + + + + + + + + + + 100 + + + + + + + + + + + + + + + + + 1 + + + out + + + + + Teste ST + + + 100 + 1 + out + + + + + + + + + + + 100 + + + + + + + + + diff --git a/l10n_br_fiscal/demo/product_demo.xml b/l10n_br_fiscal/demo/product_demo.xml index da9bb80e4161..d68a609b6531 100644 --- a/l10n_br_fiscal/demo/product_demo.xml +++ b/l10n_br_fiscal/demo/product_demo.xml @@ -1978,4 +1978,126 @@ + + + Office Lamp ST 6404 + icms + + 35.0 + 40.0 + consu + 0.01 + + + FURN_8889 + + + + + + + + + + fiscal_type + + 00 + selection + + + + + + icms_origin + + 5 + selection + + + + + + + + Office Lamp ST 6401 + icms + + 35.0 + 40.0 + consu + 0.01 + + + FURN_8880 + + + + + + + + + + fiscal_type + + 04 + selection + + + + + + icms_origin + + 5 + selection + + + diff --git a/l10n_br_fiscal/tests/test_fiscal_document_generic.py b/l10n_br_fiscal/tests/test_fiscal_document_generic.py index 281ecbd945f4..0d73e2537255 100644 --- a/l10n_br_fiscal/tests/test_fiscal_document_generic.py +++ b/l10n_br_fiscal/tests/test_fiscal_document_generic.py @@ -15,6 +15,12 @@ def setUpClass(cls): # Contribuinte cls.nfe_same_state = cls.env.ref("l10n_br_fiscal.demo_nfe_same_state") cls.nfe_other_state = cls.env.ref("l10n_br_fiscal.demo_nfe_other_state") + cls.nfe_other_state_st_6404 = cls.env.ref( + "l10n_br_fiscal.demo_nfe_other_state_st_6404" + ) + cls.nfe_other_state_st_6401 = cls.env.ref( + "l10n_br_fiscal.demo_nfe_other_state_st_6401" + ) cls.nfe_not_taxpayer = cls.env.ref("l10n_br_fiscal.demo_nfe_nao_contribuinte") cls.nfe_not_taxpayer_pf = cls.env.ref( @@ -291,6 +297,96 @@ def test_nfe_other_state(self): "from COFINS 3% for Venda de Contribuinte p/ Fora do Estado.", ) + def test_nfe_other_state_st_6404(self): + """Testing NFe in another state with tax substitution.""" + empresa_lucro_presumido = self.env.ref("l10n_br_base.empresa_lucro_presumido") + self.nfe_other_state_st_6404._onchange_document_serie_id() + self.nfe_other_state_st_6404._onchange_fiscal_operation_id() + + for line in self.nfe_other_state_st_6404.fiscal_line_ids: + line.with_company(empresa_lucro_presumido.id)._onchange_product_id_fiscal() + line.with_company( + empresa_lucro_presumido.id + )._onchange_commercial_quantity() + line.with_company(empresa_lucro_presumido.id)._onchange_ncm_id() + line.with_company( + empresa_lucro_presumido.id + )._onchange_fiscal_operation_id() + line.with_company( + empresa_lucro_presumido.id + )._onchange_fiscal_operation_line_id() + line.with_company(empresa_lucro_presumido.id)._onchange_fiscal_taxes() + + self.assertEqual( + line.cfop_id.code, + "6404", + "Error to mapping CFOP 6404" + " for Revenda de Contribuinte p/ Fora do Estado.", + ) + + # ICMS + line.with_company(empresa_lucro_presumido.id)._onchange_fiscal_taxes() + self.assertEqual( + line.icms_tax_id.id, + self.env.ref("l10n_br_fiscal.tax_icms_antst").id, + "Error to mapping ICMS Cobrado Ant. por ST" + " for Venda de Contribuinte p/ Fora do Estado.", + ) + self.assertEqual( + line.icms_cst_id.code, + "60", + "Error to mapping CST 60 from ICMS Cobrado Ant. por ST" + " for Venda de Contribuinte p/ Fora do Estado.", + ) + + def test_nfe_other_state_st_6401(self): + """Testing NFe in another state with tax substitution.""" + empresa_lucro_presumido = self.env.ref("l10n_br_base.empresa_lucro_presumido") + self.nfe_other_state_st_6401._onchange_document_serie_id() + self.nfe_other_state_st_6401._onchange_fiscal_operation_id() + + for line in self.nfe_other_state_st_6401.fiscal_line_ids: + line.with_company(empresa_lucro_presumido.id)._onchange_product_id_fiscal() + line.with_company( + empresa_lucro_presumido.id + )._onchange_commercial_quantity() + line.with_company(empresa_lucro_presumido.id)._onchange_ncm_id() + line.with_company( + empresa_lucro_presumido.id + )._onchange_fiscal_operation_id() + line.with_company( + empresa_lucro_presumido.id + )._onchange_fiscal_operation_line_id() + line.with_company(empresa_lucro_presumido.id)._onchange_fiscal_taxes() + + self.assertEqual( + line.cfop_id.code, + "6401", + "Error to mapping CFOP 6401" + " for Venda de Contribuinte p/ Fora do Estado.", + ) + + # ICMS + line.with_company(empresa_lucro_presumido.id)._onchange_fiscal_taxes() + self.assertEqual( + line.icms_tax_id.id, + self.env.ref("l10n_br_fiscal.tax_icms_12_st").id, + "Error to mapping ICMS 010 12%" + " for Venda de Contribuinte p/ Fora do Estado.", + ) + self.assertEqual( + line.icmsst_tax_id.id, + self.env.ref("l10n_br_fiscal.tax_icmsst_p30_50").id, + "Error to mapping ICMS 30% MVA 50" + " for Venda de Contribuinte p/ Fora do Estado.", + ) + self.assertEqual( + line.icms_cst_id.code, + "10", + "Error to mapping CST 10 from ICMS 010 12%" + " for Venda de Contribuinte p/ Fora do Estado.", + ) + def test_nfe_not_taxpayer(self): """Test NFe not taxpayer."""