diff --git a/addons/website_sale_stock/models/sale_order.py b/addons/website_sale_stock/models/sale_order.py index 0a8e85905ae..961f35ef0fc 100644 --- a/addons/website_sale_stock/models/sale_order.py +++ b/addons/website_sale_stock/models/sale_order.py @@ -17,12 +17,8 @@ class SaleOrder(models.Model): for line in self.order_line: if line.product_id.type == 'product' and not line.product_id.allow_out_of_stock_order: cart_qty = sum(self.order_line.filtered(lambda p: p.product_id.id == line.product_id.id).mapped('product_uom_qty')) - # The quantity should be computed based on the warehouse of the website, not the - # warehouse of the SO. - website = self.env['website'].get_current_website() - avl_qty = line.product_id.with_context(warehouse=website.warehouse_id.id).free_qty - if cart_qty > avl_qty and (line_id == line.id): - qty = avl_qty - cart_qty + if cart_qty > line.product_id.with_context(warehouse=self.warehouse_id.id).free_qty and (line_id == line.id): + qty = line.product_id.with_context(warehouse=self.warehouse_id.id).free_qty - cart_qty new_val = super(SaleOrder, self)._cart_update(line.product_id.id, line.id, qty, 0, **kwargs) values.update(new_val) diff --git a/addons/website_sale_stock/tests/test_website_sale_stock_product_warehouse.py b/addons/website_sale_stock/tests/test_website_sale_stock_product_warehouse.py index e7a2aca8bb3..cc792581911 100644 --- a/addons/website_sale_stock/tests/test_website_sale_stock_product_warehouse.py +++ b/addons/website_sale_stock/tests/test_website_sale_stock_product_warehouse.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo.addons.website.tools import MockRequest from odoo.addons.sale.tests.test_sale_product_attribute_value_config import TestSaleProductAttributeValueCommon from odoo.tests import tagged @@ -9,31 +10,31 @@ from odoo.tests import tagged class TestWebsiteSaleStockProductWarehouse(TestSaleProductAttributeValueCommon): @classmethod - def setUpClass(self): + def setUpClass(cls): super().setUpClass() # Run the tests in another company, so the tests do not rely on the # database state (eg the default company's warehouse) - self.company = self.env['res.company'].create({'name': 'Company C'}) - self.env.user.company_id = self.company - self.website = self.env['website'].create({'name': 'Website Company C'}) - self.website.company_id = self.company + cls.company = cls.env['res.company'].create({'name': 'Company C'}) + cls.env.user.company_id = cls.company + cls.website = cls.env['website'].create({'name': 'Website Company C'}) + cls.website.company_id = cls.company # Set two warehouses (one was created on company creation) - self.warehouse_1 = self.env['stock.warehouse'].search([('company_id', '=', self.company.id)]) - self.warehouse_2 = self.env['stock.warehouse'].create({ + cls.warehouse_1 = cls.env['stock.warehouse'].search([('company_id', '=', cls.company.id)]) + cls.warehouse_2 = cls.env['stock.warehouse'].create({ 'name': 'Warehouse 2', 'code': 'WH2' }) # Create two stockable products - self.product_A = self.env['product.product'].create({ + cls.product_A = cls.env['product.product'].create({ 'name': 'Product A', 'allow_out_of_stock_order': False, 'type': 'product', 'default_code': 'E-COM1', }) - self.product_B = self.env['product.product'].create({ + cls.product_B = cls.env['product.product'].create({ 'name': 'Product B', 'allow_out_of_stock_order': False, 'type': 'product', @@ -41,17 +42,17 @@ class TestWebsiteSaleStockProductWarehouse(TestSaleProductAttributeValueCommon): }) # Add 10 Product A in WH1 and 15 Product 1 in WH2 - quants = self.env['stock.quant'].with_context(inventory_mode=True).create([{ - 'product_id': self.product_A.id, + quants = cls.env['stock.quant'].with_context(inventory_mode=True).create([{ + 'product_id': cls.product_A.id, 'inventory_quantity': qty, 'location_id': wh.lot_stock_id.id, - } for wh, qty in [(self.warehouse_1, 10.0), (self.warehouse_2, 15.0)]]) + } for wh, qty in [(cls.warehouse_1, 10.0), (cls.warehouse_2, 15.0)]]) # Add 10 Product 2 in WH2 - quants |= self.env['stock.quant'].with_context(inventory_mode=True).create({ - 'product_id': self.product_B.id, + quants |= cls.env['stock.quant'].with_context(inventory_mode=True).create({ + 'product_id': cls.product_B.id, 'inventory_quantity': 10.0, - 'location_id': self.warehouse_2.lot_stock_id.id, + 'location_id': cls.warehouse_2.lot_stock_id.id, }) quants.action_apply_inventory() @@ -79,3 +80,24 @@ class TestWebsiteSaleStockProductWarehouse(TestSaleProductAttributeValueCommon): # Check available quantity of product is according to warehouse self.assertEqual(combination_info['free_qty'], qty_b, "%s units of Product B should be available in warehouse %s" % (qty_b, wh)) + + def test_02_update_cart_with_multi_warehouses(self): + """ When the user updates his cart and increases a product quantity, if + this quantity is not available in the SO's warehouse, a warning should + be returned and the quantity updated to its maximum. """ + + so = self.env['sale.order'].create({ + 'partner_id': self.env.user.partner_id.id, + 'order_line': [(0, 0, { + 'name': self.product_A.name, + 'product_id': self.product_A.id, + 'product_uom_qty': 5, + 'product_uom': self.product_A.uom_id.id, + 'price_unit': self.product_A.list_price, + })] + }) + + with MockRequest(self.env, website=self.website, sale_order_id=so.id): + values = so._cart_update(product_id=self.product_A.id, line_id=so.order_line.id, set_qty=20) + self.assertTrue(values.get('warning', False)) + self.assertEqual(values.get('quantity'), 10)