diff --git a/product_pack/__manifest__.py b/product_pack/__manifest__.py index 3fbf11e9..f94b1a2a 100644 --- a/product_pack/__manifest__.py +++ b/product_pack/__manifest__.py @@ -19,7 +19,7 @@ ############################################################################## { 'name': 'Product Pack', - 'version': '11.0.1.1.0', + 'version': '11.0.1.3.0', 'category': 'Product', 'sequence': 14, 'summary': '', diff --git a/product_pack/models/product_product.py b/product_pack/models/product_product.py index 4cd9f016..92623813 100644 --- a/product_pack/models/product_product.py +++ b/product_pack/models/product_product.py @@ -67,22 +67,52 @@ def check_recursion(self): pack_lines = pack_lines.mapped('product_id.pack_line_ids') @api.multi - def price_compute(self, price_type, uom=False, currency=False, - company=False): + def separete_pack_products(self): + """ Divide the products and the pack products into two separate + recordsets. + :return: [packs, no_packs] + """ packs = self.filtered(lambda p: p.pack and p.pack_price_type in [ 'totalice_price', 'none_detailed_assited_price', 'none_detailed_totaliced_price', ]) + + # for compatibility with website_sale + if self._context.get('website_id', False) and \ + not self._context.get('from_cart', False): + packs |= self.filtered( + lambda p: p.pack and p.pack_price_type == 'components_price') + no_packs = (self | self.mapped('pack_line_ids.product_id')) - packs + return packs, no_packs + + @api.multi + def price_compute(self, price_type, uom=False, currency=False, + company=False): + packs, no_packs = self.separete_pack_products() prices = super(ProductProduct, no_packs).price_compute( price_type, uom, currency, company) for product in packs: pack_price = 0.0 for pack_line in product.pack_line_ids: - product_line_price = prices[ - pack_line.product_id.id] * ( + product_line_price = pack_line.product_id.price * ( 1 - (pack_line.discount or 0.0) / 100.0) pack_price += (product_line_price * pack_line.quantity) prices[product.id] = pack_price return prices + + @api.depends('list_price', 'price_extra') + def _compute_product_lst_price(self): + packs, no_packs = self.separete_pack_products() + super(ProductProduct, no_packs)._compute_product_lst_price() + + to_uom = None + if 'uom' in self._context: + to_uom = self.env['product.uom'].browse([self._context['uom']]) + for product in packs: + list_price = product.price_compute('list_price').get(product.id) + if to_uom: + list_price = product.uom_id._compute_price( + list_price, to_uom) + product.lst_price = list_price + product.price_extra diff --git a/product_pack/models/product_template.py b/product_pack/models/product_template.py index 307343be..0a56dbd1 100644 --- a/product_pack/models/product_template.py +++ b/product_pack/models/product_template.py @@ -39,6 +39,16 @@ class ProductTemplate(models.Model): related='product_variant_ids.used_pack_line_ids', readonly=True, ) + allow_modify_pack = fields.Boolean( + ) + + @api.onchange('pack_price_type') + def onchange_allow_modify_pack(self): + products = self.filtered( + lambda x: x.allow_modify_pack and + x.pack_price_type and x.pack_price_type != 'components_price') + for rec in products: + rec.allow_modify_pack = False @api.constrains( 'product_variant_ids', 'pack_price_type') diff --git a/product_pack/models/sale_order.py b/product_pack/models/sale_order.py index 6284c4e9..74fb303c 100644 --- a/product_pack/models/sale_order.py +++ b/product_pack/models/sale_order.py @@ -2,7 +2,8 @@ # For copyright and license notices, see __manifest__.py file in module root # directory ############################################################################## -from odoo import models, api +from odoo import models, api, _ +from odoo.exceptions import UserError class SaleOrder(models.Model): @@ -16,3 +17,15 @@ def copy(self, default=None): lambda l: l.pack_parent_line_id.order_id == self) pack_copied_lines.unlink() return sale_copy + + @api.onchange('order_line') + def check_pack_line_unlink(self): + """At least on embeded tree editable view odoo returns a recordset on + _origin.order_line only when lines are unlinked and this is exactly + what we need + """ + if self._origin.order_line.filtered('pack_parent_line_id'): + raise UserError(_( + 'You can not delete this line because is part of a pack in' + ' this sale order. In order to delete this line you need to' + ' delete the pack itself')) diff --git a/product_pack/models/sale_order_line.py b/product_pack/models/sale_order_line.py index 675d3a44..a76a7d95 100644 --- a/product_pack/models/sale_order_line.py +++ b/product_pack/models/sale_order_line.py @@ -3,6 +3,7 @@ # directory ############################################################################## from odoo import fields, models, api, _ +from odoo.exceptions import UserError class SaleOrderLine(models.Model): @@ -129,3 +130,14 @@ def _get_real_price_currency( 'fixed_price', 'totalice_price']: new_list_price = 0.0 return new_list_price, currency_id + + @api.onchange('product_id', 'product_uom_qty', 'product_uom', 'price_unit', + 'discount', 'name', 'tax_id') + def check_pack_line_modify(self): + """ Do not let to edit a sale order line if this one belongs to pack + """ + if self._origin.pack_parent_line_id and \ + not self._origin.pack_parent_line_id.product_id.allow_modify_pack: + raise UserError(_( + 'You can not change this line because is part of a pack' + ' included in this order')) diff --git a/product_pack/views/product_template_views.xml b/product_pack/views/product_template_views.xml index c18aaa77..60d13b19 100644 --- a/product_pack/views/product_template_views.xml +++ b/product_pack/views/product_template_views.xml @@ -9,6 +9,7 @@ +