fix(buying): make Procurement Tracker GROUP BY Postgres-valid

get_po_entries() grouped only by (Purchase Order, material_request_item)
while selecting other Purchase Order Item columns. MariaDB allows this
loose GROUP BY (arbitrary-picking the extra columns); Postgres rejects it
with "column ... must appear in the GROUP BY clause".

Add the Purchase Order Item PK (child.name) to the GROUP BY so the
selected child columns are functionally determined by a grouped key.

Behaviour note: this is not a MariaDB no-op. When one PO has multiple
items sharing the same/blank material_request_item, MariaDB collapsed
them into one arbitrary row; now there is one row per PO line. The
downstream report already keys rows by purchase_order, so totals are
unaffected and the per-line breakdown is more correct.

Adds a test that runs the report and asserts the PO is listed, exercising
the GROUP BY on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mihir Kandoi
2026-06-21 04:40:33 +05:30
parent 4255059846
commit 8b4845d272
2 changed files with 16 additions and 2 deletions

View File

@@ -305,7 +305,9 @@ def get_po_entries(filters):
& (parent.name == child.parent)
& (parent.status.notin(("Closed", "Completed", "Cancelled")))
)
.groupby(parent.name, child.material_request_item)
# This is one row per PO item; the selected child.* columns are only functionally dependent
# on the child PK, which postgres requires in the GROUP BY (MariaDB allows omitting it).
.groupby(parent.name, child.material_request_item, child.name)
)
query = apply_filters_on_query(filters, parent, child, query)

View File

@@ -6,4 +6,16 @@ from erpnext.tests.utils import ERPNextTestSuite
class TestProcurementTracker(ERPNextTestSuite):
pass
def test_report_executes_and_lists_po(self):
# get_po_entries groups by (Purchase Order, material_request_item, Purchase Order Item)
# while selecting other child columns; this exercises that GROUP BY so the report stays
# valid on Postgres (which rejects selecting non-grouped columns).
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.buying.report.procurement_tracker.procurement_tracker import execute
po = create_purchase_order(company="_Test Company")
columns, data = execute({"company": "_Test Company"})
self.assertTrue(columns)
self.assertIn(po.name, {row.get("purchase_order") for row in data})