From 53a32f62d4697daae66bfdf192a4e54babaf3194 Mon Sep 17 00:00:00 2001 From: Marcel Savegnago Date: Tue, 12 Aug 2025 15:29:06 -0300 Subject: [PATCH 1/2] [IMP] l10n_br_account: manual values for taxes --- l10n_br_account/models/account_move_line.py | 133 +++++++++++++++++++- l10n_br_account/models/account_tax.py | 4 + 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/l10n_br_account/models/account_move_line.py b/l10n_br_account/models/account_move_line.py index 742af0d75b1a..6c58e5693ed9 100644 --- a/l10n_br_account/models/account_move_line.py +++ b/l10n_br_account/models/account_move_line.py @@ -9,6 +9,28 @@ from odoo.addons.l10n_br_fiscal.constants.fiscal import FISCAL_TAX_ID_FIELDS +FISCAL_TAX_PREFIXES = [ + "icms", + "icmsst", + "issqn", + "issqn_wh", + "icmsst_wh", + "ipi", + "ii", + "cofins", + "cofinsst", + "cofins_wh", + "pis", + "pisst", + "pis_wh", + "csll", + "csll_wh", + "irpj", + "irpj_wh", + "inss", + "inss_wh", +] + class AccountMoveLine(models.Model): _name = "account.move.line" @@ -300,6 +322,22 @@ def changed(fname): self.env.add_to_compute(self._fields["debit"], container["records"]) self.env.add_to_compute(self._fields["credit"], container["records"]) + def _get_manual_tax_values_from_context(self): + tax_values = {} + suffixes = ["_base_manual", "_value_manual"] + + for tax_prefix in FISCAL_TAX_PREFIXES: + for suffix in suffixes: + attr_name = tax_prefix + suffix + # tenta pegar do contexto + value = self.env.context.get(attr_name) + # se não veio do contexto, tenta pegar do próprio objeto + if value is None: + value = getattr(self, attr_name, None) + tax_values[attr_name] = value + + return tax_values + @api.depends( "quantity", "discount", @@ -326,6 +364,44 @@ def changed(fname): "icms_origin", "ind_final", "icms_relief_value", + "icms_base_manual", + "icms_value_manual", + "icmsst_base_manual", + "icmsst_value_manual", + "issqn_base_manual", + "issqn_value_manual", + "issqn_wh_base_manual", + "issqn_wh_value_manual", + "icmsst_wh_base_manual", + "icmsst_wh_value_manual", + "ipi_base_manual", + "ipi_value_manual", + "ii_base_manual", + "ii_value_manual", + "cofins_base_manual", + "cofins_value_manual", + "cofinsst_base_manual", + "cofinsst_value_manual", + "cofins_wh_base_manual", + "cofins_wh_value_manual", + "pis_base_manual", + "pis_value_manual", + "pisst_base_manual", + "pisst_value_manual", + "pis_wh_base_manual", + "pis_wh_value_manual", + "csll_base_manual", + "csll_value_manual", + "csll_wh_base_manual", + "csll_wh_value_manual", + "irpj_base_manual", + "irpj_value_manual", + "irpj_wh_base_manual", + "irpj_wh_value_manual", + "inss_base_manual", + "inss_value_manual", + "inss_wh_base_manual", + "inss_wh_value_manual", ) def _compute_totals(self): """ @@ -344,6 +420,7 @@ def _compute_totals(self): # Compute 'price_total'. if line.tax_ids: + manual_tax_values = line._get_manual_tax_values_from_context() taxes_res = line.tax_ids._origin.with_context().compute_all( line_discount_price_unit, currency=line.currency_id, @@ -370,6 +447,7 @@ def _compute_totals(self): icmssn_range=line.icmssn_range_id, icms_origin=line.icms_origin, ind_final=line.ind_final, + **manual_tax_values, ) line.price_subtotal = taxes_res["total_excluded"] @@ -424,6 +502,7 @@ def _compute_all_tax(self): for line in self: sign = line.move_id.direction_sign + manual_tax_values = line._prepare_br_manual_tax_dict() if line.display_type == "tax": line.compute_all_tax = {} line.compute_all_tax_dirty = False @@ -464,6 +543,7 @@ def _compute_all_tax(self): icmssn_range=line.icmssn_range_id, icms_origin=line.icms_origin, ind_final=line.ind_final, + **manual_tax_values, ) rate = ( line.amount_currency / line.balance @@ -521,7 +601,47 @@ def _onchange_icms_fields(self): if self.fiscal_document_line_id: self.fiscal_document_line_id._onchange_icms_fields() - @api.onchange(*FISCAL_TAX_ID_FIELDS) + @api.onchange( + *FISCAL_TAX_ID_FIELDS, + "icms_base_manual", + "icms_value_manual", + "icmsst_base_manual", + "icmsst_value_manual", + "issqn_base_manual", + "issqn_value_manual", + "issqn_wh_base_manual", + "issqn_wh_value_manual", + "icmsst_wh_base_manual", + "icmsst_wh_value_manual", + "ipi_base_manual", + "ipi_value_manual", + "ii_base_manual", + "ii_value_manual", + "cofins_base_manual", + "cofins_value_manual", + "cofinsst_base_manual", + "cofinsst_value_manual", + "cofins_wh_base_manual", + "cofins_wh_value_manual", + "pis_base_manual", + "pis_value_manual", + "pisst_base_manual", + "pisst_value_manual", + "pis_wh_base_manual", + "pis_wh_value_manual", + "csll_base_manual", + "csll_value_manual", + "csll_wh_base_manual", + "csll_wh_value_manual", + "irpj_base_manual", + "irpj_value_manual", + "irpj_wh_base_manual", + "irpj_wh_value_manual", + "inss_base_manual", + "inss_value_manual", + "inss_wh_base_manual", + "inss_wh_value_manual", + ) def _onchange_fiscal_taxes(self): taxes = self.env["l10n_br_fiscal.tax"] for fiscal_tax_field in FISCAL_TAX_ID_FIELDS: @@ -578,3 +698,14 @@ def _check_product_uom_category_id(self): @api.model def _get_total_for_tax_totals(self): return self.move_id.amount_total + + def _prepare_br_manual_tax_dict(self): + manual_tax_dict = {} + suffixes = ["_base_manual", "_value_manual"] + + for tax_prefix in FISCAL_TAX_PREFIXES: + for suffix in suffixes: + attr_name = tax_prefix + suffix + manual_tax_dict[attr_name] = getattr(self, attr_name) + + return manual_tax_dict diff --git a/l10n_br_account/models/account_tax.py b/l10n_br_account/models/account_tax.py index 8a4bc0bc0bd5..a86431f0b66f 100644 --- a/l10n_br_account/models/account_tax.py +++ b/l10n_br_account/models/account_tax.py @@ -47,6 +47,7 @@ def compute_all( icmssn_range=None, icms_origin=None, ind_final=FINAL_CUSTOMER_NO, + **kwargs, ): """Returns all information required to apply taxes (in self + their children in case of a tax goup). @@ -122,6 +123,7 @@ def compute_all( icmssn_range=icmssn_range, icms_origin=icms_origin or product.icms_origin, ind_final=ind_final, + **kwargs, ) taxes_results["amount_tax_included"] = fiscal_taxes_results["amount_included"] @@ -234,6 +236,7 @@ def _compute_taxes_for_single_line( if taxes: # line = base_line["record"] + manual_tax_values = base_line["record"]._prepare_br_manual_tax_dict() taxes_res = taxes.with_context(**base_line["extra_context"]).compute_all( price_unit_after_discount, currency=currency, @@ -261,6 +264,7 @@ def _compute_taxes_for_single_line( icmssn_range=line.icmssn_range_id, icms_origin=line.icms_origin, ind_final=line.ind_final, + **manual_tax_values, ) to_update_vals = { From c9871307249057c6bc05db0ac21a2c5f3d790d9e Mon Sep 17 00:00:00 2001 From: Marcel Savegnago Date: Thu, 4 Sep 2025 14:20:42 -0300 Subject: [PATCH 2/2] [IMP] l10n_br_fiscal: manual values for taxes --- l10n_br_fiscal/models/document_line_mixin.py | 228 ++++++++++++ .../models/document_line_mixin_methods.py | 77 ++++- l10n_br_fiscal/models/tax.py | 109 +++--- .../views/document_line_mixin_view.xml | 324 ++++++++++++++++++ 4 files changed, 686 insertions(+), 52 deletions(-) diff --git a/l10n_br_fiscal/models/document_line_mixin.py b/l10n_br_fiscal/models/document_line_mixin.py index 2e8aebb30094..1e45c7bd165e 100644 --- a/l10n_br_fiscal/models/document_line_mixin.py +++ b/l10n_br_fiscal/models/document_line_mixin.py @@ -449,6 +449,18 @@ def _compute_ind_final(self): readonly=False, ) + issqn_base_manual = fields.Monetary( + string="Manual ISSQN Base", + help="Value of the ISSQN Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + issqn_value_manual = fields.Monetary( + string="Manual ISSQN Value", + help="Value of the ISSQN Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + issqn_percent = fields.Float( string="ISSQN %", compute="_compute_tax_fields", @@ -491,6 +503,18 @@ def _compute_ind_final(self): readonly=False, ) + issqn_wh_base_manual = fields.Monetary( + string="Manual ISSQN RET Base", + help="Value of the ISSQN RET Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + issqn_wh_value_manual = fields.Monetary( + string="Manual ISSQN RET Value", + help="Value of the ISSQN RET Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + issqn_wh_percent = fields.Float( string="ISSQN RET %", compute="_compute_tax_fields", @@ -576,6 +600,18 @@ def _compute_ind_final(self): precompute=True, ) + icms_base_manual = fields.Monetary( + string="Manual ICMS Base", + help="Value of the ICMS Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + icms_value_manual = fields.Monetary( + string="Manual ICMS Value", + help="Value of the ICMS Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + # vBC - Valor da base de cálculo do ICMS icms_base = fields.Monetary( string="ICMS Base", @@ -653,6 +689,18 @@ def _compute_ind_final(self): readonly=False, ) + icmsst_base_manual = fields.Monetary( + string="Manual ICMS ST Base", + help="Value of the ICMS ST Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + icmsst_value_manual = fields.Monetary( + string="Manual ICMS ST Value", + help="Value of the ICMS ST Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + # pMVAST - Percentual da margem de valor Adicionado do ICMS ST icmsst_mva_percent = fields.Float( string="ICMS ST MVA %", @@ -698,6 +746,18 @@ def _compute_ind_final(self): readonly=False, ) + icmsst_wh_base_manual = fields.Monetary( + string="Manual ICMS ST RET Base", + help="Value of the ICMS ST RET Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + icmsst_wh_value_manual = fields.Monetary( + string="Manual ICMS ST RET Value", + help="Value of the ICMS ST RET Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + # vBCSTRet - Valor da base de cálculo do ICMS ST retido icmsst_wh_base = fields.Monetary(string="ICMS ST WH Base") @@ -956,6 +1016,18 @@ def _compute_ind_final(self): readonly=False, ) + ipi_base_manual = fields.Monetary( + string="Manual IPI Base", + help="Value of the IPI Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + ipi_value_manual = fields.Monetary( + string="Manual IPI Value", + help="Value of the IPI Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + ipi_percent = fields.Float( string="IPI %", compute="_compute_tax_fields", @@ -1014,6 +1086,18 @@ def _compute_ind_final(self): readonly=False, ) + ii_base_manual = fields.Monetary( + string="Manual II Base", + help="Value of the II Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + ii_value_manual = fields.Monetary( + string="Manual II Value", + help="Value of the II Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + ii_percent = fields.Float( string="II %", compute="_compute_tax_fields", @@ -1079,6 +1163,18 @@ def _compute_ind_final(self): readonly=False, ) + cofins_base_manual = fields.Monetary( + string="Manual COFINS Base", + help="Value of the COFINS Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + cofins_value_manual = fields.Monetary( + string="Manual COFINS Value", + help="Value of the COFINS Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + cofins_percent = fields.Float( string="COFINS %", compute="_compute_tax_fields", @@ -1155,6 +1251,18 @@ def _compute_ind_final(self): readonly=False, ) + cofinsst_base_manual = fields.Monetary( + string="Manual COFINS ST Base", + help="Value of the COFINS ST Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + cofinsst_value_manual = fields.Monetary( + string="Manual COFINS ST Value", + help="Value of the COFINS ST Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + cofinsst_percent = fields.Float( string="COFINS ST %", compute="_compute_tax_fields", @@ -1206,6 +1314,18 @@ def _compute_ind_final(self): readonly=False, ) + cofins_wh_base_manual = fields.Monetary( + string="Manual COFINS RET Base", + help="Value of the COFINS RET Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + cofins_wh_value_manual = fields.Monetary( + string="Manual COFINS RET Value", + help="Value of the COFINS RET Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + cofins_wh_percent = fields.Float( string="COFINS RET %", compute="_compute_tax_fields", @@ -1274,6 +1394,18 @@ def _compute_ind_final(self): readonly=False, ) + pis_base_manual = fields.Monetary( + string="Manual PIS Base", + help="Value of the PIS Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + pis_value_manual = fields.Monetary( + string="Manual PIS Value", + help="Value of the PIS Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + pis_percent = fields.Float( string="PIS %", compute="_compute_tax_fields", @@ -1350,6 +1482,18 @@ def _compute_ind_final(self): readonly=False, ) + pisst_base_manual = fields.Monetary( + string="Manual PIS ST Base", + help="Value of the PIS ST Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + pisst_value_manual = fields.Monetary( + string="Manual PIS ST Value", + help="Value of the PIS ST Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + pisst_percent = fields.Float( string="PIS ST %", compute="_compute_tax_fields", @@ -1401,6 +1545,18 @@ def _compute_ind_final(self): readonly=False, ) + pis_wh_base_manual = fields.Monetary( + string="Manual PIS RET Base", + help="Value of the PIS RET Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + pis_wh_value_manual = fields.Monetary( + string="Manual PIS RET Value", + help="Value of the PIS RET Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + pis_wh_percent = fields.Float( string="PIS RET %", compute="_compute_tax_fields", @@ -1444,6 +1600,18 @@ def _compute_ind_final(self): readonly=False, ) + csll_base_manual = fields.Monetary( + string="Manual CSLL Base", + help="Value of the CSLL Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + csll_value_manual = fields.Monetary( + string="Manual CSLL Value", + help="Value of the CSLL Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + csll_percent = fields.Float( string="CSLL %", compute="_compute_tax_fields", @@ -1486,6 +1654,18 @@ def _compute_ind_final(self): readonly=False, ) + csll_wh_base_manual = fields.Monetary( + string="Manual CSLL RET Base", + help="Value of the CSLL RET Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + csll_wh_value_manual = fields.Monetary( + string="Manual CSLL RET Value", + help="Value of the CSLL RET Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + csll_wh_percent = fields.Float( string="CSLL RET %", compute="_compute_tax_fields", @@ -1528,6 +1708,18 @@ def _compute_ind_final(self): readonly=False, ) + irpj_base_manual = fields.Monetary( + string="Manual IRPJ Base", + help="Value of the IRPJ Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + irpj_value_manual = fields.Monetary( + string="Manual IRPJ Value", + help="Value of the IRPJ Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + irpj_percent = fields.Float( string="IRPJ %", compute="_compute_tax_fields", @@ -1570,6 +1762,18 @@ def _compute_ind_final(self): readonly=False, ) + irpj_wh_base_manual = fields.Monetary( + string="Manual IRPJ RET Base", + help="Value of the IRPJ RET Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + irpj_wh_value_manual = fields.Monetary( + string="Manual IRPJ RET Value", + help="Value of the IRPJ RET Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + irpj_wh_percent = fields.Float( string="IRPJ RET %", compute="_compute_tax_fields", @@ -1612,6 +1816,18 @@ def _compute_ind_final(self): readonly=False, ) + inss_base_manual = fields.Monetary( + string="Manual INSS Base", + help="Value of the INSS Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + inss_value_manual = fields.Monetary( + string="Manual INSS Value", + help="Value of the INSS Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + inss_percent = fields.Float( string="INSS %", compute="_compute_tax_fields", @@ -1654,6 +1870,18 @@ def _compute_ind_final(self): readonly=False, ) + inss_wh_base_manual = fields.Monetary( + string="Manual INSS RET Base", + help="Value of the INSS RET Base calculated manually. " + "Leave this field blank for automatic calculation.", + ) + + inss_wh_value_manual = fields.Monetary( + string="Manual INSS Value", + help="Value of the INSS Value calculated manually. " + "Leave this field blank for automatic calculation.", + ) + inss_wh_percent = fields.Float( string="INSS RET %", compute="_compute_tax_fields", diff --git a/l10n_br_fiscal/models/document_line_mixin_methods.py b/l10n_br_fiscal/models/document_line_mixin_methods.py index cfad757b7592..deea733c916e 100644 --- a/l10n_br_fiscal/models/document_line_mixin_methods.py +++ b/l10n_br_fiscal/models/document_line_mixin_methods.py @@ -21,6 +21,28 @@ ICMS_ST_BASE_TYPE_DEFAULT, ) +FISCAL_TAX_PREFIXES = [ + "icms", + "icmsst", + "issqn", + "issqn_wh", + "icmsst_wh", + "ipi", + "ii", + "cofins", + "cofinsst", + "cofins_wh", + "pis", + "pisst", + "pis_wh", + "csll", + "csll_wh", + "irpj", + "irpj_wh", + "inss", + "inss_wh", +] + class FiscalDocumentLineMixinMethods(models.AbstractModel): """ @@ -335,7 +357,47 @@ def _update_fiscal_tax_ids(self): ) line.fiscal_tax_ids = fiscal_taxes + taxes - @api.onchange(*FISCAL_TAX_ID_FIELDS) + @api.onchange( + *FISCAL_TAX_ID_FIELDS, + "icms_base_manual", + "icms_value_manual", + "icmsst_base_manual", + "icmsst_value_manual", + "issqn_base_manual", + "issqn_value_manual", + "issqn_wh_base_manual", + "issqn_wh_value_manual", + "icmsst_wh_base_manual", + "icmsst_wh_value_manual", + "ipi_base_manual", + "ipi_value_manual", + "ii_base_manual", + "ii_value_manual", + "cofins_base_manual", + "cofins_value_manual", + "cofinsst_base_manual", + "cofinsst_value_manual", + "cofins_wh_base_manual", + "cofins_wh_value_manual", + "pis_base_manual", + "pis_value_manual", + "pisst_base_manual", + "pisst_value_manual", + "pis_wh_base_manual", + "pis_wh_value_manual", + "csll_base_manual", + "csll_value_manual", + "csll_wh_base_manual", + "csll_wh_value_manual", + "irpj_base_manual", + "irpj_value_manual", + "irpj_wh_base_manual", + "irpj_wh_value_manual", + "inss_base_manual", + "inss_value_manual", + "inss_wh_base_manual", + "inss_wh_value_manual", + ) def _onchange_fiscal_taxes(self): self._update_fiscal_tax_ids() @@ -391,6 +453,7 @@ def _compute_tax_fields(self): } ) if line.fiscal_operation_line_id: + manual_tax_values = line._prepare_br_manual_tax_dict() compute_result = line.fiscal_tax_ids.compute_taxes( company=line.company_id, partner=line._get_fiscal_partner(), @@ -418,6 +481,7 @@ def _compute_tax_fields(self): icms_cst_id=line.icms_cst_id, ind_final=line.ind_final, icms_relief_id=line.icms_relief_id, + **manual_tax_values, ) to_update.update(line._prepare_tax_fields(compute_result)) else: @@ -458,6 +522,17 @@ def _prepare_tax_fields(self, compute_result): tax_values.update(prepared_fields) return tax_values + def _prepare_br_manual_tax_dict(self): + manual_tax_dict = {} + suffixes = ["_base_manual", "_value_manual"] + + for tax_prefix in FISCAL_TAX_PREFIXES: + for suffix in suffixes: + attr_name = tax_prefix + suffix + manual_tax_dict[attr_name] = getattr(self, attr_name) + + return manual_tax_dict + @api.depends( "product_id", "fiscal_operation_id", diff --git a/l10n_br_fiscal/models/tax.py b/l10n_br_fiscal/models/tax.py index 6176a00b8068..fc2d3fdcb5a2 100644 --- a/l10n_br_fiscal/models/tax.py +++ b/l10n_br_fiscal/models/tax.py @@ -2,7 +2,6 @@ # License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html from odoo import api, fields, models -from odoo.tools import float_is_zero from ..constants.fiscal import ( CFOP_DESTINATION_EXPORT, @@ -242,6 +241,8 @@ def cst_from_tax(self, fiscal_operation_type=FISCAL_OUT): @api.model def _compute_tax_base(self, tax, tax_dict, **kwargs): + """Calculates the base, percentage, and tax amount.""" + company = kwargs.get("company", tax.env.company) currency = kwargs.get("currency", company.currency_id) fiscal_price = kwargs.get("fiscal_price", 0.00) @@ -252,53 +253,55 @@ def _compute_tax_base(self, tax, tax_dict, **kwargs): freight_value = kwargs.get("freight_value", 0.00) other_value = kwargs.get("other_value", 0.00) - if tax.tax_group_id.base_with_additional_values: - tax_dict["add_to_base"] += sum( - [freight_value, insurance_value, other_value] - ) - tax_dict["remove_from_base"] += sum([discount_value]) - - base = 0.00 - if not tax_dict.get("percent_amount") and tax.percent_amount: tax_dict["percent_amount"] = tax.percent_amount if not tax_dict.get("value_amount") and tax.value_amount: tax_dict["value_amount"] = tax.value_amount - if tax_dict["base_type"] == "percent": - # Compute initial Tax Base for base_type Percent - base = currency.round(fiscal_price * fiscal_quantity) - - if tax_dict["base_type"] == "quantity": - # Compute initial Tax Base for base_type Quantity - base = fiscal_quantity - - if tax_dict["base_type"] == "fixed": - # Compute initial Tax Base - base = currency.round(tax_dict["value_amount"] * fiscal_quantity) + if tax_dict.get("base_manual"): + base_amount = tax_dict["base_manual"] + else: + # calculate base + if tax.tax_group_id.base_with_additional_values: + tax_dict["add_to_base"] += sum( + [freight_value, insurance_value, other_value] + ) + tax_dict["remove_from_base"] += sum([discount_value]) - # Update Base Value - base_amount = currency.round( - (base + tax_dict["add_to_base"]) - tax_dict["remove_from_base"] - ) + if tax_dict["base_type"] == "percent": + # Compute initial Tax Base for base_type Percent + base = currency.round(fiscal_price * fiscal_quantity) - # Compute Tax Base Reduction - base_reduction = base_amount * abs(tax.percent_reduction / 100) + if tax_dict["base_type"] == "quantity": + # Compute initial Tax Base for base_type Quantity + base = fiscal_quantity - # Compute Tax Base Amount - if compute_reduction: - base_amount = currency.round(base_amount - base_reduction) + if tax_dict["base_type"] == "fixed": + # Compute initial Tax Base + base = currency.round(tax_dict["value_amount"] * fiscal_quantity) - if tax_dict.get("icmsst_mva_percent"): + # Update Base Value base_amount = currency.round( - base_amount * (1 + (tax_dict["icmsst_mva_percent"] / 100)) + (base + tax_dict["add_to_base"]) - tax_dict["remove_from_base"] ) - if tax_dict.get("compute_with_tax_value"): - base_amount = currency.round( - base_amount / (1 - (tax_dict["percent_amount"] / 100)) - ) + # Compute Tax Base Reduction + base_reduction = base_amount * abs(tax.percent_reduction / 100) + + # Compute Tax Base Amount + if compute_reduction: + base_amount = currency.round(base_amount - base_reduction) + + if tax_dict.get("icmsst_mva_percent"): + base_amount = currency.round( + base_amount * (1 + (tax_dict["icmsst_mva_percent"] / 100)) + ) + + if tax_dict.get("compute_with_tax_value"): + base_amount = currency.round( + base_amount / (1 - (tax_dict["percent_amount"] / 100)) + ) if ( not tax.percent_amount @@ -322,6 +325,11 @@ def _compute_tax(self, tax, taxes_dict, **kwargs): fiscal_operation_type = operation_line.fiscal_operation_type or FISCAL_OUT tax_dict = taxes_dict.get(tax.tax_domain) + + # extract manual values + base_manual = kwargs.get(f"{tax.tax_domain}_base_manual") + tax_value_manual = kwargs.get(f"{tax.tax_domain}_value_manual") + tax_dict.update( { "name": tax.name, @@ -333,6 +341,8 @@ def _compute_tax(self, tax, taxes_dict, **kwargs): "percent_reduction": tax.percent_reduction, "percent_amount": tax_dict.get("percent_amount", tax.percent_amount), "cst_id": tax.cst_from_tax(fiscal_operation_type), + "base_manual": base_manual, + "tax_value_manual": tax_value_manual, } ) @@ -341,21 +351,22 @@ def _compute_tax(self, tax, taxes_dict, **kwargs): tax_dict_icms = taxes_dict.get("icms", {}) tax_dict["remove_from_base"] += tax_dict_icms.get("tax_value", 0.00) - # TODO futuramente levar em consideração outros tipos de base de calculo - if float_is_zero(tax_dict.get("base", 0.00), currency.decimal_places): - tax_dict = self._compute_tax_base(tax, tax_dict, **kwargs) + tax_dict = self._compute_tax_base(tax, tax_dict, **kwargs) base_amount = tax_dict.get("base", 0.00) - if tax_dict["base_type"] == "percent": - tax_dict["tax_value"] = currency.round( - base_amount * (tax_dict["percent_amount"] / 100) - ) + if tax_dict.get("tax_value_manual"): + tax_dict["tax_value"] = tax_dict["tax_value_manual"] + else: + if tax_dict["base_type"] == "percent": + tax_dict["tax_value"] = currency.round( + base_amount * (tax_dict["percent_amount"] / 100) + ) - if tax_dict["base_type"] in ("quantity", "fixed"): - tax_dict["tax_value"] = currency.round( - base_amount * tax_dict["value_amount"] - ) + if tax_dict["base_type"] in ("quantity", "fixed"): + tax_dict["tax_value"] = currency.round( + base_amount * tax_dict["value_amount"] + ) return tax_dict @@ -599,12 +610,8 @@ def _compute_icmsst(self, tax, taxes_dict, **kwargs): if taxes_dict.get(tax.tax_domain): taxes_dict[tax.tax_domain]["icmsst_mva_percent"] = tax.icmsst_mva_percent - taxes_dict[tax.tax_domain].update( - self._compute_tax_base(tax, taxes_dict.get(tax.tax_domain), **kwargs) - ) - tax_dict = self._compute_tax(tax, taxes_dict, **kwargs) - if tax_dict.get("icmsst_mva_percent"): + if tax_dict.get("icmsst_mva_percent") and not tax_dict.get("tax_value_manual"): tax_dict["tax_value"] -= taxes_dict.get("icms", {}).get("tax_value", 0.0) return tax_dict diff --git a/l10n_br_fiscal/views/document_line_mixin_view.xml b/l10n_br_fiscal/views/document_line_mixin_view.xml index e28c478401b8..5ce54892d3cd 100644 --- a/l10n_br_fiscal/views/document_line_mixin_view.xml +++ b/l10n_br_fiscal/views/document_line_mixin_view.xml @@ -106,6 +106,23 @@ attrs="{'readonly': [('issqn_tax_id', '!=', False)]}" /> + +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
@@ -315,6 +367,23 @@ force_save="1" attrs="{'readonly': [('icms_tax_id', '!=', False)], 'invisible': [('icms_cst_code', 'in', ('60', '500'))]}" /> + +
Keep empty for + automatic calculation
+ + +
+ +
Keep empty for + automatic calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
@@ -611,6 +731,23 @@ attrs="{'readonly': [('pis_tax_id', '!=', False)]}" /> + +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
@@ -753,6 +924,23 @@ attrs="{'readonly': [('cofins_tax_id', '!=', False)]}" /> + +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +
+ +
Keep empty for automatic + calculation
+ + +