Skip to content

Commit

Permalink
[WIP][FIX] product pack refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
augusto-weiss committed May 8, 2024
1 parent 60aa3e4 commit d02a480
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 34 deletions.
1 change: 1 addition & 0 deletions product_pack/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
from . import product_pack_line
from . import product_product
from . import product_template
from . import product_pricelist
3 changes: 3 additions & 0 deletions product_pack/models/product_pack_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,6 @@ def _pack_line_price_compute(
pack_line_prices[line.product_id.id] *= line.quantity

return pack_line_prices

def _compute_price(self, base_price):
return base_price * self.quantity
71 changes: 71 additions & 0 deletions product_pack/models/product_pricelist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
from odoo import models


class Pricelist(models.Model):
_inherit = "product.pricelist"

def _get_product_price(self, product, quantity, uom=None, date=False, **kwargs):
"""Compute the pricelist price for the specified product, qty & uom.
Note: self.ensure_one()
:returns: unit price of the product, considering pricelist rules
:rtype: float
"""
self.ensure_one()
if product._is_pack_to_be_handled():
pack_lines = product.sudo().pack_line_ids.mapped("product_id")
pack_line_prices = self._compute_price_rule(
pack_lines, quantity, uom=uom, date=date, **kwargs
)
pack_price = self._compute_price_rule(
product, quantity, uom=uom, date=date, **kwargs
)[product.id][0]
for line in product.sudo().pack_line_ids:
pack_price += line._compute_price(
base_price=pack_line_prices[line.product_id.id][0]
)
return pack_price
else:
return super()._get_product_price(
product=product, quantity=quantity, uom=uom, date=date, **kwargs
)

# def _get_product_price(self, product, quantity, uom=None, date=False, **kwargs):
# """Compute the pricelist price for the specified product, qty & uom.

# Note: self.ensure_one()

# :returns: unit price of the product, considering pricelist rules
# :rtype: float
# """
# self.ensure_one()
# if product._is_pack_to_be_handled():
# pack_lines = product.sudo().pack_line_ids.mapped('product_id')
# pack_line_prices = self._compute_price_rule(
# pack_lines, quantity, uom=uom, date=date, **kwargs
# )
# pack_price = self._compute_price_rule(product, quantity, uom=uom, date=date, **kwargs)[product.id][0]
# for line in product.sudo().pack_line_ids:
# pack_price += pack_line_prices[line.product_id.id][0] * line.quantity * (1 - line.sale_discount / 100.0)
# return pack_price
# else:
# return super()._get_product_price(product=product, quantity=quantity, uom=uom, date=date, **kwargs)

def _get_products_price(self, products, quantity, uom=None, date=False, **kwargs):
"""Compute the pricelist prices for the specified products, qty & uom.
Note: self.ensure_one()
:returns: dict{product_id: product price}, considering the current pricelist
:rtype: dict
"""
packs, no_packs = products.split_pack_products()
res = super()._get_products_price(
no_packs, quantity=quantity, uom=uom, date=date, **kwargs
)
for pack in packs:
res[pack.id] = self._get_product_price(
product=pack, quantity=quantity, uom=uom, date=date, **kwargs
)
return res
37 changes: 20 additions & 17 deletions product_pack/models/product_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,30 @@ def get_pack_lines(self):
can be overloaded to introduce filtering function by date, etc..."""
return self.mapped("pack_line_ids")

def _is_pack_to_be_handled(self):
return self.product_tmpl_id._is_pack_to_be_handled()

def split_pack_products(self):
packs = self.filtered(lambda p: p.product_tmpl_id._is_pack_to_be_handled())
return packs, (self - packs)

def price_compute(
self, price_type, uom=False, currency=False, company=False, date=False
):
packs, no_packs = self.split_pack_products()
# NOTE: If we want to change the price computation of the "Totalized in main
# product" and "Non detailed" packs to sum the component prices plus the main
# products price, we should call super for all the products here and sum the
# price plus the components (only for packs to be handled)
prices = super(ProductProduct, no_packs).price_compute(
price_type, uom, currency, company, date
)
for product in packs.with_context(prefetch_fields=False):
pack_line_prices = product.sudo().pack_line_ids._pack_line_price_compute(
price_type, uom, currency, company, date
)
prices[product.id] = sum(pack_line_prices.values())
return prices
# def price_compute(
# self, price_type, uom=False, currency=False, company=False, date=False
# ):
# packs, no_packs = self.split_pack_products()
# # NOTE: If we want to change the price computation of the "Totalized in main
# # product" and "Non detailed" packs to sum the component prices plus the main
# # products price, we should call super for all the products here and sum the
# # price plus the components (only for packs to be handled)
# prices = super(ProductProduct, no_packs).price_compute(
# price_type, uom, currency, company, date
# )
# for product in packs.with_context(prefetch_fields=False):
# pack_line_prices = product.sudo().pack_line_ids._pack_line_price_compute(
# price_type, uom, currency, company, date
# )
# prices[product.id] = sum(pack_line_prices.values())
# return prices

@api.depends("list_price", "price_extra")
def _compute_product_lst_price(self):
Expand Down
5 changes: 5 additions & 0 deletions sale_product_pack/models/product_pack_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ def _pack_line_price_compute(
for line in self:
pack_line_prices[line.product_id.id] *= 1 - line.sale_discount / 100.0
return pack_line_prices

def _compute_price(self, base_price):
return super()._compute_price(base_price=base_price) * (
1 - self.sale_discount / 100.0
)
14 changes: 14 additions & 0 deletions sale_product_pack/models/sale_order_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,17 @@ def _compute_discount(self):
for pack_line in self.filtered("pack_parent_line_id"):
pack_line.discount = pack_line._get_pack_line_discount()
return res

def _get_pricelist_price(self):
"""Compute the price given by the pricelist for the given line information.
:return: the product sales price in the order currency (without taxes)
:rtype: float
"""
price = super()._get_pricelist_price()

if self.product_id.product_tmpl_id._is_pack_to_be_handled():
price = self.order_id.pricelist_id._get_product_price(
product=self.product_id.product_tmpl_id, quantity=1.0
)
return price
8 changes: 4 additions & 4 deletions sale_product_pack/tests/test_sale_product_pack.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,13 @@ def test_create_totalized_price_order_line(self):
(self.sale_order.order_line - line).mapped("price_subtotal"), [0, 0, 0]
)
# Pack price is equal to the sum of component prices
self.assertAlmostEqual(line.price_subtotal, 2662.5)
self.assertAlmostEqual(line.price_subtotal, 2693.25)
self.assertAlmostEqual(self._get_component_prices_sum(product_tp), 2662.5)

# Update pricelist with a discount
self.sale_order.pricelist_id = self.discount_pricelist
self.sale_order.action_update_prices()
self.assertAlmostEqual(line.price_subtotal, 2396.25)
self.assertAlmostEqual(line.price_subtotal, 2423.93)
self.assertEqual(
(self.sale_order.order_line - line).mapped("price_subtotal"), [0, 0, 0]
)
Expand All @@ -183,13 +183,13 @@ def test_create_non_detailed_price_order_line(self):
# not a detailed one
self.assertEqual(self.sale_order.order_line, line)
# Pack price is equal to the sum of component prices
self.assertAlmostEqual(line.price_subtotal, 2662.5)
self.assertAlmostEqual(line.price_subtotal, 2693.25)
self.assertAlmostEqual(self._get_component_prices_sum(product_ndtp), 2662.5)

# Update pricelist with a discount
self.sale_order.pricelist_id = self.discount_pricelist
self.sale_order.action_update_prices()
self.assertAlmostEqual(line.price_subtotal, 2396.25)
self.assertAlmostEqual(line.price_subtotal, 2423.93)

def test_update_qty(self):
# Ensure the quantities are always updated
Expand Down
26 changes: 13 additions & 13 deletions website_sale_product_pack/models/product_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,16 @@ def check_website_published(self):

# Necessary for the website_sale_product_pack module because the price in /shop
# is calculated by the product.template.price_compute method
def price_compute(
self, price_type, uom=False, currency=False, company=False, date=False
):
templates_with_packs, templates_without_packs = self.split_pack_products()
prices = super(ProductTemplate, templates_without_packs).price_compute(
price_type, uom, currency, company, date
)
for template in templates_with_packs.with_context(prefetch_fields=False):
pack_line_prices = template.sudo().pack_line_ids._pack_line_price_compute(
price_type, uom, currency, company, date
)
prices[template.id] = sum(pack_line_prices.values())
return prices
# def price_compute(
# self, price_type, uom=False, currency=False, company=False, date=False
# ):
# templates_with_packs, templates_without_packs = self.split_pack_products()
# prices = super(ProductTemplate, templates_without_packs).price_compute(
# price_type, uom, currency, company, date
# )
# for template in templates_with_packs.with_context(prefetch_fields=False):
# pack_line_prices = template.sudo().pack_line_ids._pack_line_price_compute(
# price_type, uom, currency, company, date
# )
# prices[template.id] = sum(pack_line_prices.values())
# return prices

0 comments on commit d02a480

Please sign in to comment.