Eric's answer is really good. I would add to use the "getInternalStatus()" so it works for CLOSE and any aliases. I have also added a few safety checks in case the script was invoked in an unexpected context, just as good practice.
I didn't change it here, but as good practice you should add a message in the System Configuration > Platform Configuration > Database Configuration > Messages More Actions menu item and then reference the message group and key instead of embedding the message in your script.
The scriptConfig at the end is metadata included so you can deploy it with this VSCode extension, which vastly speeds up automation script development.
https://marketplace.visualstudio.com/items?itemName=sharptree.maximo-script-deploy
if mbo is not None and mbo.isBasedOn("WORKORDER") and mbo.getInternalStatus() == "CLOSE":
laborSet = mbo.getMboSet("SHOWACTUALLABOR")
if laborSet.isEmpty():
service.error("configure","BlankMsg",["You must have a labor transaction to close this workorder."])
scriptConfig="""{
"autoscript": "WORKORDER.SAVE.LABORCHECK",
"description": "Check for labor before close.",
"version": "",
"active": true,
"logLevel": "ERROR",
"scriptLaunchPoints": [
{
"launchPointName": "WORKORDER.SAVE.LABORCHECK",
"launchPointType": "OBJECT",
"active": true,
"description": "Check for labor before close.",
"objectName": "WORKORDER",
"save": true,
"add": false,
"update": true,
"delete": false,
"beforeSave": true
}
]
}"""