Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[14.0] [FW] [IMP] account global discount: add base selection and fixed discount #1666

Open
wants to merge 2 commits into
base: 14.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion account_global_discount/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Account Global Discount
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:99b4a5fc4c160372c6436d7866324cab44bc010f7436f88731b3419d83d76c63
!! source digest: sha256:67f29e2f1d4c9dd6ef7dfaa58d84e53a86abb545b581d5e7c5c042a37190552b
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
Expand Down Expand Up @@ -111,6 +111,12 @@ Contributors
* Ernesto Tejeda
* Víctor Martínez
* Omar Castiñeira <[email protected]>
* `TAKOBI <https://takobi.online>`_:

* Simone Rubino <[email protected]>
* `Pordenone Linux User Group APS <https://www.pnlug.it>`_:

* Sergio Zanchetta

Maintainers
~~~~~~~~~~~
Expand Down
151 changes: 123 additions & 28 deletions account_global_discount/models/account_move.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Copyright 2019 Tecnativa - David Vidal
# Copyright 2020-2021 Tecnativa - Pedro M. Baeza
# Copyright 2021 Tecnativa - Víctor Martínez
# Copyright 2022 Simone Rubino - TAKOBI
# Copyright 2024 Sergio Zanchetta - PNLUG APS
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, exceptions, fields, models
from odoo.fields import first
from odoo.tools import config


Expand Down Expand Up @@ -33,6 +36,22 @@ class AccountMove(models.Model):
readonly=True,
states={"draft": [("readonly", False)]},
)
global_discount_base = fields.Selection(
selection=[
("subtotal", "Subtotal"),
("total", "Total"),
],
string="Discount Base",
compute="_compute_global_discount_selection",
)
global_discount_type = fields.Selection(
selection=[
("percentage", "Percentage"),
("fixed", "Fixed"),
],
string="Discount Type",
compute="_compute_global_discount_selection",
)
amount_global_discount = fields.Monetary(
string="Total Global Discounts",
compute="_compute_amount",
Expand All @@ -49,12 +68,29 @@ class AccountMove(models.Model):
compute_sudo=True,
store=True,
)
amount_total_before_global_discounts = fields.Monetary(
string="Amount Total Before Discounts",
compute="_compute_amount",
currency_field="currency_id",
readonly=True,
compute_sudo=True,
store=True,
)
invoice_global_discount_ids = fields.One2many(
comodel_name="account.invoice.global.discount",
inverse_name="invoice_id",
readonly=True,
)

@api.depends("global_discount_ids")
def _compute_global_discount_selection(self):
for invoice in self:
# Only check first because sanity checks
# assure all global discounts in same invoice have same base
first_global_discount = first(invoice.global_discount_ids)
invoice.global_discount_base = first_global_discount.discount_base
invoice.global_discount_type = first_global_discount.discount_type

