diff --git a/addons/website_sale_stock/models/product_template.py b/addons/website_sale_stock/models/product_template.py index ee8ea1e3ac3..ed39cdd0659 100644 --- a/addons/website_sale_stock/models/product_template.py +++ b/addons/website_sale_stock/models/product_template.py @@ -27,8 +27,9 @@ class ProductTemplate(models.Model): if combination_info['product_id']: product = self.env['product.product'].sudo().browse(combination_info['product_id']) + website = self.env['website'].get_current_website() combination_info.update({ - 'virtual_available': product.virtual_available, + 'virtual_available': product.with_context(warehouse=website.warehouse_id.id).virtual_available, 'product_type': product.type, 'inventory_availability': product.inventory_availability, 'available_threshold': product.available_threshold, diff --git a/addons/website_sale_stock/models/res_config_settings.py b/addons/website_sale_stock/models/res_config_settings.py index 73b02412726..51b05aa01ae 100644 --- a/addons/website_sale_stock/models/res_config_settings.py +++ b/addons/website_sale_stock/models/res_config_settings.py @@ -10,10 +10,11 @@ class ResConfigSettings(models.TransientModel): inventory_availability = fields.Selection([ ('never', 'Sell regardless of inventory'), ('always', 'Show inventory on website and prevent sales if not enough stock'), - ('threshold', 'Show inventory below a threshold and prevent sales if not enough stock'), + ('threshold', 'Show inventory when below the threshold and prevent sales if not enough stock'), ('custom', 'Show product-specific notifications'), ], string='Inventory Availability', default='never') available_threshold = fields.Float(string='Availability Threshold') + website_warehouse_id = fields.Many2one('stock.warehouse', related='website_id.warehouse_id', domain="[('company_id', '=', website_company_id)]", readonly=False) @api.multi def set_values(self): @@ -29,3 +30,8 @@ class ResConfigSettings(models.TransientModel): res.update(inventory_availability=IrDefault.get('product.template', 'inventory_availability') or 'never', available_threshold=IrDefault.get('product.template', 'available_threshold') or 5.0) return res + + @api.onchange('website_company_id') + def _onchange_website_company_id(self): + if self.website_warehouse_id.company_id != self.website_company_id: + return {'value': {'website_warehouse_id': False}} diff --git a/addons/website_sale_stock/models/sale_order.py b/addons/website_sale_stock/models/sale_order.py index 2896163c673..060577c8e80 100644 --- a/addons/website_sale_stock/models/sale_order.py +++ b/addons/website_sale_stock/models/sale_order.py @@ -17,8 +17,8 @@ class SaleOrder(models.Model): for line in self.order_line: if line.product_id.type == 'product' and line.product_id.inventory_availability in ['always', 'threshold']: cart_qty = sum(self.order_line.filtered(lambda p: p.product_id.id == line.product_id.id).mapped('product_uom_qty')) - if cart_qty > line.product_id.virtual_available and (line_id == line.id): - qty = line.product_id.virtual_available - cart_qty + if cart_qty > line.product_id.with_context(warehouse=self.warehouse_id.id).virtual_available and (line_id == line.id): + qty = line.product_id.with_context(warehouse=self.warehouse_id.id).virtual_available - 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/models/website.py b/addons/website_sale_stock/models/website.py index bee131093b7..e9730cffed0 100644 --- a/addons/website_sale_stock/models/website.py +++ b/addons/website_sale_stock/models/website.py @@ -1,15 +1,19 @@ # -*- coding: utf-8 -*- -from odoo import api, models +from odoo import api, fields, models + class Website(models.Model): _inherit = 'website' + warehouse_id = fields.Many2one('stock.warehouse', string='Warehouse') + @api.multi def _prepare_sale_order_values(self, partner, pricelist): self.ensure_one() values = super(Website, self)._prepare_sale_order_values(partner, pricelist) if values['company_id']: warehouse_id = ( + self.warehouse_id and self.warehouse_id.id or self.env['ir.default'].get('sale.order', 'warehouse_id', company_id=values.get('company_id')) or self.env['ir.default'].get('sale.order', 'warehouse_id') or self.env['stock.warehouse'].sudo().search([('company_id', '=', values['company_id'])], limit=1).id diff --git a/addons/website_sale_stock/tests/__init__.py b/addons/website_sale_stock/tests/__init__.py new file mode 100644 index 00000000000..778ed8c0ec7 --- /dev/null +++ b/addons/website_sale_stock/tests/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from . import test_website_sale_stock_product_warehouse 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 new file mode 100644 index 00000000000..9ae58e320f0 --- /dev/null +++ b/addons/website_sale_stock/tests/test_website_sale_stock_product_warehouse.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo.addons.website_sale.tests.test_website_sale_product_attribute_value_config import TestWebsiteSaleProductAttributeValueConfig + + +class TestWebsiteSaleStockProductWarehouse(TestWebsiteSaleProductAttributeValueConfig): + + def test_get_combination_info(self): + """ Checked that correct product quantity is shown in website according to the warehouse + which is set in current website. + - Create two warehouse + - Create two stockable products + - Update quantity of Product A in Warehouse 1 + - Update quantity of Product B in Warehouse 2 + - Set Warehouse 1 in website + - Check available quantity of Product A and Product B in website + Product A should be available in the website as it is available in warehouse 1 but Product B + should not be available in website as it is stored in warehouse 2. + """ + # Create two warehouses + warehouse_1 = self.env['stock.warehouse'].create({ + 'name': 'Warehouse 1', + 'code': 'WH1' + }) + warehouse_2 = self.env['stock.warehouse'].create({ + 'name': 'Warehouse 2', + 'code': 'WH2' + }) + + # Create two stockable products + product_1 = self.env['product.product'].create({ + 'name': 'Product A', + 'inventory_availability': 'always', + 'type': 'product', + 'default_code': 'E-COM1', + }) + + product_2 = self.env['product.product'].create({ + 'name': 'Product B', + 'inventory_availability': 'always', + 'type': 'product', + 'default_code': 'E-COM2', + }) + + # Update quantity of Product A in Warehouse 1 + inventory_wizard = self.env['stock.change.product.qty'].create({ + 'product_id': product_1.id, + 'new_quantity': 10.0, + 'location_id': warehouse_1.lot_stock_id.id, + }) + inventory_wizard.change_product_qty() + + # Update quantity of Product B in Warehouse 2 + inventory_wizard = self.env['stock.change.product.qty'].create({ + 'product_id': product_2.id, + 'new_quantity': 10.0, + 'location_id': warehouse_2.lot_stock_id.id, + }) + inventory_wizard.change_product_qty() + + # Get current website and set warehouse_id of Warehouse 1 + current_website = self.env['website'].get_current_website() + current_website.warehouse_id = warehouse_1 + + product = product_1.with_context(website_id=current_website.id) + combination_info = product.product_tmpl_id.with_context(website_sale_stock_get_quantity=True)._get_combination_info() + + # Check available quantity of product is according to warehouse + self.assertEqual(combination_info['virtual_available'], 10, "10 units of Product A should be available in warehouse 1.") + + product = product_2.with_context(website_id=current_website.id) + combination_info = product.product_tmpl_id.with_context(website_sale_stock_get_quantity=True)._get_combination_info() + + # Check available quantity of product is according to warehouse + self.assertEqual(combination_info['virtual_available'], 0, "Product B should not be available in warehouse 1.") diff --git a/addons/website_sale_stock/views/res_config_settings_views.xml b/addons/website_sale_stock/views/res_config_settings_views.xml index 1bbd33ef454..58dd9ce059f 100644 --- a/addons/website_sale_stock/views/res_config_settings_views.xml +++ b/addons/website_sale_stock/views/res_config_settings_views.xml @@ -12,12 +12,16 @@
+
+
-

-