From a2e706edf7b565a213ad95ad8fe2089bb8fc2d5b Mon Sep 17 00:00:00 2001 From: clesgow Date: Tue, 9 Nov 2021 13:53:10 +0000 Subject: [PATCH] [IMP] stock, purchase_stock: remove security lead time from picking deadline Remove the Purchase Security Lead Time from the computing of the purchase order's picking deadline to better reflect that the shipment is actually meant to arrive earlier than date + security lead time. Also makes sure that receipts and subsequent pickings (multi-step reception) are planned the earliest possible, not taking the purchase security lead time into account. Task-2656397 Part-of: odoo/odoo#79523 --- addons/purchase_stock/i18n/purchase_stock.pot | 4 ++-- addons/purchase_stock/models/purchase.py | 4 ++-- addons/purchase_stock/models/stock.py | 7 ++++++- addons/purchase_stock/models/stock_rule.py | 8 +++----- .../tests/test_purchase_lead_time.py | 16 ++++++++-------- .../views/res_config_settings_views.xml | 4 ++-- addons/stock/models/stock_orderpoint.py | 5 ++++- 7 files changed, 27 insertions(+), 21 deletions(-) diff --git a/addons/purchase_stock/i18n/purchase_stock.pot b/addons/purchase_stock/i18n/purchase_stock.pot index 51bf76987b1..67905414784 100644 --- a/addons/purchase_stock/i18n/purchase_stock.pot +++ b/addons/purchase_stock/i18n/purchase_stock.pot @@ -346,7 +346,7 @@ msgstr "" #. module: purchase_stock #: model_terms:ir.ui.view,arch_db:purchase_stock.res_config_settings_view_form_stock -msgid "Move forward expected delivery dates by" +msgid "Move forward expected request creation date by" msgstr "" #. module: purchase_stock @@ -545,7 +545,7 @@ msgstr "" #. module: purchase_stock #: model_terms:ir.ui.view,arch_db:purchase_stock.res_config_settings_view_form_stock -msgid "Schedule receivings earlier to avoid delays" +msgid "Schedule automatically generated request for quotations earlier to avoid delays" msgstr "" #. module: purchase_stock diff --git a/addons/purchase_stock/models/purchase.py b/addons/purchase_stock/models/purchase.py index 6352e27edb1..f9c0873b29e 100644 --- a/addons/purchase_stock/models/purchase.py +++ b/addons/purchase_stock/models/purchase.py @@ -389,7 +389,7 @@ class PurchaseOrderLine(models.Model): if not moves_to_update: moves_to_update = self.move_dest_ids.filtered(lambda m: m.state not in ('done', 'cancel')) for move in moves_to_update: - move.date_deadline = new_date + relativedelta(days=move.company_id.po_lead) + move.date_deadline = new_date def _create_or_update_picking(self): for line in self: @@ -498,7 +498,7 @@ class PurchaseOrderLine(models.Model): 'name': (self.name or '')[:2000], 'product_id': self.product_id.id, 'date': date_planned, - 'date_deadline': date_planned + relativedelta(days=self.order_id.company_id.po_lead), + 'date_deadline': date_planned, 'location_id': self.order_id.partner_id.property_stock_supplier.id, 'location_dest_id': (self.orderpoint_id and not (self.move_ids | self.move_dest_ids)) and self.orderpoint_id.location_id.id or self.order_id._get_destination_location(), 'picking_id': picking.id, diff --git a/addons/purchase_stock/models/stock.py b/addons/purchase_stock/models/stock.py index 108931f3dc4..c698d5ce841 100644 --- a/addons/purchase_stock/models/stock.py +++ b/addons/purchase_stock/models/stock.py @@ -3,7 +3,7 @@ from odoo import api, fields, models, _ from odoo.tools.float_utils import float_round - +from dateutil.relativedelta import relativedelta class StockPicking(models.Model): _inherit = 'stock.picking' @@ -268,6 +268,11 @@ class Orderpoint(models.Model): orderpoint_wh_supplier.route_id = route_id[0].id return super()._set_default_route_id() + def _get_orderpoint_procurement_date(self): + date = super()._get_orderpoint_procurement_date() + date -= relativedelta(days=self.company_id.po_lead) + return date + class ProductionLot(models.Model): _inherit = 'stock.production.lot' diff --git a/addons/purchase_stock/models/stock_rule.py b/addons/purchase_stock/models/stock_rule.py index e88795d36e6..2feab33b18c 100644 --- a/addons/purchase_stock/models/stock_rule.py +++ b/addons/purchase_stock/models/stock_rule.py @@ -49,7 +49,6 @@ class StockRule(models.Model): # Get the schedule date in order to find a valid seller procurement_date_planned = fields.Datetime.from_string(procurement.values['date_planned']) - schedule_date = (procurement_date_planned - relativedelta(days=procurement.company_id.po_lead)) supplier = False if procurement.values.get('supplierinfo_id'): @@ -58,7 +57,7 @@ class StockRule(models.Model): supplier = procurement.product_id.with_company(procurement.company_id.id)._select_seller( partner_id=procurement.values.get("supplierinfo_name"), quantity=procurement.product_qty, - date=schedule_date.date(), + date=procurement_date_planned.date(), uom_id=procurement.product_uom) # Fall back on a supplier for which no price may be defined. Not ideal, but better than @@ -261,7 +260,6 @@ class StockRule(models.Model): dates = [fields.Datetime.from_string(value['date_planned']) for value in values] procurement_date_planned = min(dates) - schedule_date = (procurement_date_planned - relativedelta(days=company_id.po_lead)) supplier_delay = max([int(value['supplier'].delay) for value in values]) # Since the procurements are grouped if they share the same domain for @@ -270,7 +268,7 @@ class StockRule(models.Model): # arbitrary procurement. In this case the first. values = values[0] partner = values['supplier'].partner_id - purchase_date = schedule_date - relativedelta(days=supplier_delay) + purchase_date = procurement_date_planned - relativedelta(days=supplier_delay) fpos = self.env['account.fiscal.position'].with_company(company_id).get_fiscal_position(partner.id) @@ -305,7 +303,7 @@ class StockRule(models.Model): ('user_id', '=', False), ) if values.get('orderpoint_id'): - procurement_date = fields.Date.to_date(values['date_planned']) - relativedelta(days=int(values['supplier'].delay) + company_id.po_lead) + procurement_date = fields.Date.to_date(values['date_planned']) - relativedelta(days=int(values['supplier'].delay)) delta_days = int(self.env['ir.config_parameter'].get_param('purchase_stock.delta_days_merge') or 0) domain += ( ('date_order', '<=', datetime.combine(procurement_date + relativedelta(days=delta_days), datetime.max.time())), diff --git a/addons/purchase_stock/tests/test_purchase_lead_time.py b/addons/purchase_stock/tests/test_purchase_lead_time.py index 7aa0b709b41..375cee68180 100644 --- a/addons/purchase_stock/tests/test_purchase_lead_time.py +++ b/addons/purchase_stock/tests/test_purchase_lead_time.py @@ -29,11 +29,11 @@ class TestPurchaseLeadTime(PurchaseTestCommon): purchase.button_confirm() # Check order date of purchase order - order_date = fields.Datetime.from_string(date_planned) - timedelta(days=company.po_lead) - timedelta(days=self.product_1.seller_ids.delay) + order_date = fields.Datetime.from_string(date_planned) - timedelta(days=self.product_1.seller_ids.delay) self.assertEqual(purchase.date_order, order_date, 'Order date should be equal to: Date of the procurement order - Purchase Lead Time - Delivery Lead Time.') # Check scheduled date of purchase order - schedule_date = datetime.combine(order_date + timedelta(days=self.product_1.seller_ids.delay), time.min).replace(tzinfo=None, hour=12) + schedule_date = order_date + timedelta(days=self.product_1.seller_ids.delay) self.assertEqual(purchase.order_line.date_planned, schedule_date, 'Schedule date should be equal to: Order date of Purchase order + Delivery Lead Time.') # check the picking created or not @@ -41,7 +41,7 @@ class TestPurchaseLeadTime(PurchaseTestCommon): # Check scheduled and deadline date of In Type shipment self.assertEqual(purchase.picking_ids.scheduled_date, schedule_date, 'Schedule date of In type shipment should be equal to: schedule date of purchase order.') - self.assertEqual(purchase.picking_ids.date_deadline, schedule_date + timedelta(days=company.po_lead), 'Deadline date of should be equal to: schedule date of purchase order + lead_po.') + self.assertEqual(purchase.picking_ids.date_deadline, schedule_date, 'Deadline date of should be equal to: schedule date of purchase order.') def test_01_product_level_delay(self): """ To check schedule dates of multiple purchase order line of the same purchase order, @@ -74,11 +74,11 @@ class TestPurchaseLeadTime(PurchaseTestCommon): self.assertEqual(purchase2.date_order, order_date, 'Order date should be equal to: Date of the procurement order - Delivery Lead Time.') # Check scheduled date of purchase order line for product_1 - schedule_date_1 = datetime.combine(order_date + timedelta(days=self.product_1.seller_ids.delay), time.min).replace(tzinfo=None, hour=12) + schedule_date_1 = order_date + timedelta(days=self.product_1.seller_ids.delay) self.assertEqual(order_line_pro_1.date_planned, schedule_date_1, 'Schedule date of purchase order line for product_1 should be equal to: Order date of purchase order + Delivery Lead Time of product_1.') # Check scheduled date of purchase order line for product_2 - schedule_date_2 = datetime.combine(order_date + timedelta(days=self.product_2.seller_ids.delay), time.min).replace(tzinfo=None, hour=12) + schedule_date_2 = order_date + timedelta(days=self.product_2.seller_ids.delay) self.assertEqual(order_line_pro_2.date_planned, schedule_date_2, 'Schedule date of purchase order line for product_2 should be equal to: Order date of purchase order + Delivery Lead Time of product_2.') # Check scheduled date of purchase order @@ -133,11 +133,11 @@ class TestPurchaseLeadTime(PurchaseTestCommon): purchase.button_confirm() # Check order date of purchase order - order_date = fields.Datetime.from_string(date_planned) - timedelta(days=self.product_1.seller_ids.delay + rule_delay + company.po_lead) + order_date = fields.Datetime.from_string(date_planned) - timedelta(days=self.product_1.seller_ids.delay + rule_delay) self.assertEqual(purchase.date_order, order_date, 'Order date should be equal to: Date of the procurement order - Delivery Lead Time(supplier and pull rules).') # Check scheduled date of purchase order - schedule_date = order_date + timedelta(days=self.product_1.seller_ids.delay + rule_delay + company.po_lead) + schedule_date = order_date + timedelta(days=self.product_1.seller_ids.delay + rule_delay) self.assertEqual(date_planned, str(schedule_date), 'Schedule date should be equal to: Order date of Purchase order + Delivery Lead Time(supplier and pull rules).') # Check the picking crated or not @@ -145,7 +145,7 @@ class TestPurchaseLeadTime(PurchaseTestCommon): # Check scheduled date of Internal Type shipment incoming_shipment1 = self.env['stock.picking'].search([('move_ids.product_id', 'in', (self.product_1.id, self.product_2.id)), ('picking_type_id', '=', self.warehouse_1.int_type_id.id), ('location_id', '=', self.warehouse_1.wh_input_stock_loc_id.id), ('location_dest_id', '=', self.warehouse_1.wh_qc_stock_loc_id.id)]) - incoming_shipment1_date = order_date + timedelta(days=self.product_1.seller_ids.delay + company.po_lead) + incoming_shipment1_date = order_date + timedelta(days=self.product_1.seller_ids.delay) self.assertEqual(incoming_shipment1.scheduled_date, incoming_shipment1_date, 'Schedule date of Internal Type shipment for input stock location should be equal to: schedule date of purchase order + push rule delay.') self.assertEqual(incoming_shipment1.date_deadline, incoming_shipment1_date) old_deadline1 = incoming_shipment1.date_deadline diff --git a/addons/purchase_stock/views/res_config_settings_views.xml b/addons/purchase_stock/views/res_config_settings_views.xml index 612cbb545ed..8de8626a54d 100644 --- a/addons/purchase_stock/views/res_config_settings_views.xml +++ b/addons/purchase_stock/views/res_config_settings_views.xml @@ -48,11 +48,11 @@
- Schedule receivings earlier to avoid delays + Schedule automatically generated request for quotations earlier to avoid delays
- Move forward expected delivery dates by days + Move forward expected request creation date by days
diff --git a/addons/stock/models/stock_orderpoint.py b/addons/stock/models/stock_orderpoint.py index f931a5d72a8..ef54063f088 100644 --- a/addons/stock/models/stock_orderpoint.py +++ b/addons/stock/models/stock_orderpoint.py @@ -498,7 +498,7 @@ class StockWarehouseOrderpoint(models.Model): else: origin = orderpoint.name if float_compare(orderpoint.qty_to_order, 0.0, precision_rounding=orderpoint.product_uom.rounding) == 1: - date = datetime.combine(orderpoint.lead_days_date, time.min) + date = orderpoint._get_orderpoint_procurement_date() values = orderpoint._prepare_procurement_values(date=date) procurements.append(self.env['procurement.group'].Procurement( orderpoint.product_id, orderpoint.qty_to_order, orderpoint.product_uom, @@ -551,3 +551,6 @@ class StockWarehouseOrderpoint(models.Model): def _post_process_scheduler(self): return True + + def _get_orderpoint_procurement_date(self): + return datetime.combine(self.lead_days_date, time.min)