def _recompute_tax_lines(
self, recompute_tax_base_amount=False, tax_rep_lines_to_recompute=None
):
Expand Down Expand Up @@ -84,25 +120,29 @@ def _update_tax_lines_for_global_discount(self):
We are altering the recently recreated tax move lines got calling super on
``_recompute_tax_lines``.
"""
round_curr = self.currency_id.round
tax_lines = self.line_ids.filtered(
lambda r: r.tax_line_id.amount_type in ("percent", "division")
)
for tax_line in tax_lines:
base = tax_line.tax_base_amount
tax_line.base_before_global_discounts = base
amount = tax_line.balance
for discount in self.global_discount_ids:
base = discount._get_global_discount_vals(base)["base_discounted"]
amount = discount._get_global_discount_vals(amount)["base_discounted"]
tax_line.tax_base_amount = round_curr(base)
tax_line.debit = amount > 0.0 and amount or 0.0
tax_line.credit = amount < 0.0 and -amount or 0.0
# Apply onchanges
tax_line._onchange_balance()
tax_line._onchange_amount_currency()

def _prepare_global_discount_vals(self, global_discount, base, tax_ids):
if self.global_discount_base == "subtotal":
round_curr = self.currency_id.round
tax_lines = self.line_ids.filtered(
lambda r: r.tax_line_id.amount_type in ("percent", "division")
)
for tax_line in tax_lines:
base = tax_line.tax_base_amount
tax_line.base_before_global_discounts = base
amount = tax_line.balance
for discount in self.global_discount_ids:
base = discount._get_global_discount_vals(base)["base_discounted"]
if discount.discount_type == "percentage":
amount = discount._get_global_discount_vals(amount)[
"base_discounted"
]
tax_line.tax_base_amount = round_curr(base)
tax_line.debit = amount > 0.0 and amount or 0.0
tax_line.credit = amount < 0.0 and -amount or 0.0
# Apply onchanges
tax_line._onchange_balance()
tax_line._onchange_amount_currency()

def _prepare_global_discount_vals(self, global_discount, base, tax_ids=None):
"""Prepare the dictionary values for an invoice global discount
line.
"""
Expand All @@ -112,11 +152,13 @@ def _prepare_global_discount_vals(self, global_discount, base, tax_ids):
"name": global_discount.display_name,
"invoice_id": self.id,
"global_discount_id": global_discount.id,
"discount_type": global_discount.discount_type,
"discount": global_discount.discount,
"discount_fixed": global_discount.discount_fixed,
"base": base,
"base_discounted": discount["base_discounted"],
"account_id": global_discount.account_id.id,
"tax_ids": [(4, tax_id) for tax_id in tax_ids],
"tax_ids": [(4, tax_id) for tax_id in tax_ids] if tax_ids else None,
}

def _set_global_discounts_by_tax(self):
Expand All @@ -128,10 +170,16 @@ def _set_global_discounts_by_tax(self):
self.ensure_one()
if not self.is_invoice():
return
in_draft_mode = self != self._origin
if not self.global_discount_ids:
return
taxes_keys = {}
# Perform a sanity check for discarding cases that will lead to
# incorrect data in discounts
discount_base = set(self.global_discount_ids.mapped("discount_base"))
if len(discount_base) > 1:
raise exceptions.UserError(_("All global discount must have the same base"))
discount_base = discount_base.pop()

_self = self.filtered("global_discount_ids")
for inv_line in _self.invoice_line_ids.filtered(lambda l: not l.display_type):
for key in taxes_keys:
Expand All @@ -141,6 +189,14 @@ def _set_global_discounts_by_tax(self):
taxes_keys[tuple(inv_line.tax_ids.ids)] = True
# Reset previous global discounts
self.invoice_global_discount_ids -= self.invoice_global_discount_ids

if discount_base == "subtotal":
self._apply_global_discount_by_subtotal(_self, taxes_keys)
elif discount_base == "total":
self._apply_global_discount_by_total()

def _apply_global_discount_by_subtotal(self, _self, taxes_keys):
in_draft_mode = self != self._origin
model = "account.invoice.global.discount"
create_method = in_draft_mode and self.env[model].new or self.env[model].create
for tax_line in _self.line_ids.filtered("tax_line_id"):
Expand Down Expand Up @@ -171,6 +227,16 @@ def _set_global_discounts_by_tax(self):
create_method(vals)
base = vals["base_discounted"]

def _apply_global_discount_by_total(self):
in_draft_mode = self != self._origin
model = "account.invoice.global.discount"
create_method = in_draft_mode and self.env[model].new or self.env[model].create
base = self.amount_total
for global_discount in self.global_discount_ids:
vals = self._prepare_global_discount_vals(global_discount, base, None)
create_method(vals)
base = vals["base_discounted"]

def _recompute_global_discount_lines(self):
"""Append global discounts move lines.

Expand All @@ -181,7 +247,9 @@ def _recompute_global_discount_lines(self):
in_draft_mode = self != self._origin
model = "account.move.line"
create_method = in_draft_mode and self.env[model].new or self.env[model].create
for discount in self.invoice_global_discount_ids.filtered("discount"):
for discount in self.invoice_global_discount_ids.filtered(
lambda x: x.discount or x.discount_fixed
):
sign = -1 if self.move_type in {"in_invoice", "out_refund"} else 1
disc_amount = sign * discount.discount_amount
create_method(
Expand Down Expand Up @@ -248,8 +316,14 @@ def _compute_amount_one(self):
for discount in self.invoice_global_discount_ids
)
self.amount_untaxed_before_global_discounts = self.amount_untaxed
self.amount_untaxed = self.amount_untaxed + self.amount_global_discount
self.amount_total = self.amount_untaxed + self.amount_tax
self.amount_total_before_global_discounts = self.amount_total

