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

[16.0][REF] purchase_triple_discount: Consolidate discount in std field #2599

Merged
merged 2 commits into from
Mar 9, 2025
Merged
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
6 changes: 3 additions & 3 deletions purchase_discount/tests/test_purchase_discount.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,12 @@ def test_invoice(self):
line = invoice.invoice_line_ids.filtered(
lambda x: x.purchase_line_id == self.po_line_1
)
self.assertEqual(line.discount, 50)
self.assertAlmostEqual(line.discount, 50)
line = invoice.invoice_line_ids.filtered(
lambda x: x.purchase_line_id == self.po_line_2
)
self.assertEqual(line.discount, 30)
self.assertAlmostEqual(line.discount, 30)
line = invoice.invoice_line_ids.filtered(
lambda x: x.purchase_line_id == self.po_line_3
)
self.assertEqual(line.discount, 0)
self.assertAlmostEqual(line.discount, 0)
1 change: 1 addition & 0 deletions purchase_triple_discount/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from . import models
from . import report
from .hooks import post_init_hook
3 changes: 2 additions & 1 deletion purchase_triple_discount/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Purchase Order Triple Discount",
"version": "16.0.2.0.0",
"version": "16.0.3.0.0",
"category": "Purchase Management",
"author": "Tecnativa," "GRAP," "Odoo Community Association (OCA)",
"website": "https://github.com/OCA/purchase-workflow",
Expand All @@ -19,4 +19,5 @@
"views/res_partner_view.xml",
],
"installable": True,
"post_init_hook": "post_init_hook",
}
25 changes: 25 additions & 0 deletions purchase_triple_discount/hooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2024-Today - Sylvain Le GAL (GRAP)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging

_logger = logging.getLogger(__name__)


def post_init_hook(cr, registry):
_logger.info("Initializing column discount1 on table purchase_order_line")
cr.execute(
"""
UPDATE purchase_order_line
SET discount1 = discount
WHERE discount != 0
"""
)
_logger.info("Initializing column discount1 on table product_supplierinfo")
cr.execute(
"""
UPDATE product_supplierinfo
SET discount1 = discount
WHERE discount != 0
"""
)
74 changes: 74 additions & 0 deletions purchase_triple_discount/migrations/16.0.3.0.0/post-migrate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)

from openupgradelib import openupgrade


@openupgrade.logging()
def compute_purchase_line_discount(env):
purchase_lines_to_compute = env["purchase.order.line"].search(
[
"|",
"|",
("discount1", "!=", 0),
("discount2", "!=", 0),
("discount3", "!=", 0),
]
)
for line in purchase_lines_to_compute:
discount = line._get_aggregated_multiple_discounts(
[line[x] for x in ["discount1", "discount2", "discount3"]]
)
rounded_discount = line._fields["discount"].convert_to_column(discount, line)
openupgrade.logged_query(
env.cr,
"""
UPDATE prochase_order_line
SET discount = %s
WHERE id = %s;
""",
tuple(
[
rounded_discount,
line.id,
]
),
)


@openupgrade.logging()
def compute_supplierinfo_line_discount(env):
supplierinfo_lines_to_compute = env["product.supplierinfo"].search(
[
"|",
"|",
("discount1", "!=", 0),
("discount2", "!=", 0),
("discount3", "!=", 0),
]
)
for line in supplierinfo_lines_to_compute:
discount = line._get_aggregated_multiple_discounts(
[line[x] for x in ["discount1", "discount2", "discount3"]]
)
rounded_discount = line._fields["discount"].convert_to_column(discount, line)
openupgrade.logged_query(
env.cr,
"""
UPDATE product_supplierinfo
SET discount = %s
WHERE id = %s;
""",
tuple(
[
rounded_discount,
line.id,
]
),
)


@openupgrade.migrate()
def migrate(env, version):
compute_purchase_line_discount(env)
compute_supplierinfo_line_discount(env)
57 changes: 57 additions & 0 deletions purchase_triple_discount/migrations/16.0.3.0.0/pre-migrate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Copyright 2024 Camptocamp SA
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from openupgradelib import openupgrade


def migrate_order_discount_to_discount1(env):
openupgrade.add_fields(
env,
[
(
"discount1",
"purchase.order.line",
"purchase_order_line",
"float",
"numeric",
"purchase_triple_discount",
0.0,
)
],
)
openupgrade.logged_query(
env.cr,
"""
UPDATE purchase_order_line
SET discount1 = discount;
""",
)


def migrate_supplierinfo_discount_to_discount1(env):
openupgrade.add_fields(
env,
[
(
"discount1",
"product.supplierinfo",
"product_supplierinfo",
"float",
"numeric",
"purchase_triple_discount",
0.0,
)
],
)
openupgrade.logged_query(
env.cr,
"""
UPDATE product_supplierinfo
SET discount1 = discount;
""",
)


@openupgrade.migrate()
def migrate(env, version):
migrate_order_discount_to_discount1(env)
migrate_supplierinfo_discount_to_discount1(env)
1 change: 1 addition & 0 deletions purchase_triple_discount/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from . import triple_discount_mixin
from . import product_supplierinfo
from . import purchase_order
from . import res_partner
49 changes: 21 additions & 28 deletions purchase_triple_discount/models/product_supplierinfo.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,34 @@
# Copyright 2019 Tecnativa - David Vidal
# Copyright 2019 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo import api, models


