From 4141fc5ab18c22f6403982f300156821dd73b18d Mon Sep 17 00:00:00 2001 From: snt Date: Thu, 5 Mar 2026 22:15:50 +0100 Subject: [PATCH] [IMP] website_sale_aplicoop: respect allow_out_of_stock_order Added website_sale_stock dependency and modified _compute_stock_ribbons to respect the allow_out_of_stock_order field: - If allow_out_of_stock_order=True: product can always be added to cart - If allow_out_of_stock_order=False and qty<=0: add-to-cart is blocked The JS logic already checks data-out-of-stock attribute from template, so no frontend changes were needed. Version bump: 18.0.1.7.0 -> 18.0.1.8.0 --- website_sale_aplicoop/__manifest__.py | 3 +- .../models/product_extension.py | 31 ++++++++++++++----- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/website_sale_aplicoop/__manifest__.py b/website_sale_aplicoop/__manifest__.py index 69bf0ba..0fb3a83 100644 --- a/website_sale_aplicoop/__manifest__.py +++ b/website_sale_aplicoop/__manifest__.py @@ -3,7 +3,7 @@ { # noqa: B018 "name": "Website Sale - Aplicoop", - "version": "18.0.1.7.0", + "version": "18.0.1.8.0", "category": "Website/Sale", "summary": "Modern replacement of legacy Aplicoop - Collaborative consumption group orders", "author": "Odoo Community Association (OCA), Criptomart", @@ -12,6 +12,7 @@ "license": "AGPL-3", "depends": [ "website_sale", + "website_sale_stock", "product", "sale", "stock", diff --git a/website_sale_aplicoop/models/product_extension.py b/website_sale_aplicoop/models/product_extension.py index defc458..f518fd1 100644 --- a/website_sale_aplicoop/models/product_extension.py +++ b/website_sale_aplicoop/models/product_extension.py @@ -41,9 +41,18 @@ class ProductProduct(models.Model): help="Auto-assigned ribbon based on stock levels", ) - @api.depends("qty_available", "type") + @api.depends("qty_available", "type", "allow_out_of_stock_order") def _compute_stock_ribbons(self): - """Compute stock-based ribbons dynamically.""" + """Compute stock-based ribbons dynamically. + + A product is considered out of stock only when: + - It is a storable product (type='consu') + - qty_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 @@ -60,21 +69,29 @@ class ProductProduct(models.Model): ) 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 + # 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 - # Lógica de stock qty = product.qty_available - if qty <= 0: + # 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 @@ -82,7 +99,7 @@ class ProductProduct(models.Model): else: product.is_out_of_stock = False product.is_low_stock = False - product.dynamic_ribbon_id = False # No ribbon + product.dynamic_ribbon_id = False @api.model def _get_products_for_group_order(self, order_id):