details: https://code.tryton.org/tryton/commit/21cb53f6b5ba
branch: default
user: Cédric Krier <[email protected]>
date: Tue Nov 11 18:04:50 2025 +0100
description:
Use the fastest product supplier when anyone can supply on time
Closes #12806
diffstat:
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 deletions(-)
diffs (107 lines):
diff -r e0d1ee7e0c9f -r 21cb53f6b5ba modules/purchase_request/CHANGELOG
--- a/modules/purchase_request/CHANGELOG Tue Oct 21 12:07:40 2025 +0200
+++ b/modules/purchase_request/CHANGELOG Tue Nov 11 18:04:50 2025 +0100
@@ -1,3 +1,4 @@
+* Use the fastest product supplier when anyone can supply on time
Version 7.6.0 - 2025-04-28
--------------------------
diff -r e0d1ee7e0c9f -r 21cb53f6b5ba
modules/purchase_request/purchase_request.py
--- a/modules/purchase_request/purchase_request.py Tue Oct 21 12:07:40
2025 +0200
+++ b/modules/purchase_request/purchase_request.py Tue Nov 11 18:04:50
2025 +0100
@@ -298,6 +298,7 @@
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 @@
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 -r e0d1ee7e0c9f -r 21cb53f6b5ba
modules/purchase_request/tests/test_module.py
--- a/modules/purchase_request/tests/test_module.py Tue Oct 21 12:07:40
2025 +0200
+++ b/modules/purchase_request/tests/test_module.py Tue Nov 11 18:04:50
2025 +0100
@@ -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