[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>
This commit is contained in:
Kinjal Mehta
2019-04-19 06:22:02 +00:00
committed by Jeremy Kersten
parent 25153b50ef
commit 2b484317ff
7 changed files with 102 additions and 7 deletions
@@ -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,
@@ -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}}
@@ -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)
+5 -1
View File
@@ -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
@@ -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
@@ -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.")
@@ -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>