diff options
| author | Kinjal Mehta <kme@odoo.com> | 2018-12-12 10:28:27 +0000 |
|---|---|---|
| committer | Jeremy Kersten <jke@odoo.com> | 2019-04-19 06:22:02 +0000 |
| commit | 2b484317ff01160dbfebc69fada654aecf594f87 (patch) | |
| tree | 95f0b1ded56bcfc9c90a7d9c14aed07dd8b34beb /addons | |
| parent | 25153b50efd5fe7c005482018a0c460acb6f0599 (diff) | |
[ADD] website_sale_stock: allow to set warehouse on the website.
Purpose: Add option to set a default warehouse on the website.
Before this: We are showing all quantity of product for specific company not
specific warehouse.
After this: We will see availability of product based on warehouse set on the
website.
task-1913031
closes odoo/odoo#30104
Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
Diffstat (limited to 'addons')
7 files changed, 102 insertions, 7 deletions
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 @@ <xpath expr="//div[@name='stock_inventory_availability']" position="inside"> <div class="content-group"> + <div class="row mt16" attrs="{'invisible': [('group_stock_multi_warehouses', '=', False)]}"> + <label for="website_warehouse_id" string="Warehouse" class="col-lg-3 o_light_label" /> + <field name="website_warehouse_id"/> + </div> <div class="row mt16" title="Default availability mode set on newly created storable products. This can be changed at the product level."> - <label for="inventory_availability" string="Default Mode" class="col-lg-3 o_light_label" /> + <label for="inventory_availability" string="Mode" class="col-lg-3 o_light_label" /> <field name="inventory_availability" string="Inventory"/> </div><br/> <div class="row" attrs="{'invisible': [('inventory_availability', '!=', 'threshold')]}"> - <label for="available_threshold" string="Default threshold" class="col-lg-3 o_light_label" /> + <label for="available_threshold" string="Threshold" class="col-lg-3 o_light_label" /> <field name="available_threshold" class="oe_inline" attrs="{'required': [('inventory_availability', '=', 'threshold')]}"/> </div> </div> |
