# Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import _, api, fields, models from odoo.exceptions import ValidationError class ProductCombo(models.Model): _name = 'product.combo' _description = "Product Combo" _order = 'sequence, id' name = fields.Char(string="Name", required=True) sequence = fields.Integer(default=10, copy=False) company_id = fields.Many2one(string="Company", comodel_name='res.company', index=True) combo_item_ids = fields.One2many( comodel_name='product.combo.item', inverse_name='combo_id', copy=True, ) combo_item_count = fields.Integer(string="Product Count", compute='_compute_combo_item_count') currency_id = fields.Many2one(comodel_name='res.currency', compute='_compute_currency_id') base_price = fields.Float( string="Combo Price", help="The minimum price among the products in this combo. This value will be used to" " prorate the price of this combo with respect to the other combos in a combo product." " This heuristic ensures that whatever product the user chooses in a combo, it will" " always be the same price.", digits='Product Price', compute='_compute_base_price', ) @api.depends('combo_item_ids') def _compute_combo_item_count(self): # Initialize combo_item_count to 0 as _read_group won't return any results for new combos. self.combo_item_count = 0 # Optimization to count the number of combo items in each combo. for combo, item_count in self.env['product.combo.item']._read_group( domain=[('combo_id', 'in', self.ids)], groupby=['combo_id'], aggregates=['__count'], ): combo.combo_item_count = item_count @api.depends('company_id') def _compute_currency_id(self): main_company = self.env['res.company']._get_main_company() for combo in self: combo.currency_id = ( combo.company_id.sudo().currency_id or main_company.currency_id ) @api.depends('combo_item_ids') def _compute_base_price(self): for combo in self: combo.base_price = min(combo.combo_item_ids.mapped( lambda item: item.currency_id._convert( from_amount=item.lst_price, to_currency=combo.currency_id, company=combo.company_id or self.env.company, date=self.env.cr.now(), ) )) if combo.combo_item_ids else 0 @api.constrains('combo_item_ids') def _check_combo_item_ids_not_empty(self): if any(not combo.combo_item_ids for combo in self): raise ValidationError(_("A combo choice must contain at least 1 product.")) @api.constrains('combo_item_ids') def _check_combo_item_ids_no_duplicates(self): for combo in self: if len(combo.combo_item_ids.mapped('product_id')) < len(combo.combo_item_ids): raise ValidationError(_("A combo choice can't contain duplicate products.")) @api.constrains('company_id') def _check_company_id(self): templates = self.env['product.template'].sudo().search([('combo_ids', 'in', self.ids)]) templates._check_company(fnames=['combo_ids'])