# Copyright 2025 Criptomart # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl) from odoo import api from odoo import fields from odoo import models # Note: translation function _ is not used in this module (removed to satisfy flake8) class ProductProduct(models.Model): _inherit = "product.product" group_order_ids = fields.Many2many( "group.order", "group_order_product_rel", "product_id", "order_id", string="Group Orders", readonly=True, help="Group orders where this product is available", ) is_out_of_stock = fields.Boolean( string="Is Out of Stock", compute="_compute_stock_ribbons", store=False, help="True if qty_available <= 0", ) is_low_stock = fields.Boolean( string="Is Low Stock", compute="_compute_stock_ribbons", store=False, help="True if 0 < qty_available <= threshold", ) dynamic_ribbon_id = fields.Many2one( "product.ribbon", string="Dynamic Stock Ribbon", compute="_compute_stock_ribbons", store=False, help="Auto-assigned ribbon based on stock levels", ) @api.depends("qty_available", "type") def _compute_stock_ribbons(self): """Compute stock-based ribbons dynamically.""" # Obtener ribbons (usar sudo para evitar permisos) out_of_stock_ribbon = self.env.ref( "website_sale_aplicoop.out_of_stock_ribbon", raise_if_not_found=False ) low_stock_ribbon = self.env.ref( "website_sale_aplicoop.low_stock_ribbon", raise_if_not_found=False ) # Obtener threshold de configuración threshold = float( self.env["ir.config_parameter"] .sudo() .get_param("website_sale_aplicoop.low_stock_threshold", default="5.0") ) for product in self: # Solo para productos almacenables (type='consu' o 'product' en algunos casos) # En Odoo 18: 'consu' = Goods (almacenable), 'service' = Service, 'combo' = Combo if product.type != "consu": product.is_out_of_stock = False product.is_low_stock = False product.dynamic_ribbon_id = False continue # Lógica de stock qty = product.qty_available if qty <= 0: product.is_out_of_stock = True product.is_low_stock = False product.dynamic_ribbon_id = out_of_stock_ribbon elif qty <= threshold: product.is_out_of_stock = False product.is_low_stock = True product.dynamic_ribbon_id = low_stock_ribbon else: product.is_out_of_stock = False product.is_low_stock = False product.dynamic_ribbon_id = False # No ribbon @api.model def _get_products_for_group_order(self, order_id): """Backward-compatible delegation to `group.order` discovery. The canonical discovery logic lives on `group.order` to keep responsibilities together. Keep this wrapper so existing callers on `product.product` keep working. """ order = self.env["group.order"].browse(order_id) if not order.exists(): return self.browse() return order._get_products_for_group_order(order.id) class ProductTemplate(models.Model): _inherit = "product.template" group_order_ids = fields.Many2many( "group.order", compute="_compute_group_order_ids", string="Consumer Group Orders", readonly=True, help="Consumer group orders where variants of this product are available", ) @api.depends("product_variant_ids.group_order_ids") def _compute_group_order_ids(self): for template in self: variants = template.product_variant_ids template.group_order_ids = variants.mapped("group_order_ids")