diff --git a/l10n_br_account/models/account_move.py b/l10n_br_account/models/account_move.py index b294fd438d6d..290feef3c7e6 100644 --- a/l10n_br_account/models/account_move.py +++ b/l10n_br_account/models/account_move.py @@ -300,6 +300,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")) @@ -338,31 +339,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 + untaxed_amount_currency = invoice.amount_untaxed * sign + untaxed_amount = invoice.amount_untaxed_signed invoice_payment_terms = ( invoice.invoice_payment_term_id._compute_terms( date_ref=invoice.invoice_date diff --git a/l10n_br_account/models/account_move_line.py b/l10n_br_account/models/account_move_line.py index 315b2f21dbf6..edc031ffea9e 100644 --- a/l10n_br_account/models/account_move_line.py +++ b/l10n_br_account/models/account_move_line.py @@ -110,6 +110,18 @@ class AccountMoveLine(models.Model): " and '3-3' for the last installment.", ) + # These fields are already inherited by _inherits, but there is some limitation of + # the ORM that the values of these fields are zeroed when called by onchange. This + # limitation directly affects the _get_amount_credit_debit method. + amount_untaxed = fields.Monetary(compute="_compute_amounts") + amount_total = fields.Monetary( + compute="_compute_amounts", + ) + + def _compute_amounts(self): + res = super()._compute_amounts() + return res + @api.depends( "quantity", "price_unit", @@ -301,6 +313,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 +338,8 @@ def changed(fname): ) unsigned_amount_currency = line.currency_id.round( amount_total - - ( - line.amount_tax_included - - line.amount_tax_withholding - ) - - line.amount_tax_not_included - - line.icms_relief_value + # - line.amount_tax_included + # - line.amount_tax_not_included ) amount_currency = unsigned_amount_currency * line.move_id.direction_sign if line.amount_currency != amount_currency or line not in before: @@ -325,6 +347,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 +429,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 @@ -536,4 +570,4 @@ def _onchange_fiscal_tax_ids(self): user_type=user_type, fiscal_operation=self.fiscal_operation_id ) - return result + return result # diff --git a/l10n_br_account/tests/test_account_move_lc.py b/l10n_br_account/tests/test_account_move_lc.py index af967744e948..3ce4795d3c92 100644 --- a/l10n_br_account/tests/test_account_move_lc.py +++ b/l10n_br_account/tests/test_account_move_lc.py @@ -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,9 +1273,9 @@ 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, + "amount_currency": 133.5, "debit": 0.0, - "credit": 0.0, + "credit": 133.5, "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_fiscal/models/document_line_mixin_methods.py b/l10n_br_fiscal/models/document_line_mixin_methods.py index 0442dbd36b41..0e4e4c8bbe33 100644 --- a/l10n_br_fiscal/models/document_line_mixin_methods.py +++ b/l10n_br_fiscal/models/document_line_mixin_methods.py @@ -127,6 +127,7 @@ def _get_view(self, view_id=None, view_type="form", **options): "company_id", "price_unit", "quantity", + "icms_relief_id", ) def _compute_amounts(self): for record in self: @@ -134,20 +135,20 @@ def _compute_amounts(self): # 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/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_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