class ProductSupplierInfo(models.Model):
_inherit = "product.supplierinfo"
_name = "product.supplierinfo"
_inherit = ["product.supplierinfo", "triple.discount.mixin"]

discount2 = fields.Float(
string="Discount 2 (%)",
digits="Discount",
compute="_compute_discount2",
store=True,
readonly=False,
)
discount3 = fields.Float(
string="Discount 3 (%)",
digits="Discount",
compute="_compute_discount3",
store=True,
readonly=False,
)
@api.onchange("partner_id")
def _onchange_partner_id(self):
self.update(

Check warning on line 13 in purchase_triple_discount/models/product_supplierinfo.py

View check run for this annotation

Codecov / codecov/patch

purchase_triple_discount/models/product_supplierinfo.py#L13

Added line #L13 was not covered by tests
{
field: self.partner_id[f"default_supplierinfo_{field}"]
for field in self._get_multiple_discount_field_names()
}
)

@api.depends("partner_id")
def _compute_discount2(self):
"""Apply the default supplier discount of the selected supplier"""
for record in self:
record.discount2 = record.partner_id.default_supplierinfo_discount2

@api.depends("partner_id")
def _compute_discount3(self):
"""Apply the default supplier discount of the selected supplier"""
for record in self:
record.discount3 = record.partner_id.default_supplierinfo_discount3
def default_get(self, fields_list):
res = super().default_get(fields_list)
res.update(
{
field: self.partner_id[f"default_supplierinfo_{field}"]
for field in self._get_multiple_discount_field_names()
}
)
return res

@api.model
def _get_po_to_supplierinfo_synced_fields(self):
res = super()._get_po_to_supplierinfo_synced_fields()
res += ["discount2", "discount3"]
res += self._get_multiple_discount_field_names()
return res
74 changes: 10 additions & 64 deletions purchase_triple_discount/models/purchase_order.py
Original file line number Diff line number Diff line change
@@ -1,83 +1,29 @@
# Copyright 2017-19 Tecnativa - David Vidal
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import functools

from odoo import api, fields, models
from odoo import api, models


class PurchaseOrderLine(models.Model):
_inherit = "purchase.order.line"

# adding discount2 and discount3 to depends
@api.depends("discount2", "discount3")
def _compute_amount(self):
return super()._compute_amount()

discount2 = fields.Float(
"Disc. 2 (%)",
digits="Discount",
)

discount3 = fields.Float(
"Disc. 3 (%)",
digits="Discount",
)

_sql_constraints = [
(
"discount2_limit",
"CHECK (discount2 <= 100.0)",
"Discount 2 must be lower than 100%.",
),
(
"discount3_limit",
"CHECK (discount3 <= 100.0)",
"Discount 3 must be lower than 100%.",
),
]

def _get_discounted_price_unit(self):
# Include possible discounts 2 and 3
price_unit = super()._get_discounted_price_unit()
aggregated_discount = self._compute_aggregated_discount(self.discount)
if aggregated_discount != self.discount:
price_unit = self.price_unit * (1 - aggregated_discount / 100)
return price_unit

def _compute_aggregated_discount(self, base_discount):
self.ensure_one()
discounts = [base_discount]
for discount_fname in self._get_multiple_discount_field_names():
discounts.append(getattr(self, discount_fname, 0.0))
return self._get_aggregated_multiple_discounts(discounts)
_name = "purchase.order.line"
_inherit = ["purchase.order.line", "triple.discount.mixin"]

@api.model
def _apply_value_from_seller(self, seller):
super()._apply_value_from_seller(seller)
if not seller:
return
self.discount2 = seller.discount2
self.discount3 = seller.discount3
self.update(
{
field: seller[field]
for field in self._get_multiple_discount_field_names()
}
)

def _prepare_account_move_line(self, move=False):
self.ensure_one()
res = super()._prepare_account_move_line(move)
res.update(
{
"discount2": self.discount2,
"discount3": self.discount3,
}
{field: self[field] for field in self._get_multiple_discount_field_names()}
)
return res

def _get_aggregated_multiple_discounts(self, discounts):
discount_values = []
for discount in discounts:
discount_values.append(1 - (discount or 0.0) / 100.0)
aggregated_discount = (
1 - functools.reduce((lambda x, y: x * y), discount_values)
) * 100
return aggregated_discount

def _get_multiple_discount_field_names(self):
return ["discount2", "discount3"]
7 changes: 7 additions & 0 deletions purchase_triple_discount/models/res_partner.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
class ResPartner(models.Model):
_inherit = "res.partner"

default_supplierinfo_discount1 = fields.Float(
string="Default Supplier Discount 1 (%)",
digits="Discount",
help="This value will be used as the default one, for each new "
"supplierinfo line depending on that supplier.",
)

default_supplierinfo_discount2 = fields.Float(
string="Default Supplier Discount 2 (%)",
digits="Discount",
Expand Down
Loading