Merge pull request #56340 from mihir-kandoi/pg-mr-supplier-distinct-orderby

fix(stock): keep supplier-based Material Request picker valid on Postgres
This commit is contained in:
Mihir Kandoi
2026-06-23 07:59:47 +05:30
committed by GitHub
2 changed files with 42 additions and 5 deletions

View File

@@ -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))
)

View File

@@ -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"):