Constraints are an inherent part of any scheduling workflow. From simple time restrictions to frequently changing rule matrices, rules can range in complexity. Validation rules allow you to codify these constraints, enabling end users to build and modify schedules with an understanding of the limitations and restrictions that define your organization’s operations.
Each validation rule is backed by a TypeScript function that evaluates whether the current state of a schedule object meets a certain condition as defined in the function logic.
Users are presented with the results of validation rules on the front-end of the Scheduling Gantt Chart widget in Workshop. Upon initial load, all rules are evaluated based on the current state of the Ontology. With each modification to the schedule, the rules are re-evaluated. This process empowers users with the knowledge of how their decisions comply with specific constraints and restrictions.
Below is an example of scheduling constraints within a Scheduling Gantt Chart widget. In the first image, the rule No Operator Overlaps is applied, as indicated with the toggle. This option ensures that only results abiding by this rule will be presented. The following image demonstrates the output. In this example, there is a conflict between the two rows, where the operators, Brad Evans and Ashley Brown, are overlapping.
In the Scheduling Gantt Chart widget in Workshop, the validation rules will be called each time a change is performed to validate the schedules.
1. Action "saveHandler" called on scenario
2. Validation rules called on updated scenario
3. Action "saveHandler" called on scenario
4. Validation rules called on updated scenario
etc ...
n. The user selects "Submit changes", and all Actions that have been applied to the scenario are applied to the Ontology
Rules are configured directly in the Scheduling Gantt Chart widget, allowing you to apply rules on a per use case basis. To add a rule to your Scheduling Gantt Chart widget:
scheduleObjectPrimaryKeys
input argument. You can leave this argument empty as it will be autofilled by the widget at runtime.The types below represent the necessary information to write a validation rule, which includes the status of the rule for each object.
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
type IFoORule = (scheduleObjectPrimaryKeys: string[]) => Array<IRuleResult> /* Rule result is interpreted as follows: true - Rule validated as passing false - Rule validated as not passing undefined - Rule is not relevant to the given schedule object */ interface IRuleResult { result: boolean | undefined; scheduleObjectPrimaryKey: string; details?: Array<IRuleResultDetails>; } /* By default the text on the pop-over card will display the rule name as configured in the rule object Optionally, you can explicitly define custom text based on the results of rule evaluation Additionally, you can provide a set of related puckIds to point users towards why a rule is passing or failing */ interface IRuleResultDetails { description: string; relatedPuckIds: string[]; }
The following is a basic example of a Function without the core logic of the validation:
Copied!1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
import { Function, Integer } from "@foundry/functions-api"; import { Objects, TaskOrSchedule, ObjectSet} from "@foundry/ontology-api"; // For type definitions, review our public documentation interface IRuleResultDetails { description: string; relatedPuckIds: string[]; } interface IRuleResult { result: boolean | undefined; scheduleObjectPrimaryKey: string; details?: Array<IRuleResultDetails>; } type IFoORule = (scheduleObjectPrimaryKeys: string[]) => Array<IRuleResult> export class MyFunctions { // NOTE: it is important that the input argument to a constraint function is named EXACTLY `scheduleObjectPrimaryKeys`. // This is how the widget knows to send over the correct set of keys to this Function. @Function() public async evaluateIfTaskOrScheduleIsValid(scheduleObjectPrimaryKeys: string[]): Promise<Array<IRuleResult>> { // Fetch all schedule Ontology Objects const taskOrSchedules = await Objects.search().taskOrSchedule() .filter(taskOrSchedule => taskOrSchedule.primaryKey.exactMatch(...scheduleObjectPrimaryKeys)) .allAsync(); // Iterate through every input key and generate a result entry for it const ruleResults: Array<IRuleResult> = scheduleObjectPrimaryKeys.map(pk => { const currentTaskOrSchedule = taskOrSchedules.find(taskOrSchedule => taskOrSchedule.primaryKey === pk); // Do something with the object and validate something, ... // Build the validation result const currentValidationDetails: Array<IRuleResultDetails> = []; currentValidationDetails.push( { description: "This is the description of the validation that passes or not", relatedPuckIds: [] }); const currentResult: IRuleResult= { result: true, scheduleObjectPrimaryKey: pk, details: currentValidationDetails, }; return currentResult; }); return ruleResults; } }
More complex validation rules can be created. For example, rules can check the following: