mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-14 15:11:52 +00:00
fix: replace column-literal work order filter with server-side query
The work_order link filter in Stock Entry passed the string `tabWork Order`.produced_qty as a filter value. It was never a real column comparison: db_query coerces string values on numeric fields with flt(), so the condition silently degraded to qty > 0, and on backends that don't coerce text to numeric (postgres) such filters fail with InvalidTextRepresentation. Move the condition into a whitelisted search query that compares the columns properly (qty > produced_qty), mirroring pick_list's get_pending_work_orders.
This commit is contained in:
@@ -21,11 +21,10 @@ frappe.ui.form.on("Stock Entry", {
|
||||
|
||||
frm.set_query("work_order", function () {
|
||||
return {
|
||||
filters: [
|
||||
["Work Order", "docstatus", "=", 1],
|
||||
["Work Order", "qty", ">", "`tabWork Order`.produced_qty"],
|
||||
["Work Order", "company", "=", frm.doc.company],
|
||||
],
|
||||
query: "erpnext.stock.doctype.stock_entry.stock_entry.get_pending_work_orders",
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -1577,6 +1577,28 @@ def make_stock_in_entry(source_name: str, target_doc: str | Document | None = No
|
||||
return doclist
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
@frappe.validate_and_sanitize_search_inputs
|
||||
def get_pending_work_orders(
|
||||
doctype: str, txt: str, searchfield: str, start: int, page_length: int, filters: dict
|
||||
) -> list:
|
||||
work_order = frappe.qb.DocType("Work Order")
|
||||
query = frappe.qb.get_query(
|
||||
"Work Order",
|
||||
fields=["name", "production_item"],
|
||||
filters={
|
||||
"docstatus": 1,
|
||||
"company": filters.get("company"),
|
||||
"name": ("like", f"%{txt}%"),
|
||||
},
|
||||
order_by="name",
|
||||
limit=cint(page_length),
|
||||
offset=cint(start),
|
||||
ignore_permissions=False,
|
||||
)
|
||||
return query.where(work_order.qty > work_order.produced_qty).run()
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_work_order_details(work_order: str, company: str):
|
||||
work_order = frappe.get_doc("Work Order", work_order)
|
||||
|
||||
@@ -26,7 +26,11 @@ from erpnext.stock.doctype.serial_and_batch_bundle.test_serial_and_batch_bundle
|
||||
make_serial_batch_bundle,
|
||||
)
|
||||
from erpnext.stock.doctype.serial_no.serial_no import *
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import FinishedGoodError, make_stock_in_entry
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry import (
|
||||
FinishedGoodError,
|
||||
get_pending_work_orders,
|
||||
make_stock_in_entry,
|
||||
)
|
||||
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
|
||||
from erpnext.stock.doctype.stock_ledger_entry.stock_ledger_entry import StockFreezeError
|
||||
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import (
|
||||
@@ -3392,6 +3396,24 @@ class TestStockEntryCoverage(ERPNextTestSuite):
|
||||
for bn in list(get_batches_from_bundle(row.serial_and_batch_bundle).keys()):
|
||||
self.assertIn(bn, wo1_batches)
|
||||
|
||||
def test_get_pending_work_orders(self):
|
||||
from erpnext.manufacturing.doctype.work_order.test_work_order import make_wo_order_test_record
|
||||
|
||||
wo = make_wo_order_test_record(qty=2, skip_transfer=True)
|
||||
|
||||
def pending_work_orders(txt=""):
|
||||
return [
|
||||
row[0]
|
||||
for row in get_pending_work_orders("Work Order", txt, "name", 0, 0, {"company": wo.company})
|
||||
]
|
||||
|
||||
self.assertIn(wo.name, pending_work_orders())
|
||||
self.assertIn(wo.name, pending_work_orders(wo.name.lower()))
|
||||
self.assertNotIn(wo.name, pending_work_orders("no-such-work-order"))
|
||||
|
||||
frappe.db.set_value("Work Order", wo.name, "produced_qty", wo.qty)
|
||||
self.assertNotIn(wo.name, pending_work_orders())
|
||||
|
||||
|
||||
def make_serialized_item(self, **args):
|
||||
args = frappe._dict(args)
|
||||
|
||||
Reference in New Issue
Block a user