Skip to content

Commit

Permalink
Merge PR #1664 into 16.0
Browse files Browse the repository at this point in the history
Signed-off-by grindtildeath
  • Loading branch information
OCA-git-bot committed May 13, 2024
2 parents 1897625 + 890d038 commit a1c0056
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 44 deletions.
1 change: 1 addition & 0 deletions account_invoice_triple_discount/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ Contributors
* `Aion Tech <https://aiontech.company/>`_:

* Simone Rubino <simone.rubino@aion-tech.it>
* Laurent Mignon <laurent.mignon@acsone.eu>

Maintainers
~~~~~~~~~~~
Expand Down
85 changes: 45 additions & 40 deletions account_invoice_triple_discount/models/account_move_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import functools
from contextlib import contextmanager

from odoo import api, fields, models
from odoo.tools import float_compare
Expand Down Expand Up @@ -55,6 +56,42 @@ def create(self, values_list):
record.write(old_values[index])
return records

@contextmanager
def _aggregated_discount(self):
"""A context manager to temporarily change the discount value on the
records and restore it after the context is exited. It temporarily
changes the discount value to the aggregated discount value so that
methods that depend on the discount value will use the aggregated
discount value instead of the original one.
"""
discount_field = self._fields["discount"]
original_digits = discount_field._digits
# Change the discount field to have a higher precision to avoid
# rounding errors when computing the aggregated discount
discount_field._digits = (16, 16)
# Protect discount field from triggering recompute of totals
# and calls to the write method on account.move. This is safe
# because we are going to restore the original value at the end
# of the method. This is also required to avoid to trigger the
# _sync_dynamic_lines and _check_balanced methods on account.move
# that would lead to errors while computing the triple discount
# on the invoice lines and raise an exception when the computation is called
# on account.move.line with a date prior to fiscal year close date.
with self.env.protecting([discount_field], self):
old_values = {}
for line in self:
old_values[line.id] = line.discount
aggregated_discount = line._compute_aggregated_discount(line.discount)
line.update({"discount": aggregated_discount})
yield
discount_field._digits = original_digits
for line in self:
if line.id not in old_values:
continue
line.with_context(
restoring_triple_discount=True,
).update({"discount": old_values[line.id]})

@api.depends(
"quantity",
"discount",
Expand All @@ -65,26 +102,10 @@ def create(self, values_list):
"discount3",
)
def _compute_totals(self):
"""
As the totals are recalculated based on a single discount, we need to
simulate a multiple discount by changing the discount value. Values are
restored after the original process is done
"""
old_values_by_line_id = {}
digits = self._fields["discount"]._digits
self._fields["discount"]._digits = (16, 16)
for line in self:
aggregated_discount = line._compute_aggregated_discount(line.discount)
old_values_by_line_id[line.id] = {"discount": line.discount}
line.update({"discount": aggregated_discount})
res = super()._compute_totals()
self._fields["discount"]._digits = digits
for line in self:
if line.id not in old_values_by_line_id:
continue
line.with_context(
restoring_triple_discount=True,
).update(old_values_by_line_id[line.id])
# As the totals are recompute based on the discount field, we need
# to use the aggregated discount value to compute the totals.
with self._aggregated_discount():
res = super()._compute_totals()
return res

@api.depends(
Expand All @@ -100,26 +121,10 @@ def _compute_totals(self):
"discount3",
)
def _compute_all_tax(self):
"""
As the taxes are recalculated based on a single discount, we need to
simulate a multiple discount by changing discount value. Values are
restored after the original process is done
"""
digits = self._fields["discount"]._digits
self._fields["discount"]._digits = (16, 16)
old_values_by_line_id = {}
for line in self:
aggregated_discount = line._compute_aggregated_discount(line.discount)
old_values_by_line_id[line.id] = {"discount": line.discount}
line.update({"discount": aggregated_discount})
res = super()._compute_all_tax()
self._fields["discount"]._digits = digits
for line in self:
if line.id not in old_values_by_line_id:
continue
line.with_context(
restoring_triple_discount=True,
).update(old_values_by_line_id[line.id])
# As the taxes are recompute based on the discount field, we need
# to use the aggregated discount value to compute the taxes.
with self._aggregated_discount():
res = super()._compute_all_tax()
return res

def _convert_to_tax_base_line_dict(self):
Expand Down
1 change: 1 addition & 0 deletions account_invoice_triple_discount/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
* `Aion Tech <https://aiontech.company/>`_:

* Simone Rubino <simone.rubino@aion-tech.it>
* Laurent Mignon <laurent.mignon@acsone.eu>
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
Expand Down Expand Up @@ -434,6 +433,7 @@ <h2><a class="toc-backref" href="#toc-entry-5">Contributors</a></h2>
<li>Simone Rubino &lt;<a class="reference external" href="mailto:simone.rubino&#64;aion-tech.it">simone.rubino&#64;aion-tech.it</a>&gt;</li>
</ul>
</li>
<li>Laurent Mignon &lt;<a class="reference external" href="mailto:laurent.mignon&#64;acsone.eu">laurent.mignon&#64;acsone.eu</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
# Copyright 2023 Simone Rubino - Aion Tech
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo.tests import TransactionCase
from odoo.tests.common import Form

from odoo.addons.base.tests.common import BaseCommon

class TestInvoiceTripleDiscount(TransactionCase):

class TestInvoiceTripleDiscount(BaseCommon):
@classmethod
def setUpClass(cls):
super(TestInvoiceTripleDiscount, cls).setUpClass()
Expand All @@ -17,7 +18,6 @@ def setUpClass(cls):
cls.Partner = cls.env["res.partner"]
cls.Journal = cls.env["account.journal"]

cls.partner = cls.Partner.create({"name": "test"})
cls.tax = cls.AccountTax.create(
{
"name": "TAX 15%",
Expand Down Expand Up @@ -202,3 +202,19 @@ def test_07_round_tax_discount(self):
invoice_line.discount = 100
invoice_line.tax_ids = False
self.assertEqual(invoice_line.discount, 100)

def test_tax_compute_with_lock_date(self):
# Check that the tax computation works even if the lock date is set
invoice = self.create_simple_invoice(0)
invoice_form = Form(invoice)
with invoice_form.invoice_line_ids.edit(0) as line_form:
line_form.name = "Line Decimals"
line_form.quantity = 9950
line_form.price_unit = 0.14
line_form.discount = 10
line_form.discount2 = 20
invoice_form.save()
invoice_line = invoice.invoice_line_ids[0]
invoice.action_post()
self.env.user.company_id.fiscalyear_lock_date = "2000-01-01"
invoice_line._compute_all_tax()

0 comments on commit a1c0056

Please sign in to comment.