79 lines
3.3 KiB
Python
79 lines
3.3 KiB
Python
# 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'])
|