Workflow Guard-Skripte#

Workflow Guard-Skripte werden Zustandsübergängen im Workflow zugewiesen. Sie prüfen etwas und stoppen den Zustandsübergang, wenn die Prüfung ein Nichteinhalten der Prüfbedingung ergeben hat.

Validierung eines Checkbox-Attributs#

package script.workflowGuard

import com.aurel.track.admin.customize.scripting.BINDING_PARAMS;
import com.aurel.track.admin.customize.treeConfig.field.FieldBL
import com.aurel.track.beans.TFieldBean
import com.aurel.track.beans.TWorkItemBean

public class CheckBoxValidator {
	/**
	 * Workflow guard script example
	 * @param inputBinding
	 * @return
	 */
	public Map<String, Object> handleEvent(Map<String, Object> inputBinding) {
		TFieldBean checkBoxField = FieldBL.loadByName("checkBoxFieldName");
		if (checkBoxField!=null) {
			Integer fieldID = checkBoxField.getObjectID();
			TWorkItemBean workItemBean = inputBinding.get("item");
			Boolean isChecked = workItemBean.getAttribute(fieldID);
			inputBinding.put(BINDING_PARAMS.GUARD_PASSED, isChecked!=null && isChecked.booleanValue());
		}
		return inputBinding;
	}
}

Prüfung, ob Vorgänger fertig#

Das basiert auf Vorgänger-Nachfolger-Verknüpfungen. Wenn der Vorgänger einen bestimmten Zustand erreicht hat, darf der Zustandsübergang stattfinden.

package script.workflowGuard
import com.aurel.track.admin.customize.lists.systemOption.StatusBL
import com.aurel.track.admin.customize.scripting.BINDING_PARAMS;
import com.aurel.track.beans.TPersonBean
import com.aurel.track.beans.TStateBean
import com.aurel.track.beans.TWorkItemBean
import com.aurel.track.beans.TWorkItemLinkBean
import com.aurel.track.errors.ErrorData
import com.aurel.track.fieldType.runtime.base.LookupContainer
import com.aurel.track.fieldType.runtime.base.WorkItemContext
import com.aurel.track.item.ItemBL
import com.aurel.track.item.link.ItemLinkBL
import com.aurel.track.resources.LocalizeUtil

public class PredecessorReady {
	
	/**
	 * Prevents the status change related to a guard if a predecessor, having other status than the configured, is found 
	 * @param inputBinding
	 * @return
	 */
	public Map<String, Object> handleEvent(Map<String, Object> inputBinding) {
		WorkItemContext workItemContext = (WorkItemContext)inputBinding.get("workItemContext")
		TWorkItemBean workItemBean = workItemContext.getWorkItemBean()
		Integer itemID = workItemBean.getObjectID()
		TPersonBean personBean = (TPersonBean)inputBinding.get("user")
		Locale locale = (Locale)inputBinding.get("locale")
		List<ErrorData> errorList = new ArrayList<>()
		//look up the linktype ID in Link types config, ID column
		Integer linkTypeID = 4
		// 1=Unidirectional outward and bidirectional links,
		// 2=Unidirectional inward (MsProject)
		Integer linkDirection = 2
		List<TWorkItemLinkBean> itemLinkBeans = ItemLinkBL.loadBySuccAndLinkType(itemID,
								linkTypeID, linkDirection, true)
		//alternatively look up target state(s) by other criteria
		boolean notDonePredecessorFound = false;
		if (itemLinkBeans!=null && itemLinkBeans.size()>0) {
			//System.out.println("Linked items found: " + itemLinkBeans.size())
			TStateBean doneStatusBean = StatusBL.loadByLabel("erledigt", Locale.GERMAN)
			if (doneStatusBean!=null) {
				//System.out.println("Done status found: " + doneStatusBean.getObjectID())
				for (itemLinkBean in itemLinkBeans) {
					Integer predecessor = itemLinkBean.getLinkPred()
					TWorkItemBean linkedItemBean = ItemBL.loadWorkItemSystemAttributes(predecessor)
					Integer status = linkedItemBean.getStateID()
					if (!status.equals(doneStatusBean.getObjectID())) {
						//System.out.println("Predecessor " + linkedItemBean.getObjectID() + " " + linkedItemBean.getSynopsis() + " with other status found. Exclude the transition")
						notDonePredecessorFound = true
						break;
					}
				}
			}
		}
		inputBinding.put(BINDING_PARAMS.GUARD_PASSED, !notDonePredecessorFound);
		return inputBinding;
	}
}