From 8873e2015f3f44956a6198cfb013820d486fb87c Mon Sep 17 00:00:00 2001 From: oco-odoo Date: Fri, 24 Sep 2021 12:16:01 +0000 Subject: [PATCH] [IMP] account: make use of fiscal positions in write-offs created by reconciliation models Before, the taxes assigned by the reconciliation models in their write-offs weren't mapped by fiscal positions. This could cause confusion, and essentially required the user to always fix by hand the cases that weren't matched. Task 2645280 closes odoo/odoo#77204 X-original-commit: e75184459a7d47df86aa72efa36c06462d7ee9ea Related: odoo/enterprise#21187 Signed-off-by: Laurent Smet Signed-off-by: oco-odoo --- .../account/models/account_reconcile_model.py | 17 +++--- .../test_reconciliation_matching_rules.py | 52 +++++++++++++++++++ 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/addons/account/models/account_reconcile_model.py b/addons/account/models/account_reconcile_model.py index be34f6caa7b..2198f4987cb 100644 --- a/addons/account/models/account_reconcile_model.py +++ b/addons/account/models/account_reconcile_model.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from odoo import api, fields, models, _ +from odoo import api, fields, models, Command, _ from odoo.tools import float_compare, float_is_zero from odoo.osv.expression import get_unaccent_wrapper from odoo.exceptions import UserError, ValidationError @@ -356,7 +356,7 @@ class AccountReconcileModel(models.Model): base_line_dict['tax_tag_ids'] = [(6, 0, res['base_tags'])] return new_aml_dicts - def _get_write_off_move_lines_dict(self, st_line, residual_balance): + def _get_write_off_move_lines_dict(self, st_line, residual_balance, partner_id): ''' Get move.lines dict (to be passed to the create()) corresponding to the reconciliation model's write-off lines. :param st_line: An account.bank.statement.line record.(possibly empty, if performing manual reconciliation) :param residual_balance: The residual balance of the statement line. @@ -420,13 +420,16 @@ class AccountReconcileModel(models.Model): residual_balance -= balance if line.tax_ids: - writeoff_line['tax_ids'] = [(6, None, line.tax_ids.ids)] - tax = line.tax_ids + taxes = line.tax_ids + detected_fiscal_position = self.env['account.fiscal.position'].get_fiscal_position(partner_id) + if detected_fiscal_position: + taxes = detected_fiscal_position.map_tax(taxes) + writeoff_line['tax_ids'] = [Command.set(taxes.ids)] # Multiple taxes with force_tax_included results in wrong computation, so we # only allow to set the force_tax_included field if we have one tax selected if line.force_tax_included: - tax = tax[0].with_context(force_price_include=True) - tax_vals_list = self._get_taxes_move_lines_dict(tax, writeoff_line) + taxes = taxes[0].with_context(force_price_include=True) + tax_vals_list = self._get_taxes_move_lines_dict(taxes, writeoff_line) lines_vals_list += tax_vals_list if not line.force_tax_included: for tax_line in tax_vals_list: @@ -828,6 +831,7 @@ class AccountReconcileModel(models.Model): writeoff_vals_list = self._get_write_off_move_lines_dict( st_line, matched_candidates_values['balance_sign'] * residual_balance_after_rec, + partner.id, ) if writeoff_vals_list: rslt['status'] = 'write_off' @@ -1043,6 +1047,7 @@ class AccountReconcileModel(models.Model): writeoff_vals_list = self._get_write_off_move_lines_dict( st_line, matched_candidates_values['balance_sign'] * residual_balance_after_rec, + partner.id, ) rslt = { diff --git a/addons/account/tests/test_reconciliation_matching_rules.py b/addons/account/tests/test_reconciliation_matching_rules.py index 1fcb021edeb..217aea2ac9a 100644 --- a/addons/account/tests/test_reconciliation_matching_rules.py +++ b/addons/account/tests/test_reconciliation_matching_rules.py @@ -807,6 +807,58 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon): {'partner_id': self.partner_1.id, 'debit': 7.26, 'credit': 0.0, 'tax_ids': [], 'tax_line_id': self.tax12.id}, ]) + def test_auto_reconcile_with_tax_fpos(self): + """ Test the fiscal positions are applied by reconcile models when using taxes. + """ + self.rule_1.write({ + 'auto_reconcile': True, + 'rule_type': 'writeoff_suggestion', + 'line_ids': [(1, self.rule_1.line_ids.id, { + 'amount': 100, + 'force_tax_included': True, + 'tax_ids': [(6, 0, self.tax21.ids)], + })] + }) + + self.partner_1.country_id = self.env.ref('base.lu') + belgium = self.env.ref('base.be') + self.partner_2.country_id = belgium + + self.bank_line_2.partner_id = self.partner_2 + + self.bank_line_1.amount = -121 + self.bank_line_2.amount = -112 + + self.env['account.fiscal.position'].create({ + 'name': "Test", + 'country_id': belgium.id, + 'auto_apply': True, + 'tax_ids': [ + Command.create({ + 'tax_src_id': self.tax21.id, + 'tax_dest_id': self.tax12.id, + }), + ] + }) + + self._check_statement_matching(self.rule_1, { + self.bank_line_1.id: {'aml_ids': [], 'model': self.rule_1, 'status': 'reconciled', 'partner': self.bank_line_1.partner_id}, + self.bank_line_2.id: {'aml_ids': [], 'model': self.rule_1, 'status': 'reconciled', 'partner': self.bank_line_2.partner_id}, + }, statements=self.bank_st) + + self.assertRecordValues(self.bank_line_1.line_ids, [ + {'partner_id': self.partner_1.id, 'debit': 0.0, 'credit': 121.0, 'tax_ids': [], 'tax_line_id': False}, + {'partner_id': self.partner_1.id, 'debit': 100.0, 'credit': 0.0, 'tax_ids': [self.tax21.id], 'tax_line_id': False}, + {'partner_id': self.partner_1.id, 'debit': 21.0, 'credit': 0.0, 'tax_ids': [], 'tax_line_id': self.tax21.id}, + ]) + + self.assertRecordValues(self.bank_line_2.line_ids, [ + {'partner_id': self.partner_2.id, 'debit': 0.0, 'credit': 112.0, 'tax_ids': [], 'tax_line_id': False}, + {'partner_id': self.partner_2.id, 'debit': 100.0, 'credit': 0.0, 'tax_ids': [self.tax12.id], 'tax_line_id': False}, + {'partner_id': self.partner_2.id, 'debit': 12.0, 'credit': 0.0, 'tax_ids': [], 'tax_line_id': self.tax12.id}, + ]) + + def test_reverted_move_matching(self): partner = self.partner_1 AccountMove = self.env['account.move']