if self.global_discount_base == "subtotal":
self.amount_untaxed = self.amount_untaxed + self.amount_global_discount
self.amount_total = self.amount_untaxed + self.amount_tax
elif self.global_discount_base == "total":
self.amount_total += self.amount_global_discount

amount_untaxed_signed = self.amount_untaxed
if (
self.currency_id
Expand Down Expand Up @@ -296,6 +370,7 @@ def create(self, vals_list):
def _check_balanced(self):
"""Add the check of proper taxes for global discounts."""
super()._check_balanced()

test_condition = not config["test_enable"] or self.env.context.get(
"test_account_global_discount"
)
Expand Down Expand Up @@ -358,7 +433,20 @@ class AccountInvoiceGlobalDiscount(models.Model):
comodel_name="global.discount",
string="Global Discount",
)
discount = fields.Float(string="Discount (number)")
discount_type = fields.Selection(
selection=[
("percentage", "Percentage"),
("fixed", "Fixed"),
],
string="Discount Type",
)
discount = fields.Float(
string="Discount (number)",
)
discount_fixed = fields.Float(
string="Discount (number)",
currency_field="currency_id",
)
discount_display = fields.Char(
compute="_compute_discount_display",
string="Discount",
Expand All @@ -367,7 +455,7 @@ class AccountInvoiceGlobalDiscount(models.Model):
base_discounted = fields.Float(string="Base after discount", digits="Product Price")
currency_id = fields.Many2one(related="invoice_id.currency_id", readonly=True)
discount_amount = fields.Monetary(
string="Discounted Amount",
string="Discount Amount",
compute="_compute_discount_amount",
currency_field="currency_id",
compute_sudo=True,
Expand All @@ -387,9 +475,16 @@ class AccountInvoiceGlobalDiscount(models.Model):

def _compute_discount_display(self):
"""Given a discount type, we need to render a different symbol"""

for one in self:
precision = self.env["decimal.precision"].precision_get("Discount")
one.discount_display = "{0:.{1}f}%".format(one.discount * -1, precision)
if one.discount_type == "percentage":
precision = self.env["decimal.precision"].precision_get("Discount")
one.discount_display = "{0:.{1}f}%".format(one.discount * -1, precision)
elif one.discount_type == "fixed":
precision = self.env["decimal.precision"].precision_get("Product Price")
one.discount_display = "{0:.{1}f}".format(
one.discount_fixed * -1, precision
)

@api.depends("base", "base_discounted")
def _compute_discount_amount(self):
Expand Down
6 changes: 6 additions & 0 deletions account_global_discount/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,9 @@
* Ernesto Tejeda
* Víctor Martínez
* Omar Castiñeira <[email protected]>
* `TAKOBI <https://takobi.online>`_:

* Simone Rubino <[email protected]>
* `Pordenone Linux User Group APS <https://www.pnlug.it>`_:

* Sergio Zanchetta
10 changes: 9 additions & 1 deletion account_global_discount/static/description/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ <h1 class="title">Account Global Discount</h1>
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:99b4a5fc4c160372c6436d7866324cab44bc010f7436f88731b3419d83d76c63
!! source digest: sha256:67f29e2f1d4c9dd6ef7dfaa58d84e53a86abb545b581d5e7c5c042a37190552b
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/account-invoicing/tree/14.0/account_global_discount"><img alt="OCA/account-invoicing" src="https://img.shields.io/badge/github-OCA%2Faccount--invoicing-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/account-invoicing-14-0/account-invoicing-14-0-account_global_discount"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/account-invoicing&amp;target_branch=14.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>Apply global discounts to invoices</p>
Expand Down Expand Up @@ -462,6 +462,14 @@ <h2><a class="toc-backref" href="#toc-entry-7">Contributors</a></h2>
</ul>
</li>
<li>Omar Castiñeira &lt;<a class="reference external" href="mailto:omar&#64;comunitea.com">omar&#64;comunitea.com</a>&gt;</li>
<li><a class="reference external" href="https://takobi.online">TAKOBI</a>:<ul>
<li>Simone Rubino &lt;<a class="reference external" href="mailto:sir&#64;takobi.online">sir&#64;takobi.online</a>&gt;</li>
</ul>
</li>
<li><a class="reference external" href="https://www.pnlug.it">Pordenone Linux User Group APS</a>:<ul>
<li>Sergio Zanchetta</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
Expand Down
Loading
Loading