105 lines
3.9 KiB
Python
Executable File
105 lines
3.9 KiB
Python
Executable File
# 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
|