addons-cm/website_sale_aplicoop/models/product_extension.py

131 lines
4.5 KiB
Python

# Copyright 2025 - Today 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
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(
compute="_compute_stock_ribbons",
store=False,
help="True if virtual_available <= 0",
)
is_low_stock = fields.Boolean(
compute="_compute_stock_ribbons",
store=False,
help="True if 0 < virtual_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("virtual_available", "type", "allow_out_of_stock_order")
def _compute_stock_ribbons(self):
"""Compute stock-based ribbons dynamically.
A product is considered out of stock only when:
- It is a storable product (type='consu')
- virtual_available <= 0
- allow_out_of_stock_order is False
If allow_out_of_stock_order is True, the product can always be sold
regardless of stock level.
"""
# 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' en Odoo 18)
if product.type != "consu":
product.is_out_of_stock = False
product.is_low_stock = False
product.dynamic_ribbon_id = False
continue
qty = product.virtual_available
# Check if product allows selling when out of stock
# If True, never block add-to-cart based on stock
allow_oos = getattr(product, "allow_out_of_stock_order", True)
if qty <= 0 and not allow_oos:
# Out of stock and NOT allowed to sell without stock
product.is_out_of_stock = True
product.is_low_stock = False
product.dynamic_ribbon_id = out_of_stock_ribbon
elif qty <= 0 and allow_oos:
# Out of stock but allowed to sell anyway
product.is_out_of_stock = False
product.is_low_stock = False
product.dynamic_ribbon_id = False
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
@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")