diff --git a/l10n_br_account/models/account_move.py b/l10n_br_account/models/account_move.py index b294fd438d6d..48829b483bfe 100644 --- a/l10n_br_account/models/account_move.py +++ b/l10n_br_account/models/account_move.py @@ -282,9 +282,11 @@ def _get_view(self, view_id=None, view_type="form", **options): "line_ids.full_reconcile_id", "state", "ind_final", + "fiscal_operation_id", ) def _compute_amount(self): for move in self.filtered(lambda m: m.fiscal_operation_id): + move._compute_fiscal_amount() for line in move.line_ids: if ( move.is_invoice(include_receipts=True) @@ -300,6 +302,7 @@ def _compute_amount(self): sign = 1 inv_line_ids = move.line_ids.filtered( lambda line: line.display_type == "product" + and (not line.cfop_id or line.cfop_id.finance_move) ) move.amount_untaxed = sum(inv_line_ids.mapped("amount_untaxed")) move.amount_tax = sum(inv_line_ids.mapped("amount_tax")) @@ -321,9 +324,14 @@ def _compute_needed_terms(self): """ Similar to the _compute_needed_terms super method in the account module, but ensure moves are balanced in Brazil when there is a fiscal_operation_id. - WARNING: it seems we might not be able to call the super method here.... """ - for invoice in self: + res = None + invoices_with_fiscal_op = self.filtered(lambda inv: inv.fiscal_operation_id) + invoices_without_fiscal_op = self - invoices_with_fiscal_op + if invoices_without_fiscal_op: + res = super(AccountMove, invoices_without_fiscal_op)._compute_needed_terms() + + for invoice in invoices_with_fiscal_op: is_draft = invoice.id != invoice._origin.id invoice.needed_terms = {} invoice.needed_terms_dirty = True @@ -338,31 +346,18 @@ def _compute_needed_terms(self): pass else: untaxed_amount_currency += line.price_subtotal - for tax_result in (line.compute_all_tax or {}).values(): - tax_amount_currency += -sign * tax_result.get( - "amount_currency", 0.0 - ) + for tax_result in (line.compute_all_tax or {}).values(): + tax_amount_currency += -sign * tax_result.get( + "amount_currency", 0.0 + ) untaxed_amount = untaxed_amount_currency tax_amount = tax_amount_currency else: - tax_amount_currency = invoice.amount_tax * sign - tax_amount = invoice.amount_tax_signed - if invoice.fiscal_operation_id: - if invoice.fiscal_operation_id.deductible_taxes: - amount_currency = ( - invoice.amount_total - + invoice.amount_tax_withholding - ) - else: - amount_currency = ( - invoice.amount_total - invoice.amount_ipi_value - ) * sign - untaxed_amount_currency = amount_currency * sign - untaxed_amount = amount_currency * sign - - else: - untaxed_amount_currency = invoice.amount_untaxed * sign - untaxed_amount = invoice.amount_untaxed_signed + tax_amount_currency = tax_amount = 0.0 + # TODO forçando o compute + # invoice._compute_amount() + untaxed_amount_currency = invoice.amount_financial_total * sign + untaxed_amount = invoice.amount_financial_total * sign invoice_payment_terms = ( invoice.invoice_payment_term_id._compute_terms( date_ref=invoice.invoice_date @@ -418,6 +413,7 @@ def _compute_needed_terms(self): "balance": invoice.amount_total_signed, "amount_currency": invoice.amount_total_in_currency_signed, } + return res @contextmanager def _sync_dynamic_lines(self, container): diff --git a/l10n_br_account/models/account_move_line.py b/l10n_br_account/models/account_move_line.py index 315b2f21dbf6..0140042646d3 100644 --- a/l10n_br_account/models/account_move_line.py +++ b/l10n_br_account/models/account_move_line.py @@ -301,6 +301,20 @@ def changed(fname): else: # BRAZIL CASE: if line.cfop_id and not line.cfop_id.finance_move: unsigned_amount_currency = 0 + if not line.move_id.fiscal_operation_id.deductible_taxes: + # Quando não há financeiro, mas há imposto, e não há + # dedutíveis, é necessário registrar a contrapartida dos + # impostos para equilibrar o balanço. Na versão 14, essa + # diferença era automaticamente alocada às contas dos + # termos de pagamento. + # TODO: + # o correto mesmo seria não lançar os impostos nesse caso, + # resolver depois. + unsigned_amount_currency = -( + line.amount_tax_included + + line.amount_tax_not_included + - line.amount_tax_withholding + ) else: if line.move_id.fiscal_operation_id.deductible_taxes: unsigned_amount_currency = ( @@ -312,12 +326,10 @@ def changed(fname): ) unsigned_amount_currency = line.currency_id.round( amount_total - - ( - line.amount_tax_included - - line.amount_tax_withholding - ) + - line.amount_tax_included - line.amount_tax_not_included - - line.icms_relief_value + if line.tax_ids + else amount_total ) amount_currency = unsigned_amount_currency * line.move_id.direction_sign if line.amount_currency != amount_currency or line not in before: @@ -325,6 +337,19 @@ def changed(fname): if line.currency_id == line.company_id.currency_id: line.balance = amount_currency + # Os totais nas linhas foram atualizadas, mas o total da fatura + # não foi recalculado automaticamente, já que o método compute_amount + # não foi acionado após as alterações nas linhas. + # Por esse motivo, estou adicionando manualmente os campos no + # add_to_compute do account_move. + # Questão: Por que o compute_amount não foi acionado automaticamente? + # Isso ocorre apenas quando os valores são diretamente informados + # no create? Realizar um teste isolado para confirmar esse + # comportamento. + move_id = line.move_id + self.env.add_to_compute(move_id._fields["amount_total"], move_id) + self.env.add_to_compute(move_id._fields["amount_untaxed"], move_id) + after = existing() for line in after: if ( @@ -394,7 +419,6 @@ def _compute_totals(self): line.price_subtotal = taxes_res["total_excluded"] line.price_total = taxes_res["total_included"] - line._compute_balance() line.price_total += ( line.insurance_value @@ -521,19 +545,33 @@ def _onchange_fiscal_document_line_id(self): # override the default product uom (set by the onchange): self.product_uom_id = self.fiscal_document_line_id.uom_id.id - @api.onchange("fiscal_tax_ids") - def _onchange_fiscal_tax_ids(self): - """Ao alterar o campo fiscal_tax_ids que contém os impostos fiscais, - são atualizados os impostos contábeis relacionados""" - result = super()._onchange_fiscal_tax_ids() + @api.depends("product_id", "product_uom_id", "fiscal_tax_ids") + def _compute_tax_ids(self): + # Adding 'fiscal_tax_ids' as a dependency to ensure that the taxes + # are recalculated when this field changes. + return super()._compute_tax_ids() + + def _get_computed_taxes(self): + """ + Override the native method to load taxes from the fiscal module. + """ + self.ensure_one() - # Atualiza os impostos contábeis relacionados aos impostos fiscais - user_type = "sale" - if self.move_id.move_type in ("in_invoice", "in_refund"): + # If no fiscal operation is defined, fallback to the default implementation. + if not self.fiscal_operation_id: + return super()._get_computed_taxes() + + # Determine the user type based on the document type. + user_type = None + if self.move_id.is_sale_document(include_receipts=True): + user_type = "sale" + elif self.move_id.is_purchase_document(include_receipts=True): user_type = "purchase" - self.tax_ids = self.fiscal_tax_ids.account_taxes( - user_type=user_type, fiscal_operation=self.fiscal_operation_id - ) + # Retrieve taxes based on user type and fiscal operation. + if user_type: + tax_ids = self.fiscal_tax_ids.account_taxes( + user_type=user_type, fiscal_operation=self.fiscal_operation_id + ) - return result + return tax_ids diff --git a/l10n_br_account/tests/test_account_move_lc.py b/l10n_br_account/tests/test_account_move_lc.py index af967744e948..213b8a1bd90f 100644 --- a/l10n_br_account/tests/test_account_move_lc.py +++ b/l10n_br_account/tests/test_account_move_lc.py @@ -480,7 +480,7 @@ def test_venda_with_icms_reduction_with_relief(self): # Testando com Alivio do ICMS self.move_out_venda_with_icms_reduction.invoice_line_ids[0].icms_relief_id = 1 self.move_out_venda_with_icms_reduction.invoice_line_ids._onchange_fiscal_taxes() - self.move_out_venda_with_icms_reduction.line_ids._compute_amounts() + self.move_out_venda_with_icms_reduction.line_ids._compute_fiscal_amounts() product_line_vals_1 = { "name": self.product_a.display_name, @@ -666,8 +666,8 @@ def test_simples_remessa(self): "price_total": 1050.0, "tax_line_id": False, "currency_id": self.company_data["currency"].id, - "amount_currency": 0.0, - "debit": 0.0, + "amount_currency": 206.5, + "debit": 206.5, "credit": 0.0, "date_maturity": False, } @@ -775,6 +775,8 @@ def test_simples_remessa(self): "date_maturity": False, } + # Remessa não gera financeiro, as linhas das condições de pagamento + # devem estar zeradas! term_line_vals_1 = { "name": "", "product_id": False, @@ -789,8 +791,8 @@ def test_simples_remessa(self): "tax_ids": [], "tax_line_id": False, "currency_id": self.company_data["currency"].id, - "amount_currency": 206.5, - "debit": 206.5, + "amount_currency": 0, + "debit": 0, "credit": 0.0, "date_maturity": fields.Date.from_string("2019-01-01"), } @@ -803,9 +805,9 @@ def test_simples_remessa(self): "fiscal_position_id": False, "payment_reference": "", "invoice_payment_term_id": self.pay_terms_a.id, - "amount_untaxed": 1000, - "amount_tax": 50, - "amount_total": 206.5, + "amount_untaxed": 0.0, + "amount_tax": 0.0, + "amount_total": 0.0, } self.assertInvoiceValues( @@ -1271,8 +1273,8 @@ def test_simples_remessa_tax_withholding(self): "price_total": 1050.0, "tax_line_id": False, "currency_id": self.company_data["currency"].id, - "amount_currency": 0.0, - "debit": 0.0, + "amount_currency": 133.5, + "debit": 133.5, "credit": 0.0, "date_maturity": False, } @@ -1390,8 +1392,8 @@ def test_simples_remessa_tax_withholding(self): "tax_ids": [], "tax_line_id": False, "currency_id": self.company_data["currency"].id, - "amount_currency": 133.5, - "debit": 133.5, + "amount_currency": 0.0, + "debit": 0.0, "credit": 0.0, "date_maturity": fields.Date.from_string("2019-01-01"), } @@ -1404,9 +1406,9 @@ def test_simples_remessa_tax_withholding(self): "fiscal_position_id": False, "payment_reference": "", "invoice_payment_term_id": self.pay_terms_a.id, - "amount_untaxed": 1000.0, # FIXME is this correct for a simples remessa?? - "amount_tax": 50.0, - "amount_total": 133.5, + "amount_untaxed": 0.0, + "amount_tax": 0.0, + "amount_total": 0.0, } self.assertInvoiceValues( diff --git a/l10n_br_account/tests/test_invoice_refund.py b/l10n_br_account/tests/test_invoice_refund.py index 896681baf6b1..0e8b69f66c32 100644 --- a/l10n_br_account/tests/test_invoice_refund.py +++ b/l10n_br_account/tests/test_invoice_refund.py @@ -109,18 +109,19 @@ def test_refund(self): with self.assertRaises(UserError): move_reversal.reverse_moves() - invoice["fiscal_operation_id"] = (self.env.ref("l10n_br_fiscal.fo_venda").id,) + invoice.fiscal_operation_id = self.env.ref("l10n_br_fiscal.fo_venda") with self.assertRaises(UserError): move_reversal.reverse_moves() - for line_id in invoice.invoice_line_ids: - line_id["fiscal_operation_id"] = ( - self.env.ref("l10n_br_fiscal.fo_venda").id, - ) - line_id["fiscal_operation_line_id"] = self.env.ref( - "l10n_br_fiscal.fo_venda_venda" - ).id + invoice.invoice_line_ids.write( + { + "fiscal_operation_id": self.env.ref("l10n_br_fiscal.fo_venda").id, + "fiscal_operation_line_id": ( + self.env.ref("l10n_br_fiscal.fo_venda_venda").id, + ), + } + ) reversal = move_reversal.reverse_moves() reverse_move = self.env["account.move"].browse(reversal["res_id"]) @@ -137,15 +138,15 @@ def test_refund_force_fiscal_operation(self): reverse_vals = self.reverse_vals invoice = self.invoice - invoice["fiscal_operation_id"] = (self.env.ref("l10n_br_fiscal.fo_venda").id,) - - for line_id in invoice.invoice_line_ids: - line_id["fiscal_operation_id"] = ( - self.env.ref("l10n_br_fiscal.fo_venda").id, - ) - line_id["fiscal_operation_line_id"] = self.env.ref( - "l10n_br_fiscal.fo_venda_venda" - ).id + invoice.fiscal_operation_id = self.env.ref("l10n_br_fiscal.fo_venda") + invoice.invoice_line_ids.write( + { + "fiscal_operation_id": self.env.ref("l10n_br_fiscal.fo_venda").id, + "fiscal_operation_line_id": self.env.ref( + "l10n_br_fiscal.fo_venda_venda" + ).id, + } + ) invoice.action_post() self.assertEqual( diff --git a/l10n_br_fiscal/models/document.py b/l10n_br_fiscal/models/document.py index 18507b74eca4..6c0bd1102337 100644 --- a/l10n_br_fiscal/models/document.py +++ b/l10n_br_fiscal/models/document.py @@ -337,6 +337,7 @@ def _compute_name(self): r.name = r._compute_document_name() @api.depends( + "fiscal_line_ids", "fiscal_line_ids.estimate_tax", "fiscal_line_ids.price_gross", "fiscal_line_ids.amount_untaxed", @@ -350,8 +351,8 @@ def _compute_name(self): "fiscal_line_ids.amount_tax_not_included", "fiscal_line_ids.amount_tax_withholding", ) - def _compute_amount(self): - return super()._compute_amount() + def _compute_fiscal_amount(self): + return super()._compute_fiscal_amount() @api.model_create_multi def create(self, vals_list): diff --git a/l10n_br_fiscal/models/document_line_mixin.py b/l10n_br_fiscal/models/document_line_mixin.py index 7e7eaa7b2833..6c9e7a24d8cc 100644 --- a/l10n_br_fiscal/models/document_line_mixin.py +++ b/l10n_br_fiscal/models/document_line_mixin.py @@ -192,7 +192,7 @@ def _operation_domain(self): ) amount_fiscal = fields.Monetary( - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) price_gross = fields.Monetary( @@ -201,38 +201,38 @@ def _operation_domain(self): "Total value of products or services (quantity x unit price)" "before any discounts." ), - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) amount_untaxed = fields.Monetary( - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) amount_tax = fields.Monetary( - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) amount_taxed = fields.Monetary( - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) amount_total = fields.Monetary( - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) financial_total = fields.Monetary( string="Amount Financial", - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) financial_total_gross = fields.Monetary( string="Financial Gross Amount", help="Total amount before any discounts are applied.", - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) financial_discount_value = fields.Monetary( - compute="_compute_amounts", + compute="_compute_fiscal_amounts", ) amount_tax_included = fields.Monetary() diff --git a/l10n_br_fiscal/models/document_line_mixin_methods.py b/l10n_br_fiscal/models/document_line_mixin_methods.py index 0442dbd36b41..1c19392f71b9 100644 --- a/l10n_br_fiscal/models/document_line_mixin_methods.py +++ b/l10n_br_fiscal/models/document_line_mixin_methods.py @@ -127,27 +127,29 @@ def _get_view(self, view_id=None, view_type="form", **options): "company_id", "price_unit", "quantity", + "icms_relief_id", + "fiscal_operation_line_id", ) - def _compute_amounts(self): + def _compute_fiscal_amounts(self): for record in self: round_curr = record.currency_id or self.env.ref("base.BRL") # Total value of products or services record.price_gross = round_curr.round(record.price_unit * record.quantity) - - record.amount_untaxed = record.price_gross - record.discount_value - record.amount_fiscal = record.price_gross - record.discount_value - record.amount_tax = record.amount_tax_not_included add_to_amount = sum(record[a] for a in record._add_fields_to_amount()) rm_to_amount = sum(record[r] for r in record._rm_fields_to_amount()) + record.amount_untaxed = ( + record.price_gross + - record.discount_value + + add_to_amount + - rm_to_amount + ) # Valor do documento (NF) - record.amount_total = ( - record.amount_untaxed + record.amount_tax + add_to_amount - rm_to_amount - ) + record.amount_total = record.amount_untaxed + record.amount_tax # Valor Liquido (TOTAL + IMPOSTOS - RETENÇÕES) record.amount_taxed = record.amount_total - record.amount_tax_withholding diff --git a/l10n_br_fiscal/models/document_mixin_fields.py b/l10n_br_fiscal/models/document_mixin_fields.py index 3f846c19194d..aa2e2dcfea63 100644 --- a/l10n_br_fiscal/models/document_mixin_fields.py +++ b/l10n_br_fiscal/models/document_mixin_fields.py @@ -99,337 +99,337 @@ def _operation_domain(self): ) amount_price_gross = fields.Monetary( - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, string="Amount Gross", help="Amount without discount.", ) amount_untaxed = fields.Monetary( - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icms_base = fields.Monetary( string="ICMS Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icms_value = fields.Monetary( string="ICMS Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icmsst_base = fields.Monetary( string="ICMS ST Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icmsst_value = fields.Monetary( string="ICMS ST Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icmssn_credit_value = fields.Monetary( string="ICMSSN Credit Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icmsfcp_base = fields.Monetary( string="ICMS FCP Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icmsfcp_value = fields.Monetary( string="ICMS FCP Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icmsfcpst_value = fields.Monetary( string="ICMS FCP ST Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icms_destination_value = fields.Monetary( string="ICMS Destination Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_icms_origin_value = fields.Monetary( string="ICMS Origin Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_ipi_base = fields.Monetary( string="IPI Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_ipi_value = fields.Monetary( string="IPI Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_ii_base = fields.Monetary( string="II Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_ii_value = fields.Monetary( string="II Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_ii_customhouse_charges = fields.Monetary( string="Customhouse Charges", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_pis_base = fields.Monetary( string="PIS Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_pis_value = fields.Monetary( string="PIS Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_pisst_base = fields.Monetary( string="PIS ST Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_pisst_value = fields.Monetary( string="PIS ST Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_pis_wh_base = fields.Monetary( string="PIS Ret Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_pis_wh_value = fields.Monetary( string="PIS Ret Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_cofins_base = fields.Monetary( string="COFINS Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_cofins_value = fields.Monetary( string="COFINS Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_cofinsst_base = fields.Monetary( string="COFINS ST Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_cofinsst_value = fields.Monetary( string="COFINS ST Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_cofins_wh_base = fields.Monetary( string="COFINS Ret Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_cofins_wh_value = fields.Monetary( string="COFINS Ret Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_issqn_base = fields.Monetary( string="ISSQN Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_issqn_value = fields.Monetary( string="ISSQN Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_issqn_wh_base = fields.Monetary( string="ISSQN Ret Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_issqn_wh_value = fields.Monetary( string="ISSQN Ret Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_csll_base = fields.Monetary( string="CSLL Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_csll_value = fields.Monetary( string="CSLL Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_csll_wh_base = fields.Monetary( string="CSLL Ret Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_csll_wh_value = fields.Monetary( string="CSLL Ret Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_irpj_base = fields.Monetary( string="IRPJ Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_irpj_value = fields.Monetary( string="IRPJ Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_irpj_wh_base = fields.Monetary( string="IRPJ Ret Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_irpj_wh_value = fields.Monetary( string="IRPJ Ret Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_inss_base = fields.Monetary( string="INSS Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_inss_value = fields.Monetary( string="INSS Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_inss_wh_base = fields.Monetary( string="INSS Ret Base", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_inss_wh_value = fields.Monetary( string="INSS Ret Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_estimate_tax = fields.Monetary( - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_tax = fields.Monetary( - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_total = fields.Monetary( - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_tax_withholding = fields.Monetary( string="Tax Withholding", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_financial_total = fields.Monetary( string="Amount Financial", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_discount_value = fields.Monetary( string="Amount Discount", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_financial_total_gross = fields.Monetary( string="Amount Financial Gross", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_financial_discount_value = fields.Monetary( string="Financial Discount Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, ) amount_insurance_value = fields.Monetary( string="Insurance Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, inverse="_inverse_amount_insurance", ) amount_other_value = fields.Monetary( string="Other Costs", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, inverse="_inverse_amount_other", ) amount_freight_value = fields.Monetary( string="Freight Value", - compute="_compute_amount", + compute="_compute_fiscal_amount", store=True, inverse="_inverse_amount_freight", ) diff --git a/l10n_br_fiscal/models/document_mixin_methods.py b/l10n_br_fiscal/models/document_mixin_methods.py index eec037c42543..eeb93f9a2e2e 100644 --- a/l10n_br_fiscal/models/document_mixin_methods.py +++ b/l10n_br_fiscal/models/document_mixin_methods.py @@ -40,7 +40,7 @@ def _get_amount_fields(self): amount_fields = [f for f in fields if f.startswith("amount_")] return amount_fields - def _compute_amount(self): + def _compute_fiscal_amount(self): fields = self._get_amount_fields() for doc in self: values = {key: 0.0 for key in fields} diff --git a/l10n_br_fiscal/models/tax.py b/l10n_br_fiscal/models/tax.py index 1a583402aa80..773d7d67ef06 100644 --- a/l10n_br_fiscal/models/tax.py +++ b/l10n_br_fiscal/models/tax.py @@ -699,19 +699,15 @@ def compute_taxes(self, **kwargs): except AttributeError: taxes[tax.tax_domain].update(tax._compute_tax(tax, taxes, **kwargs)) - if taxes[tax.tax_domain]["tax_include"]: - result_amounts["amount_included"] += taxes[tax.tax_domain].get( - "tax_value", 0.00 - ) + tax_domain = taxes[tax.tax_domain] + tax_value = tax_domain.get("tax_value", 0.00) + if tax_domain["tax_withholding"]: + result_amounts["amount_withholding"] += tax_value else: - result_amounts["amount_not_included"] += taxes[tax.tax_domain].get( - "tax_value", 0.00 - ) - - if taxes[tax.tax_domain]["tax_withholding"]: - result_amounts["amount_withholding"] += taxes[tax.tax_domain].get( - "tax_value", 0.00 - ) + if tax_domain["tax_include"]: + result_amounts["amount_included"] += tax_value + else: + result_amounts["amount_not_included"] += tax_value # Estimate taxes result_amounts["estimate_tax"] = self._compute_estimate_taxes(**kwargs) diff --git a/l10n_br_nfe/tests/test_nfe_serialize.py b/l10n_br_nfe/tests/test_nfe_serialize.py index 58ce87f2c56f..165674b23a12 100644 --- a/l10n_br_nfe/tests/test_nfe_serialize.py +++ b/l10n_br_nfe/tests/test_nfe_serialize.py @@ -38,7 +38,7 @@ def prepare_test_nfe(self, nfe): line._onchange_fiscal_operation_id() line._onchange_fiscal_operation_line_id() - nfe._compute_amount() + nfe._compute_fiscal_amount() nfe.nfe40_detPag = [ (5, 0, 0), ( diff --git a/l10n_br_purchase/models/purchase_order.py b/l10n_br_purchase/models/purchase_order.py index 54c1a4ada566..d38f35651b59 100644 --- a/l10n_br_purchase/models/purchase_order.py +++ b/l10n_br_purchase/models/purchase_order.py @@ -80,12 +80,12 @@ def _get_amount_lines(self): return self.mapped("order_line") @api.depends("order_line") - def _compute_amount(self): - return super()._compute_amount() + def _compute_fiscal_amount(self): + return super()._compute_fiscal_amount() @api.depends("order_line.price_total") def _amount_all(self): - self._compute_amount() + self._compute_fiscal_amount() def _prepare_invoice(self): self.ensure_one() diff --git a/l10n_br_purchase/models/purchase_order_line.py b/l10n_br_purchase/models/purchase_order_line.py index e63fe87caba5..7a2acbdaf5d7 100644 --- a/l10n_br_purchase/models/purchase_order_line.py +++ b/l10n_br_purchase/models/purchase_order_line.py @@ -98,13 +98,12 @@ def _compute_amount(self): # Update taxes fields line._update_fiscal_taxes() # Call mixin compute method - line._compute_amounts() + line._compute_fiscal_amounts() # Update record line.update( { "price_subtotal": line.amount_untaxed, "price_tax": line.amount_tax, - "price_gross": line.amount_untaxed + line.discount_value, "price_total": line.amount_total, } ) diff --git a/l10n_br_sale/models/sale_order.py b/l10n_br_sale/models/sale_order.py index 6026eabb62a8..1006f43634dc 100644 --- a/l10n_br_sale/models/sale_order.py +++ b/l10n_br_sale/models/sale_order.py @@ -101,7 +101,7 @@ def _get_amount_lines(self): def _compute_amounts(self): """Compute the total amounts of the SO.""" for order in self: - order._compute_amount() + order._compute_fiscal_amount() # TODO v16 override _compute_tax_totals ? diff --git a/l10n_br_sale/models/sale_order_line.py b/l10n_br_sale/models/sale_order_line.py index 532399cf81bc..e7e0ae088922 100644 --- a/l10n_br_sale/models/sale_order_line.py +++ b/l10n_br_sale/models/sale_order_line.py @@ -184,7 +184,7 @@ def _compute_amount(self): # Update taxes fields line._update_fiscal_taxes() # Call mixin compute method - line._compute_amounts() + line._compute_fiscal_amounts() # Update record line.update( { @@ -304,3 +304,21 @@ def _get_fiscal_partner(self): partner = self.order_id.partner_invoice_id return partner + + @api.depends("product_id", "company_id", "fiscal_tax_ids") + def _compute_tax_id(self): + """Compute taxes based on fiscal operation or fallback to default behavior.""" + lines_with_fiscal_operation = self.filtered( + lambda line: line.fiscal_operation_line_id + ) + lines_without_fiscal_operation = self - lines_with_fiscal_operation + + for line in lines_with_fiscal_operation: + line.tax_id = line.fiscal_tax_ids.account_taxes( + user_type="sale", fiscal_operation=line.fiscal_operation_id + ) + + if lines_without_fiscal_operation: + return super( + SaleOrderLine, lines_without_fiscal_operation + )._compute_tax_id() diff --git a/l10n_br_sale_stock/tests/test_sale_stock.py b/l10n_br_sale_stock/tests/test_sale_stock.py index 78ad6aa9b89b..d1173cbdf37b 100644 --- a/l10n_br_sale_stock/tests/test_sale_stock.py +++ b/l10n_br_sale_stock/tests/test_sale_stock.py @@ -217,6 +217,12 @@ def test_picking_sale_order_product_and_service(self): # a copia entre os objetos é testada tanto no stock.move acima # quanto na account.move.line abaixo "uom_id", + # O campo 'display_type' difere entre 'sale.order.line' e + # 'account.move.line' para produtos: é False em 'sale.order.line' e + # "product" em 'account.move.line' + "display_type", + "sequence", + "analytic_precision", # verificar se tem importancia # Ao chamar o _onchange_product_id_fiscal no stock.move o # partner_id usado no mapeamento é o do objeto, nesse teste # 'Akretion Aluminio - SP' por ser o Endereço de Entrega @@ -245,6 +251,14 @@ def test_picking_sale_order_product_and_service(self): "Field %s failed to transfer from " "sale.order.line to account.move.line" % field, ) + # Assert específico para 'display_type' + if sale_order_line.display_type is False: + self.assertEqual( + invoice_lines.display_type, + "product", + "Esperado 'display_type' como 'product' em account.move.line quando" + "é False em sale.order.line", + ) for inv_line in invoice_lines: if inv_line.product_id == sale_order_line.product_id: @@ -340,7 +354,6 @@ def test_ungrouping_pickings_partner_shipping_different(self): picking and 3 moves per picking, the 3 has the same Partner to Invoice but one has Partner to Shipping so shouldn't be grouping. """ - sale_order_1 = self.env.ref("l10n_br_sale_stock.main_so_l10n_br_sale_stock_1") sale_order_1.action_confirm() picking = sale_order_1.picking_ids diff --git a/l10n_br_stock_account/models/stock_picking.py b/l10n_br_stock_account/models/stock_picking.py index 7f7fb75eb4a8..9c195889ab12 100644 --- a/l10n_br_stock_account/models/stock_picking.py +++ b/l10n_br_stock_account/models/stock_picking.py @@ -38,14 +38,14 @@ def _get_amount_lines(self): return self.mapped("move_ids") @api.depends("move_ids") - def _compute_amount(self): - return super()._compute_amount() + def _compute_fiscal_amount(self): + return super()._compute_fiscal_amount() @api.depends("move_ids.price_unit") def _amount_all(self): """Compute the total amounts of the Picking.""" for picking in self: - picking._compute_amount() + picking._compute_fiscal_amount() @api.model def fields_view_get(