diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index a806b5b6a31..4faa24941a0 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -12,7 +12,7 @@ import frappe.defaults from frappe import _, msgprint from frappe.model.document import Document from frappe.query_builder import Order -from frappe.query_builder.functions import Sum +from frappe.query_builder.functions import Min, Sum from frappe.utils import cint, flt, get_datetime, get_link_to_form, getdate, new_line_sep, nowdate from erpnext.buying.utils import check_on_hold_or_closed_status, validate_for_items @@ -483,9 +483,7 @@ def get_material_requests_based_on_supplier( query = ( frappe.qb.from_(mr) .from_(mr_item) - .select(mr.name) - .distinct() - .select(mr.transaction_date, mr.company) + .select(mr.name, mr.transaction_date, mr.company) .where( (mr.name == mr_item.parent) & (mr_item.item_code.isin(supplier_items)) @@ -495,7 +493,8 @@ def get_material_requests_based_on_supplier( & (mr.status != "Stopped") & (mr.company == filters.get("company")) ) - .orderby(mr_item.item_code, order=Order.asc) + .groupby(mr.name, mr.transaction_date, mr.company) + .orderby(Min(mr_item.item_code), order=Order.asc) .limit(cint(page_len)) .offset(cint(start)) ) diff --git a/erpnext/stock/doctype/material_request/test_material_request.py b/erpnext/stock/doctype/material_request/test_material_request.py index 0e1c42c0828..c6e63269c1f 100644 --- a/erpnext/stock/doctype/material_request/test_material_request.py +++ b/erpnext/stock/doctype/material_request/test_material_request.py @@ -1252,6 +1252,44 @@ class TestMaterialRequest(ERPNextTestSuite): over.items[0].qty = 4 over.validate_qty_against_so() + def test_get_material_requests_based_on_supplier(self): + """The supplier-based Material Request picker must run on every engine. + + It deduplicated requests with SELECT DISTINCT while ordering by an item + column that is not in the select list; PostgreSQL rejects that, so the + picker has to group and order by an aggregate instead. + """ + from erpnext.stock.doctype.material_request.material_request import ( + get_material_requests_based_on_supplier, + ) + + item = create_item("_Test MR Default Supplier Item") + item.set("item_defaults", []) + item.append( + "item_defaults", + { + "company": "_Test Company", + "default_warehouse": "_Test Warehouse - _TC", + "default_supplier": "_Test Supplier", + }, + ) + item.save() + + mr1 = make_material_request(item_code=item.name, qty=5) + mr2 = make_material_request(item_code=item.name, qty=7) + + result = get_material_requests_based_on_supplier( + doctype="Material Request", + txt="", + searchfield="name", + start=0, + page_len=20, + filters={"supplier": "_Test Supplier", "company": "_Test Company"}, + ) + returned = {row["name"] for row in result} + self.assertIn(mr1.name, returned) + self.assertIn(mr2.name, returned) + def get_in_transit_warehouse(company): if not frappe.db.exists("Warehouse Type", "Transit"):