[FIX] stock: don't use visibility days in reordering
This reverts commit 8a5541d16caa793c7549d78c082f7879d3aba233. It's a too big change for stable. It breaks the flow for poeple that want to be in just in time but want to consider the future deliveries to order all at once. Due to reverted commit they see their reorder in advance. The fixed use case, could be achieve with the security days or the global lead days system parameter. opw-crl closes odoo/odoo#158302 X-original-commit: 51833e4735fb0b761d3cd2867dfd166813469e70 Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
This commit is contained in:
committed by
William Henrotin
parent
7e9a87388e
commit
180224ae1d
@@ -974,6 +974,59 @@ class TestReorderingRule(TransactionCase):
|
||||
self.assertNotEqual(po05, po04, 'A new PO should be generated')
|
||||
self.assertEqual(po05.order_line.product_id, product_02)
|
||||
|
||||
def test_reordering_rule_visibility_days(self):
|
||||
"""
|
||||
Test the visibility days on the reordering rule update the qty_to_order but do not
|
||||
update the forecasted quantity of the current day.
|
||||
|
||||
ex:
|
||||
- We are January 14th
|
||||
- visibility days = 10
|
||||
- A sale order is scheduled on January 20th
|
||||
-> 2 scenarios
|
||||
1. Today's forecasted quantity is < orderpoint's min qty
|
||||
the sale order will be taken into account in the forecasted quantity
|
||||
2. Todays's forecasted quantity is >= orderpoint's min qty
|
||||
the sale order will not be taken into account in the forecasted quantity
|
||||
"""
|
||||
# create reordering rule
|
||||
wh = self.env['stock.warehouse'].search([('company_id', '=', self.env.user.id)], limit=1)
|
||||
op = self.env['stock.warehouse.orderpoint'].create({
|
||||
'warehouse_id': wh.id,
|
||||
'location_id': wh.lot_stock_id.id,
|
||||
'product_id': self.product_01.id,
|
||||
'product_min_qty': 0,
|
||||
'product_max_qty': 0,
|
||||
'visibility_days': 10,
|
||||
})
|
||||
|
||||
# out move on January 20th
|
||||
move = self.env['stock.move'].create({
|
||||
'name': 'Test move',
|
||||
'product_id': self.product_01.id,
|
||||
'product_uom': self.product_01.uom_id.id,
|
||||
'product_uom_qty': 1,
|
||||
'location_id': wh.lot_stock_id.id,
|
||||
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
|
||||
'date': dt.today() + td(days=6),
|
||||
})
|
||||
move._action_confirm()
|
||||
self.assertEqual(op.qty_to_order, 0, 'sale order is ignored')
|
||||
# out move today to force the forecast to be negative
|
||||
move = self.env['stock.move'].create({
|
||||
'name': 'Test move',
|
||||
'product_id': self.product_01.id,
|
||||
'product_uom': self.product_01.uom_id.id,
|
||||
'product_uom_qty': 1,
|
||||
'location_id': wh.lot_stock_id.id,
|
||||
'location_dest_id': self.env.ref('stock.stock_location_customers').id,
|
||||
})
|
||||
move._action_confirm()
|
||||
|
||||
#virtual available is -1 but we need to replenish 2
|
||||
self.product_01.virtual_available = -1
|
||||
self.assertEqual(op.qty_to_order, 2, 'sale order is ignored')
|
||||
|
||||
def test_update_po_line_without_purchase_access_right(self):
|
||||
""" Test that a user without purchase access right can update a PO line from picking."""
|
||||
# create a user with only inventory access right
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests.common import TransactionCase, Form
|
||||
from freezegun import freeze_time
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
class TestSalePurchaseStockFlow(TransactionCase):
|
||||
|
||||
@@ -85,60 +84,3 @@ class TestSalePurchaseStockFlow(TransactionCase):
|
||||
|
||||
sm.move_line_ids.quantity = 10
|
||||
self.assertEqual(so.order_line.qty_delivered, 10)
|
||||
|
||||
@freeze_time('2024-01-01')
|
||||
def test_reordering_with_visibility_days(self):
|
||||
"""
|
||||
If reordering rules' visibility is set bigger than
|
||||
DAYS_FROM_TODAY_TO_ORDER (plus lead time). Then the
|
||||
order should be included in the calculation of quantity to order.
|
||||
|
||||
┌─ Today ┌── Scheduled Delivery
|
||||
│ (2024-01-01) │ (2024-02-01)
|
||||
│ │ aka commitment_date
|
||||
│ │
|
||||
▼ ▼
|
||||
──────────────────────────────────────────►
|
||||
time
|
||||
◄────────────────────────────►
|
||||
DAYS_FROM_TODAY_TO_ORDER
|
||||
|
||||
◄────►
|
||||
lead_time
|
||||
"""
|
||||
N_ORDERED_QTY = 666
|
||||
DAYS_FROM_TODAY_TO_ORDER = 30
|
||||
MONTH_FROM_TODAY = (datetime.today() + timedelta(days=DAYS_FROM_TODAY_TO_ORDER)).strftime('%Y-%m-%d')
|
||||
|
||||
# Setup: Create a product with vendor
|
||||
partner = self.env['res.partner'].create({'name': 'Azure Interior'})
|
||||
seller = self.env['product.supplierinfo'].create({
|
||||
'partner_id': partner.id,
|
||||
'price': 1.0,
|
||||
})
|
||||
product = self.env['product.product'].create({
|
||||
'name': 'Dummy Product',
|
||||
'type': 'product',
|
||||
'seller_ids': [seller.id],
|
||||
})
|
||||
|
||||
# Setup: Create sale order scheduled in the future
|
||||
so = self.env['sale.order'].create({
|
||||
'partner_id': self.customer.id,
|
||||
'commitment_date': MONTH_FROM_TODAY,
|
||||
'order_line': [(0, 0, {
|
||||
'name': product.name,
|
||||
'product_id': product.id,
|
||||
'price_unit': 1,
|
||||
'product_uom_qty': N_ORDERED_QTY,
|
||||
})],
|
||||
})
|
||||
so.action_confirm() # so.state: 'draft' -> 'sale'
|
||||
|
||||
# Create Reordering rule and trigger recalculation
|
||||
orderpoint_form = Form(self.env['stock.warehouse.orderpoint'])
|
||||
orderpoint_form.product_id = product
|
||||
orderpoint_form.visibility_days = DAYS_FROM_TODAY_TO_ORDER
|
||||
orderpoint = orderpoint_form.save()
|
||||
|
||||
self.assertEqual(orderpoint.qty_to_order, N_ORDERED_QTY, f"Order from {DAYS_FROM_TODAY_TO_ORDER} days from today NOT included into the qty_to_order calculation, despite having visibility days set {DAYS_FROM_TODAY_TO_ORDER}!")
|
||||
|
||||
@@ -277,11 +277,12 @@ class StockWarehouseOrderpoint(models.Model):
|
||||
continue
|
||||
qty_to_order = 0.0
|
||||
rounding = orderpoint.product_uom.rounding
|
||||
# The check is on purpose. We only want to consider the visibility days if the forecast is negative and
|
||||
# there is a already something to ressuply base on lead times.
|
||||
if float_compare(orderpoint.qty_forecast, orderpoint.product_min_qty, precision_rounding=rounding) < 0:
|
||||
# We want to know how much we should order to also satisfy the needs that gonna appear in the next (visibility) days
|
||||
product_context = orderpoint._get_product_context(visibility_days=orderpoint.visibility_days)
|
||||
qty_forecast_with_visibility = orderpoint.product_id.with_context(product_context).read(['virtual_available'])[0]['virtual_available'] + orderpoint._quantity_in_progress()[orderpoint.id]
|
||||
|
||||
if float_compare(qty_forecast_with_visibility, orderpoint.product_min_qty, precision_rounding=rounding) < 0:
|
||||
qty_to_order = max(orderpoint.product_min_qty, orderpoint.product_max_qty) - qty_forecast_with_visibility
|
||||
remainder = orderpoint.qty_multiple > 0.0 and qty_to_order % orderpoint.qty_multiple or 0.0
|
||||
if (float_compare(remainder, 0.0, precision_rounding=rounding) > 0
|
||||
|
||||
Reference in New Issue
Block a user