mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-19 11:27:55 +00:00
fix(buying): take the requested-item UOM pair off one line (#59132)
This commit is contained in:
@@ -51,7 +51,6 @@ def get_data(filters):
|
||||
mr_item.item_code.as_("item_code"),
|
||||
Sum(Coalesce(mr_item.qty, 0)).as_("qty"),
|
||||
Sum(Coalesce(mr_item.stock_qty, 0)).as_("stock_qty"),
|
||||
Max(Coalesce(mr_item.stock_uom, "")).as_("stock_uom"),
|
||||
Sum(Coalesce(mr_item.ordered_qty, 0)).as_("ordered_qty"),
|
||||
Sum(Coalesce(mr_item.received_qty, 0)).as_("received_qty"),
|
||||
(Sum(Coalesce(mr_item.stock_qty, 0)) - Sum(Coalesce(mr_item.received_qty, 0))).as_(
|
||||
@@ -78,19 +77,14 @@ def get_data(filters):
|
||||
|
||||
|
||||
def apply_representative_lines(rows):
|
||||
"""Fill item_name/description/uom from one real Material Request Item line per group.
|
||||
|
||||
All three are editable per line, so a request listing the same item twice holds several values
|
||||
per group. Aggregating them sorts text, and MariaDB folds case while PostgreSQL orders by byte
|
||||
value, so the engines pick differently. Take the first line by idx.
|
||||
"""
|
||||
"""Fill the line-level columns from one real Material Request Item line: the first by idx."""
|
||||
material_requests = list({row.material_request for row in rows})
|
||||
representative = {}
|
||||
if material_requests:
|
||||
for line in frappe.get_all(
|
||||
"Material Request Item",
|
||||
filters={"parent": ("in", material_requests), "docstatus": 1},
|
||||
fields=["parent", "item_code", "item_name", "description", "uom"],
|
||||
fields=["parent", "item_code", "item_name", "description", "uom", "stock_uom"],
|
||||
order_by="idx",
|
||||
):
|
||||
representative.setdefault((line.parent, line.item_code), line)
|
||||
@@ -100,6 +94,7 @@ def apply_representative_lines(rows):
|
||||
row.item_name = line.item_name if line else None
|
||||
row.description = line.description if line else None
|
||||
row.uom = line.uom if line else ""
|
||||
row.stock_uom = line.stock_uom if line else ""
|
||||
|
||||
|
||||
def get_conditions(filters, query, mr, mr_item):
|
||||
|
||||
@@ -74,6 +74,54 @@ class TestRequestedItemsToOrderAndReceive(ERPNextTestSuite):
|
||||
self.assertEqual(len(data), 1)
|
||||
self.assertEqual(getdate(data[0].required_date), getdate(add_days(today(), 1)))
|
||||
|
||||
def test_uom_pair_comes_from_one_line(self):
|
||||
"""uom and stock_uom describe a line, so the reported pair must be one that was posted.
|
||||
|
||||
A request can list the same item twice in different units. Sourcing each column separately
|
||||
can report one line's uom beside another's stock_uom -- a pair belonging to neither.
|
||||
"""
|
||||
create_item("Test MR Report Uom Item")
|
||||
mr = frappe.copy_doc(self.globalTestRecords["Material Request"][0])
|
||||
mr.transaction_date = today()
|
||||
mr.schedule_date = add_days(today(), 5)
|
||||
mr.set("items", mr.items[:1])
|
||||
row = mr.items[0]
|
||||
row.item_code = "Test MR Report Uom Item"
|
||||
row.item_name = "Test MR Report Uom Item"
|
||||
row.description = "Test MR Report Uom Item"
|
||||
row.uom = "Nos"
|
||||
row.schedule_date = mr.schedule_date
|
||||
mr.append(
|
||||
"items",
|
||||
{
|
||||
"item_code": "Test MR Report Uom Item",
|
||||
"item_name": "Test MR Report Uom Item",
|
||||
"description": "Test MR Report Uom Item",
|
||||
"uom": "Nos",
|
||||
"qty": row.qty,
|
||||
"warehouse": row.warehouse,
|
||||
"schedule_date": mr.schedule_date,
|
||||
},
|
||||
)
|
||||
mr.submit()
|
||||
|
||||
# cross the two picks: the line holding the higher uom holds the lower stock_uom, so an
|
||||
# independently aggregated pair cannot belong to either line
|
||||
for line, uom, stock_uom in ((mr.items[0], "Nos", "Box"), (mr.items[1], "Box", "Nos")):
|
||||
frappe.db.set_value(
|
||||
"Material Request Item",
|
||||
line.name,
|
||||
{"uom": uom, "stock_uom": stock_uom},
|
||||
update_modified=False,
|
||||
)
|
||||
|
||||
posted = {("Nos", "Box"), ("Box", "Nos")}
|
||||
data = get_data(self.filters.update({"item_code": "Test MR Report Uom Item"}))
|
||||
|
||||
self.assertEqual(len(data), 1)
|
||||
self.assertIn((data[0].uom, data[0].stock_uom), posted)
|
||||
self.assertEqual((data[0].uom, data[0].stock_uom), ("Nos", "Box"), "must be the first line by idx")
|
||||
|
||||
def setup_material_request(self, order=False, receive=False, days=0):
|
||||
po = None
|
||||
mr = frappe.copy_doc(self.globalTestRecords["Material Request"][0])
|
||||
|
||||
Reference in New Issue
Block a user