Initial commit: Odoo 18.0-20251222 extra-addons
This commit is contained in:
1
sale_fixed_discount/models/__init__.py
Executable file
1
sale_fixed_discount/models/__init__.py
Executable file
@@ -0,0 +1 @@
|
||||
from . import sale_order_line
|
||||
104
sale_fixed_discount/models/sale_order_line.py
Executable file
104
sale_fixed_discount/models/sale_order_line.py
Executable file
@@ -0,0 +1,104 @@
|
||||
# Copyright 2017-20 ForgeFlow S.L.
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tools.float_utils import float_compare, float_round
|
||||
|
||||
|
||||
class SaleOrderLine(models.Model):
|
||||
_inherit = "sale.order.line"
|
||||
|
||||
discount_fixed = fields.Float(
|
||||
string="Discount (Fixed)",
|
||||
digits="Product Price",
|
||||
help="Fixed amount discount.",
|
||||
)
|
||||
|
||||
@api.constrains("discount_fixed", "discount")
|
||||
def _check_discounts(self):
|
||||
"""Check that the fixed discount and the discount percentage are consistent."""
|
||||
for line in self:
|
||||
if line.discount_fixed and line.discount:
|
||||
currency = line.currency_id
|
||||
calculated_fixed_discount = float_round(
|
||||
line._get_discount_from_fixed_discount(),
|
||||
precision_rounding=currency.rounding,
|
||||
)
|
||||
|
||||
if (
|
||||
float_compare(
|
||||
calculated_fixed_discount,
|
||||
line.discount,
|
||||
precision_rounding=currency.rounding,
|
||||
)
|
||||
!= 0
|
||||
):
|
||||
raise ValidationError(
|
||||
self.env._(
|
||||
"The fixed discount %(fixed)s does not match the calculated"
|
||||
"discount %(discount)s %%."
|
||||
"Please correct one of the discounts.",
|
||||
fixed=line.discount_fixed,
|
||||
discount=line.discount,
|
||||
)
|
||||
)
|
||||
|
||||
def _prepare_base_line_for_taxes_computation(self, **kwargs):
|
||||
"""Prior to calculating the tax toals for a line, update the discount value
|
||||
used in the tax calculation to the full float value. Otherwise, we get rounding
|
||||
errors in the resulting calculated totals.
|
||||
|
||||
For example:
|
||||
- price_unit = 750.0
|
||||
- discount_fixed = 100.0
|
||||
- discount = 13.33
|
||||
=> price_subtotal = 650.03
|
||||
|
||||
:return: A python dictionary.
|
||||
"""
|
||||
self.ensure_one()
|
||||
|
||||
# Accurately pass along the fixed discount amount to the tax computation method.
|
||||
if self.discount_fixed:
|
||||
return self.env["account.tax"]._prepare_base_line_for_taxes_computation(
|
||||
self,
|
||||
**{
|
||||
"tax_ids": self.tax_id,
|
||||
"quantity": self.product_uom_qty,
|
||||
"partner_id": self.order_id.partner_id,
|
||||
"currency_id": self.order_id.currency_id
|
||||
or self.order_id.company_id.currency_id,
|
||||
"rate": self.order_id.currency_rate,
|
||||
"discount": self._get_discount_from_fixed_discount(),
|
||||
**kwargs,
|
||||
},
|
||||
)
|
||||
|
||||
return super()._prepare_base_line_for_taxes_computation(**kwargs)
|
||||
|
||||
@api.depends("discount_fixed", "price_unit")
|
||||
def _compute_discount(self):
|
||||
lines_with_discount_fixed = self.filtered(lambda sol: sol.discount_fixed)
|
||||
for line in lines_with_discount_fixed:
|
||||
line.discount = line._get_discount_from_fixed_discount()
|
||||
return super(
|
||||
SaleOrderLine, self - lines_with_discount_fixed
|
||||
)._compute_discount()
|
||||
|
||||
def _get_discount_from_fixed_discount(self):
|
||||
"""Calculate the discount percentage from the fixed discount amount."""
|
||||
self.ensure_one()
|
||||
if not self.discount_fixed:
|
||||
return 0.0
|
||||
|
||||
return (
|
||||
(self.price_unit != 0)
|
||||
and ((self.discount_fixed) / self.price_unit) * 100
|
||||
or 0.00
|
||||
)
|
||||
|
||||
def _prepare_invoice_line(self, **optional_values):
|
||||
res = super()._prepare_invoice_line(**optional_values)
|
||||
res.update({"discount_fixed": self.discount_fixed})
|
||||
return res
|
||||
Reference in New Issue
Block a user