mirror of
https://github.com/frappe/erpnext.git
synced 2026-09-19 11:27:55 +00:00
refactor(postgres): port maintenance_schedule queries to the query builder
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -185,9 +185,7 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
else:
|
else:
|
||||||
holiday_list = frappe.get_cached_value("Company", self.company, "default_holiday_list")
|
holiday_list = frappe.get_cached_value("Company", self.company, "default_holiday_list")
|
||||||
|
|
||||||
holidays = frappe.db.sql_list(
|
holidays = frappe.get_all("Holiday", filters={"parent": holiday_list}, pluck="holiday_date")
|
||||||
"""select holiday_date from `tabHoliday` where parent=%s""", holiday_list
|
|
||||||
)
|
|
||||||
|
|
||||||
if not validated and holidays:
|
if not validated and holidays:
|
||||||
# max iterations = len(holidays)
|
# max iterations = len(holidays)
|
||||||
@@ -235,16 +233,22 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
throw(_("Start date should be less than end date for Item {0}").format(d.item_code))
|
throw(_("Start date should be less than end date for Item {0}").format(d.item_code))
|
||||||
|
|
||||||
def validate_sales_order(self):
|
def validate_sales_order(self):
|
||||||
|
ms = frappe.qb.DocType("Maintenance Schedule")
|
||||||
|
msi = frappe.qb.DocType("Maintenance Schedule Item")
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.sales_order:
|
if d.sales_order:
|
||||||
chk = frappe.db.sql(
|
# filter the parent schedule's docstatus (matches the original ms.docstatus = 1)
|
||||||
"""select ms.name from `tabMaintenance Schedule` ms,
|
chk = (
|
||||||
`tabMaintenance Schedule Item` msi where msi.parent=ms.name and
|
frappe.qb.from_(ms)
|
||||||
msi.sales_order=%s and ms.docstatus=1""",
|
.inner_join(msi)
|
||||||
d.sales_order,
|
.on(msi.parent == ms.name)
|
||||||
|
.select(ms.name)
|
||||||
|
.where((msi.sales_order == d.sales_order) & (ms.docstatus == 1))
|
||||||
|
.limit(1)
|
||||||
|
.run(pluck=True)
|
||||||
)
|
)
|
||||||
if chk:
|
if chk:
|
||||||
throw(_("Maintenance Schedule {0} exists against {1}").format(chk[0][0], d.sales_order))
|
throw(_("Maintenance Schedule {0} exists against {1}").format(chk[0], d.sales_order))
|
||||||
|
|
||||||
def validate_items_table_change(self):
|
def validate_items_table_change(self):
|
||||||
doc_before_save = self.get_doc_before_save()
|
doc_before_save = self.get_doc_before_save()
|
||||||
|
|||||||
@@ -168,6 +168,51 @@ class TestMaintenanceSchedule(ERPNextTestSuite):
|
|||||||
ms.save()
|
ms.save()
|
||||||
self.assertEqual(len(ms.schedules), 2)
|
self.assertEqual(len(ms.schedules), 2)
|
||||||
|
|
||||||
|
def test_validate_sales_order_duplicate_throws(self):
|
||||||
|
# validate_sales_order joins Maintenance Schedule + its item filtering the PARENT schedule's
|
||||||
|
# docstatus=1; a second schedule against a Sales Order already used by a submitted schedule
|
||||||
|
# must be rejected.
|
||||||
|
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||||
|
|
||||||
|
so = make_sales_order()
|
||||||
|
first = make_maintenance_schedule(sales_order=so.name)
|
||||||
|
self.assertEqual(first.items[0].sales_order, so.name)
|
||||||
|
first.submit()
|
||||||
|
|
||||||
|
self.assertRaises(frappe.ValidationError, make_maintenance_schedule, sales_order=so.name)
|
||||||
|
|
||||||
|
def test_validate_schedule_date_skips_holiday(self):
|
||||||
|
# validate_schedule_date_for_holiday_list reads the holiday list via the converted
|
||||||
|
# get_all("Holiday", {"parent": <list>}, pluck="holiday_date") and shifts a schedule date
|
||||||
|
# that lands on a holiday back by a day; a non-holiday date is returned unchanged.
|
||||||
|
from frappe.utils import getdate
|
||||||
|
|
||||||
|
from erpnext.setup.doctype.holiday_list.test_holiday_list import make_holiday_list
|
||||||
|
|
||||||
|
holiday = add_days(today(), 5)
|
||||||
|
hl = make_holiday_list(
|
||||||
|
"_Test MS Holidays " + frappe.generate_hash("", 6),
|
||||||
|
from_date=today(),
|
||||||
|
to_date=add_days(today(), 10),
|
||||||
|
holiday_dates=[{"holiday_date": holiday, "description": "Test Holiday"}],
|
||||||
|
)
|
||||||
|
|
||||||
|
ms = make_maintenance_schedule()
|
||||||
|
# a Sales Person with no linked employee routes to the company-default-holiday-list branch
|
||||||
|
sp = frappe.get_doc(
|
||||||
|
{"doctype": "Sales Person", "sales_person_name": "_Test MS SP " + frappe.generate_hash("", 5)}
|
||||||
|
).insert(ignore_permissions=True)
|
||||||
|
frappe.db.set_value("Company", ms.company, "default_holiday_list", hl.name)
|
||||||
|
|
||||||
|
# a date on the holiday is shifted back one day...
|
||||||
|
shifted = ms.validate_schedule_date_for_holiday_list(getdate(holiday), sp.name)
|
||||||
|
self.assertEqual(getdate(shifted), getdate(add_days(holiday, -1)))
|
||||||
|
|
||||||
|
# ...a non-holiday date is returned unchanged
|
||||||
|
non_holiday = add_days(today(), 7)
|
||||||
|
unchanged = ms.validate_schedule_date_for_holiday_list(getdate(non_holiday), sp.name)
|
||||||
|
self.assertEqual(getdate(unchanged), getdate(non_holiday))
|
||||||
|
|
||||||
|
|
||||||
def make_serial_item_with_serial(self, item_code):
|
def make_serial_item_with_serial(self, item_code):
|
||||||
serial_item_doc = create_item(item_code, is_stock_item=1)
|
serial_item_doc = create_item(item_code, is_stock_item=1)
|
||||||
@@ -202,6 +247,7 @@ def make_maintenance_schedule(**args):
|
|||||||
"no_of_visits": 4,
|
"no_of_visits": 4,
|
||||||
"serial_no": args.get("serial_no"),
|
"serial_no": args.get("serial_no"),
|
||||||
"sales_person": "Sales Team",
|
"sales_person": "Sales Team",
|
||||||
|
"sales_order": args.get("sales_order"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
ms.insert(ignore_permissions=True)
|
ms.insert(ignore_permissions=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user