I recently had a similar requirement while migrating our triggers off our DB into automation scripts. It's an launch point on the status attribute. Here is a starter template for what I came up with. I'm still testing it before moving into production. But I think it's pretty close to the workflow that you're looking for.
With that said, we don't allow our users to manually close work orders. All they can do is put them into a "Completed" status. We then have a batch job that will run 90 days after they are in that status to finally close them.
from psdi.server import MXServer
from psdi.util import MXApplicationException
# ---------------------------------------------------------------------------
# Script Name: VAL_WO_STATUS
# Launch Point: Attribute - WORKORDER.STATUS - Validate
# Logic: Prevents Close/Bill/Cancel if open Children or POs exist.
# ---------------------------------------------------------------------------
# 1. Define the "Gatekeeper" statuses
stop_statuses = ['CLOSE', 'BILLPREP', 'CAN', 'COMP']
# Get the status the user is trying to change to.
# Return the NEW value currently in memory.
pendingStatus = mbo.getString("STATUS")
if pendingStatus in stop_statuses:
# 2. PM Bypass Rule
# If this WO came from a PM (Preventive Maintenance), we skip all checks.
pmnum = mbo.getString("PMNUM")
if not pmnum:
# Get current WO details
wonum = mbo.getString("WONUM")
siteid = mbo.getString("SITEID")
# ---------------------------------------------------------
# CHECK 1: Open Child Work Orders
# ---------------------------------------------------------
where_children = "parent = '{}' and siteid = '{}' and status not in ('CAN','CLOSE','BILLPREP')".format(wonum, siteid)
childSet = MXServer.getMXServer().getMboSet("WORKORDER", mbo.getUserInfo())
childSet.setWhere(where_children)
if not childSet.isEmpty():
# We found open children! Stop the user.
params = [wonum]
# Ensure "openchildren" exists in Database Config > Messages
raise MXApplicationException("workorder", "openchildren", params)
childSet.close()
# ---------------------------------------------------------
# CHECK 2: Open Purchase Orders (Directly on this WO)
# ---------------------------------------------------------
where_po = "refwo = '{}' and siteid = '{}' and exists (select 1 from po where po.ponum=poline.ponum and po.revisionnum=poline.revisionnum and po.siteid=poline.siteid and po.status not like 'C%' and po.status <> 'REVISD')".format(wonum, siteid)
poLineSet = MXServer.getMXServer().getMboSet("POLINE", mbo.getUserInfo())
poLineSet.setWhere(where_po)
if not poLineSet.isEmpty():
service.error("po", "openpo_on_wo")
# raise MXApplicationException("po", "openpo_on_wo")
poLineSet.close()
# ---------------------------------------------------------
# CHECK 3: Open POs on Child Work Orders
# ---------------------------------------------------------
where_child_po = "refwo in (select wonum from workorder where parent='{}' and siteid='{}') and siteid = '{}' and exists (select 1 from po where po.ponum=poline.ponum and po.revisionnum=poline.revisionnum and po.siteid=poline.siteid and po.status not like 'C%' and po.status <> 'REVISD')".format(wonum, siteid, siteid)
childPoSet = MXServer.getMXServer().getMboSet("POLINE", mbo.getUserInfo())
childPoSet.setWhere(where_child_po)
if not childPoSet.isEmpty():
service.error("po", "openpo_on_childwo")
# raise MXApplicationException("po", "openpo_on_childwo")
childPoSet.close()
# ---------------------------------------------------------
# CHECK 4: Open Purchase Requisitions (Directly on this WO)
# ---------------------------------------------------------
# Checks PRLINEs linked to this WO where the PR header is not Closed (CLOSE) or Cancelled (CAN)
where_pr = "refwo = '{}' and siteid = '{}' and exists (select 1 from pr where pr.prnum=prline.prnum and pr.siteid=prline.siteid and pr.status not like 'C%')".format(wonum, siteid)
prLineSet = MXServer.getMXServer().getMboSet("PRLINE", mbo.getUserInfo())
prLineSet.setWhere(where_pr)
if not prLineSet.isEmpty():
service.error("pr", "openpr_on_wo")
# raise MXApplicationException("pr", "openpr_on_wo")
prLineSet.close()
# ---------------------------------------------------------
# CHECK 5: Open PRs on Child Work Orders
# ---------------------------------------------------------
where_child_pr = "refwo in (select wonum from workorder where parent='{}' and siteid='{}') and siteid = '{}' and exists (select 1 from pr where pr.prnum=prline.prnum and pr.siteid=prline.siteid and pr.status not like 'C%')".format(wonum, siteid, siteid)
childPrSet = MXServer.getMXServer().getMboSet("PRLINE", mbo.getUserInfo())
childPrSet.setWhere(where_child_pr)
if not childPrSet.isEmpty():
service.error("pr", "openpr_on_childwo")
# raise MXApplicationException("pr", "openpr_on_childwo")
childPrSet.close()
------------------------------
Brett Coleman
Georgia Building Authority
------------------------------