[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:
committed by
Jeremy Kersten
parent
cfe4a47702
commit
4da9533cdf
@@ -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');
|
||||
}
|
||||
|
||||
+7
-7
@@ -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)">
|
||||
|
||||
+1
-1
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user