[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:
committed by
Jeremy Kersten
parent
25153b50ef
commit
2b484317ff
@@ -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)
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user