From 4a17e8007065e3ce98debd587fef7b0e9dfdb9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Tue, 11 Nov 2025 18:04:50 +0100 Subject: [PATCH] Use the fastest product supplier when anyone can supply on time Closes #12806 --- modules/purchase_request/CHANGELOG | 1 + modules/purchase_request/purchase_request.py | 4 ++ modules/purchase_request/tests/test_module.py | 63 ++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/modules/purchase_request/CHANGELOG b/modules/purchase_request/CHANGELOG index 770aa8718b..a0ce40d4c6 100644 --- a/modules/purchase_request/CHANGELOG +++ b/modules/purchase_request/CHANGELOG @@ -1,3 +1,4 @@ +* Use the fastest product supplier when anyone can supply on time Version 7.6.0 - 2025-04-28 -------------------------- diff --git a/modules/purchase_request/purchase_request.py b/modules/purchase_request/purchase_request.py index 69334d1804..e74e74a81e 100644 --- a/modules/purchase_request/purchase_request.py +++ b/modules/purchase_request/purchase_request.py @@ -298,6 +298,7 @@ class PurchaseRequest(ModelSQL, ModelView): Date = pool.get('ir.date') with Transaction().set_context(context=product._context): today = Date.today() + earlier_date, fastest = datetime.date.max, None for product_supplier in product.product_suppliers_used(**pattern): if date is None: return product_supplier @@ -305,6 +306,9 @@ class PurchaseRequest(ModelSQL, ModelView): timedelta = date - supply_date if timedelta >= datetime.timedelta(0): return product_supplier + if supply_date < earlier_date or earlier_date is datetime.date.max: + earlier_date, fastest = supply_date, product_supplier + return fastest @classmethod def find_best_supplier(cls, product, date, **pattern): diff --git a/modules/purchase_request/tests/test_module.py b/modules/purchase_request/tests/test_module.py index 492ca895b5..55fd8d905a 100644 --- a/modules/purchase_request/tests/test_module.py +++ b/modules/purchase_request/tests/test_module.py @@ -1,12 +1,73 @@ # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. -from trytond.tests.test_tryton import ModuleTestCase +import datetime as dt + +from trytond.modules.company.tests import create_company, set_company +from trytond.pool import Pool +from trytond.tests.test_tryton import ModuleTestCase, with_transaction class PurchaseRequestTestCase(ModuleTestCase): 'Test Purchase Request module' module = 'purchase_request' + @with_transaction() + def test_find_best_product_supplier(self): + "Test finding best product supplier" + pool = Pool() + ProductTemplate = pool.get('product.template') + Product = pool.get('product.product') + ProductSupplier = pool.get('purchase.product_supplier') + Party = pool.get('party.party') + UoM = pool.get('product.uom') + PurchaseRequest = pool.get('purchase.request') + Date = pool.get('ir.date') + + supplier = Party(name="Supplier") + supplier.save() + + company = create_company() + with set_company(company): + unit, = UoM.search([('name', '=', "Unit")]) + template = ProductTemplate(name="Product") + template.purchasable = True + template.default_uom = unit + template.purchase_uom = unit + template.save() + product = Product(template=template) + product.save() + + product_supplier1 = ProductSupplier( + template=template, party=supplier, + lead_time=dt.timedelta(days=5)) + product_supplier1.save() + product_supplier2 = ProductSupplier( + template=template, party=supplier, + lead_time=dt.timedelta(days=2)) + product_supplier2.save() + product_supplier3 = ProductSupplier( + template=template, party=supplier, + lead_time=dt.timedelta(days=3)) + product_supplier3.save() + + today = Date.today() + for date, product_supplier in [ + (None, product_supplier1), + (today, product_supplier2), + (today + dt.timedelta(days=1), product_supplier2), + (today + dt.timedelta(days=2), product_supplier2), + (today + dt.timedelta(days=3), product_supplier2), + (today + dt.timedelta(days=4), product_supplier2), + (today + dt.timedelta(days=5), product_supplier1), + (dt.date.max, product_supplier1), + (dt.date.min, product_supplier2), + ]: + with self.subTest(date=date): + self.assertEqual( + PurchaseRequest.find_best_product_supplier( + product, date), + product_supplier) + del ModuleTestCase