# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from datetime import timedelta, time from odoo import fields, models, _, api from odoo.tools.float_utils import float_round class ProductProduct(models.Model): _inherit = 'product.product' sales_count = fields.Float(compute='_compute_sales_count', string='Sold', digits='Product Unit of Measure') def _compute_sales_count(self): r = {} self.sales_count = 0 if not self.user_has_groups('sales_team.group_sale_salesman'): return r date_from = fields.Datetime.to_string(fields.datetime.combine(fields.datetime.now() - timedelta(days=365), time.min)) done_states = self.env['sale.report']._get_done_states() domain = [ ('state', 'in', done_states), ('product_id', 'in', self.ids), ('date', '>=', date_from), ] for group in self.env['sale.report']._read_group(domain, ['product_id', 'product_uom_qty'], ['product_id']): r[group['product_id'][0]] = group['product_uom_qty'] for product in self: if not product.id: product.sales_count = 0.0 continue product.sales_count = float_round(r.get(product.id, 0), precision_rounding=product.uom_id.rounding) return r @api.onchange('type') def _onchange_type(self): if self._origin and self.sales_count > 0: return {'warning': { 'title': _("Warning"), 'message': _("You cannot change the product's type because it is already used in sales orders.") }} def action_view_sales(self): action = self.env["ir.actions.actions"]._for_xml_id("sale.report_all_channels_sales_action") action['domain'] = [('product_id', 'in', self.ids)] action['context'] = { 'pivot_measures': ['product_uom_qty'], 'active_id': self._context.get('active_id'), 'search_default_Sales': 1, 'active_model': 'sale.report', 'search_default_filter_order_date': 1, } return action def _get_invoice_policy(self): return self.invoice_policy def _get_combination_info_variant(self, add_qty=1, pricelist=False, parent_combination=False): """Return the variant info based on its combination. See `_get_combination_info` for more information. """ self.ensure_one() return self.product_tmpl_id._get_combination_info(self.product_template_attribute_value_ids, self.id, add_qty, pricelist, parent_combination) def _filter_to_unlink(self): domain = [('product_id', 'in', self.ids)] lines = self.env['sale.order.line']._read_group(domain, ['product_id'], ['product_id']) linked_product_ids = [group['product_id'][0] for group in lines] return super(ProductProduct, self - self.browse(linked_product_ids))._filter_to_unlink() class ProductAttributeCustomValue(models.Model): _inherit = "product.attribute.custom.value" sale_order_line_id = fields.Many2one('sale.order.line', string="Sales Order Line", required=True, ondelete='cascade') _sql_constraints = [ ('sol_custom_value_unique', 'unique(custom_product_template_attribute_value_id, sale_order_line_id)', "Only one Custom Value is allowed per Attribute Value per Sales Order Line.") ] class ProductPackaging(models.Model): _inherit = 'product.packaging' sales = fields.Boolean("Sales", default=True, help="If true, the packaging can be used for sales orders")