[IMP] website_sale_stock: use free_qty instead of virtual_quantity

Replaces the forecasted quantity by the available quantity to be
coherent with Sales app.

task-2458165
Related to https://github.com/odoo/odoo/issues/68185
Part of https://github.com/odoo/odoo/pull/68221
This commit is contained in:
Younn Olivier
2021-08-09 13:10:43 +00:00
committed by Jeremy Kersten
parent cfe4a47702
commit 4da9533cdf
8 changed files with 27 additions and 28 deletions
@@ -20,7 +20,7 @@ class PaymentPortal(website_sale_controller.PaymentPortal):
for line in order.order_line:
if line.product_id.type == 'product' and line.product_id.inventory_availability in ['always', 'threshold']:
cart_qty = sum(order.order_line.filtered(lambda p: p.product_id.id == line.product_id.id).mapped('product_uom_qty'))
avl_qty = line.product_id.with_context(warehouse=order.warehouse_id.id).virtual_available
avl_qty = line.product_id.with_context(warehouse=order.warehouse_id.id).free_qty
if cart_qty > avl_qty:
values.append(_(
'You ask for %(quantity)s products but only %(available_qty)s is available',
@@ -27,10 +27,10 @@ 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()
virtual_available = product.with_context(warehouse=website.warehouse_id.id).virtual_available
free_qty = product.with_context(warehouse=website.warehouse_id.id).free_qty
combination_info.update({
'virtual_available': virtual_available,
'virtual_available_formatted': self.env['ir.qweb.field.float'].value_to_html(virtual_available, {'precision': 0}),
'free_qty': free_qty,
'free_qty_formatted': self.env['ir.qweb.field.float'].value_to_html(free_qty, {'precision': 0}),
'product_type': product.type,
'inventory_availability': product.inventory_availability,
'available_threshold': product.available_threshold,
@@ -42,7 +42,7 @@ class ProductTemplate(models.Model):
else:
product_template = self.sudo()
combination_info.update({
'virtual_available': 0,
'free_qty': 0,
'product_type': product_template.type,
'inventory_availability': product_template.inventory_availability,
'available_threshold': product_template.available_threshold,
@@ -20,8 +20,9 @@ class SaleOrder(models.Model):
# 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()
if cart_qty > line.product_id.with_context(warehouse=website.warehouse_id.id).virtual_available and (line_id == line.id):
qty = line.product_id.with_context(warehouse=website.warehouse_id.id).virtual_available - cart_qty
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
new_val = super(SaleOrder, self)._cart_update(line.product_id.id, line.id, qty, 0, **kwargs)
values.update(new_val)
@@ -48,18 +48,16 @@ VariantMixin._onChangeCombinationStock = function (ev, $parent, combination) {
$parent.find('#add_to_cart').removeClass('out_of_stock');
$parent.find('.o_we_buy_now').removeClass('out_of_stock');
if (combination.product_type === 'product' && _.contains(['always', 'threshold'], combination.inventory_availability)) {
combination.virtual_available -= parseInt(combination.cart_qty);
if (combination.virtual_available < 0) {
combination.virtual_available = 0;
combination.free_qty -= parseInt(combination.cart_qty);
if (combination.free_qty < 0) {
combination.free_qty = 0;
}
// Handle case when manually write in input
if (qty > combination.virtual_available) {
var $input_add_qty = $parent.find('input[name="add_qty"]');
qty = combination.virtual_available || 1;
$input_add_qty.val(qty);
if (qty > combination.free_qty) {
var $addQtyInput = $parent.find('input[name="add_qty"]');
qty = combination.free_qty || 1;
$addQtyInput.val(qty);
}
if (qty > combination.virtual_available
|| combination.virtual_available < 1 || qty < 1) {
if (combination.free_qty < 1) {
$parent.find('#add_to_cart').addClass('disabled out_of_stock');
$parent.find('.o_we_buy_now').addClass('disabled out_of_stock');
}
@@ -4,22 +4,22 @@
<t t-name="website_sale_stock.product_availability">
<t t-if="product_type == 'product' and _.contains(['always', 'threshold'], inventory_availability)">
<t t-if="virtual_available gt 0">
<t t-if="free_qty gt 0">
<div t-if="inventory_availability == 'always'" t-attf-class="availability_message_#{product_template} text-success mt16">
<t t-esc="virtual_available_formatted" /> <t t-esc="uom_name" /> available
<t t-esc="free_qty_formatted" /> <t t-esc="uom_name" /> available
</div>
<t t-if="inventory_availability == 'threshold'">
<div t-if="virtual_available lte available_threshold" t-attf-class="availability_message_#{product_template} text-warning mt16">
<div t-if="free_qty lte available_threshold" t-attf-class="availability_message_#{product_template} text-warning mt16">
<i class="fa fa-exclamation-triangle" title="Warning" role="img" aria-label="Warning"/>
<t t-esc="virtual_available_formatted" /> <t t-esc="uom_name" /> available
<t t-esc="free_qty_formatted" /> <t t-esc="uom_name" /> available
</div>
<div t-if="virtual_available gt available_threshold" t-attf-class="availability_message_#{product_template} text-success mt16">In stock</div>
<div t-if="free_qty gt available_threshold" t-attf-class="availability_message_#{product_template} text-success mt16">In stock</div>
</t>
</t>
<div t-if="cart_qty" t-attf-class="availability_message_#{product_template} text-warning mt8">
You already added <t t-if="!virtual_available">all</t> <t t-esc="cart_qty" /> <t t-esc="uom_name" /> in your cart.
You already added <t t-if="!free_qty">all</t> <t t-esc="cart_qty" /> <t t-esc="uom_name" /> in your cart.
</div>
<div t-if="!cart_qty and virtual_available lte 0" t-attf-class="availability_message_#{product_template} text-danger mt16"><i class="fa fa-exclamation-triangle" role="img" aria-label="Warning" title="Warning"/> Temporarily out of stock</div>
<div t-if="!cart_qty and free_qty lte 0" t-attf-class="availability_message_#{product_template} text-danger mt16"><i class="fa fa-exclamation-triangle" role="img" aria-label="Warning" title="Warning"/> Temporarily out of stock</div>
</t>
<div t-if="product_type == 'product' and inventory_availability == 'custom'" t-attf-class="availability_message_#{product_template} text-success mt16">
<t t-esc="custom_message" />
@@ -66,10 +66,10 @@ class TestWebsiteSaleStockProductWarehouse(TestWebsiteSaleProductAttributeValueC
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.")
self.assertEqual(combination_info['free_qty'], 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.")
self.assertEqual(combination_info['free_qty'], 0, "Product B should not be available in warehouse 1.")
@@ -3,7 +3,7 @@
<!-- Shopping Cart Lines -->
<template id="website_sale_stock_cart_lines" inherit_id="website_sale.cart_lines" name="Shopping Cart Lines">
<xpath expr="//input[@type='text'][hasclass('quantity')]" position="attributes">
<attribute name='t-att-data-max'>(line.product_uom_qty + (line.product_id.virtual_available - line.product_id.cart_qty)) if line.product_id.type == 'product' and line.product_id.inventory_availability in ['always', 'threshold'] else None</attribute>
<attribute name='t-att-data-max'>(line.product_uom_qty + (line.product_id.free_qty - line.product_id.cart_qty)) if line.product_id.type == 'product' and line.product_id.inventory_availability in ['always', 'threshold'] else None</attribute>
</xpath>
<xpath expr="//div[hasclass('css_quantity')]//i[hasclass('fa-plus')]/.." position="replace">
<t t-if="line._get_stock_warning(clear=False)">
@@ -2,7 +2,7 @@
<odoo>
<template id="website_sale_stock_modal" inherit_id="sale_product_configurator.product_quantity_config" name="Stocks Modal">
<xpath expr="//input[@type='text'][hasclass('quantity')]" position="attributes">
<attribute name='t-att-data-max'>max(product.sudo().virtual_available - product.cart_qty, 1) if handle_stock and product.type == "product" and product.inventory_availability in ["always", "threshold"] else None</attribute>
<attribute name='t-att-data-max'>max(product.sudo().free_qty - product.cart_qty, 1) if handle_stock and product.type == "product" and product.inventory_availability in ["always", "threshold"] else None</attribute>
</xpath>
<xpath expr="//div[hasclass('css_quantity')]" position="after">
<t t-if="handle_stock">