[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:
Arnold Moyaux
2024-04-05 12:18:14 +00:00
committed by William Henrotin
parent 7e9a87388e
commit 180224ae1d
3 changed files with 60 additions and 64 deletions
@@ -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}!")
+6 -5
View File
@@ -277,11 +277,12 @@ class StockWarehouseOrderpoint(models.Model):
continue
qty_to_order = 0.0
rounding = orderpoint.product_uom.rounding
# 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:
# 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]
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