Employee Shift Scheduling User Guide
1. Terms
Term | Description |
---|---|
Employee that can be assigned to a shift. |
|
Employee contract that defines settings specific to a group of employees (e.g. maximum number of minutes worked per month). |
|
Unit of work that has to be covered by an employee. Each shift has a start and end time and can have various requirements (e.g. skills required). |
|
Configuration of global rules that apply to all employees and shifts (e.g. fairness configuration). |
2. Architecture
Under the hood, the application includes Timefold Enterprise Solver - scalable optimization engine that can solve complex constraint satisfaction problems.
Employee Shift Scheduling model has been formulated using Timefold Solver SDK.
REST API layer is defined on top of the model and serves as a communication point with the engine. It provides a stable interface that allows to manage lifecycle of the optimization problem, from submitting it to retrieving the final solution.
2.1. Typical user workflow
2.1.1. Create problem dataset
Create problem dataset using predefined model schema that follows OpenAPI specification. The application provides several out-of-the-box examples that can be used as a starting point.
GET /v1/demo-data
GET /v1/demo-data/{dataset_name}
2.1.2. Submit dataset
Submit the unsolved dataset using the REST API. The application validates the input and returns a unique identifier of the problem. The solving process is scheduled and eventually starts.
POST /v1/schedules
2.1.3. Get current best solution and check status
Check the current best solution and receive information about the solving process.
The solution contains optimized employee shift schedule.
Use id
attribute returned by submit dataset step.
GET /v1/schedules/{id}
2.1.4. Terminate solving
Terminate the solving process and receive the current best solution.
Use id
attribute returned by submit dataset step.
DELETE /v1/schedules/{id}
2.1.5. Get all solving processes
Get info about the status of all solving processes.
GET /v1/schedules
3. Input structure
Input payload consists of a model input representing a schedule and a configuration
3.1. Configuration
3.1.1. Run configuration
The run configuration is shared across all models. Below is an example of a run configuration.
"config": { "run": { "name": "run name", "termination": { "spentLimit": "PT5M", "unimprovedSpentLimit": "PT10S" }, "maxThreadCount": "1", "tags": [] }, "model": { "overrides": { <model-specific configurations> } } }
A run configuration has two fields: the run and the model.
The run has four fields:
-
name
- The run name (if empty, it will be generated). -
termination
- The termination properties, which contains the maximum duration to keep the solver running (spentLimit
) and the maximum unimproved score duration (unimprovedSpentLimit
) (if the score has not improved during this period, the solver will terminate). If null, no maximum duration or maximum unimproved score duration will be set. -
maxThreadCount
- The maximum thread count, which indicates the maximum number of threads to be used for solving. If not provided, 1 will be used. -
tags
- The tags, which are a set of optional tags to be assigned to the job.
The model is a model-specific field, that contains additional global model configuration attributes.
3.2. Concepts
3.2.1. Employee contract period rule
Employee contract can define multiple rules that are assessed over either a built-in or a custom period.
The period rule can optionally define a ruleValidityDateTimeSpan
to limit the rule to a specific time span.
The validity date time span uses the employee’s zone offset to determine the start and end time of the rule.
To learn more about time zones and daylight saving time, see Timezones and Daylight Saving Time (DST).
The following example shows a rule that requires an employee to work no more than 6 hours a day, but only during December 2024:
{ "period" : "DAY", "minutesWorkedMax" : 360, "ruleValidityDateTimeSpan": { "start": "2024-12-01T00:00:00", "end": "2025-01-31T00:00:00" } }
3.2.2. Model configuration
Provides an optional configuration of the model, for example specifying the weight of constraints.
3.2.2.1. Constraint weight overrides
Every constraint has a default weight of 1, meaning that all constraints are equally important.
Use this to express preference of some constraints over others.
For example, in order to express that the employee pairing constraint is more important than the rest of the constraints, set the value of the employeeIsPairedWithPreferredEmployeeWeight
attribute to 10.
In order to turn off a constraint, set the value of the corresponding attribute to 0.
"config": { "overrides": { "employeeIsPairedWithPreferredEmployeeWeight": 10, "employeeWorksDuringPreferredTimeWeight": 0 } }
3.3. Model input
Contains the schedule to be solved. This includes employees, shifts and other data.
3.3.1. Employee
Employee that can be assigned to a shift.
Id | Required | Format | Description | Example |
---|---|---|---|---|
Id |
true |
string |
Unique string identifier of the employee. |
|
Contracts |
false |
array |
Identifiers of employee contracts. |
|
false |
integer |
Employee priority. Employee preferences are more likely to be satisfied for employees with higher priority. |
|
|
false |
string |
Cost group of the employee. In conjunction with the cost group of the shift, it is used to calculate the cost of the shift assignment. |
|
|
false |
array |
Location of the employee. |
|
|
false |
array |
List of employee skills, optionally including date time spans when a particular skill is valid. They are checked against the required and preferred skills of a shift. |
|
|
false |
array |
List of employee tags. They provide additional information that can be used to filter out specific employees (e.g. in balance shifts constraints). |
|
|
false |
array |
List of preferred shift tags. They express a preference to assign the employee to a shift with given tags. The tags and their types need to be configured as documented in Tags and tag types. |
|
|
false |
array |
List of required shift tags. They express a requirement to assign the employee to a shift with given tags. The tags and their types need to be configured as documented in Tags and tag types. |
|
|
false |
array |
List of prohibited risk factors. Employees cannot be assigned to a shift that has any of their prohibited risk factors (e.g. selected employees cannot be exposed to COVID-19 shift). |
|
|
false |
array |
List of preferred employee pairings. Use to express preference of employees to work together at the same time, optionally only for shifts with specific tags. |
|
|
false |
array |
List of unpreferred employee pairings. Use to express non-preference of employees to work together at the same time, optionally only for shifts with specific tags. |
|
|
false |
array |
List of required employee pairings. Use to express requirement of employees to work together at the same time, optionally only for shifts with specific tags. |
|
|
false |
array |
List of prohibited employee pairings. Use to prevent employees from working together at the same time, optionally only for shifts with specific tags. |
|
|
false |
array |
List of preferred time spans. Use to express time spans where employee prefers to work, optionally only for shifts with specific tags. |
|
|
false |
array |
List of unpreferred time spans. Use to express time spans where employee does not prefer to work, optionally only for shifts with specific tags. |
|
|
false |
array |
List of unavailable time spans. Use to express time spans where employee cannot work (e.g. time off), optionally only for shifts with specific tags. |
|
|
false |
array |
List of available time spans. Use to express time spans the employee is available to work, optionally only for shifts with specific tags. |
|
|
false |
array |
The employee time zone offset to Taken into account by employee period rules, see Timezones and Daylight Saving Time (DST). The default value is |
|
3.3.2. Employee contract
Employee contract that defines settings specific to a group of employees (e.g. maximum number of minutes worked per month).
Id | Required | Format | Description | Example |
---|---|---|---|---|
Id |
true |
string |
Unique string identifier of the contract. |
|
false |
array |
Rules for minimum, or maximum consecutive days worked. Use this to control how many days in a row an employee with this contract are minimally (or maximally) required (or preferred) to work.
The rule can optionally define a |
|
|
false |
array |
Rules tied to a period (e.g. DAY, WEEK, MONTH, SCHEDULE). Use this to express preference / requirement of employees to work a certain number of minutes / shifts / shift types / days in a period,
optionally only for shifts with specific tags.
The rule can optionally define a |
|
|
false |
array |
Rules tied to shifts near a day off. Use this to express preference / requirement of employees to avoid certain shifts before / after a day off, optionally only for shifts with specific tags. |
|
|
false |
array |
Settings for the minimum, or maximum minutes between shifts. Use this to control how much time off an employee is required/preferred to have between consecutive shifts,
optionally only for shifts with specific tags.
The rule can optionally define a |
|
|
false |
array |
Settings for minimizing the gaps between shifts. Use this to prefer assigning employees to shifts that are close to each other, optionally only for shifts with specific tags. |
|
|
false |
array |
Settings for shifts that require pairing with another shift on the same or a different day. Use this to control what shifts are required/preferred to be paired for the employee, optionally only for shifts with specific tags. |
|
|
false |
array |
Settings for shift sequence patterns that span across a single day. Use this to specify a sequence of shifts that should, or should not follow each other on the same day, optionally only for shifts with specific tags. |
|
|
false |
array |
Settings for shift sequence patterns that span across multiple days. Use this to specify chain of shifts that should, or should not follow each other on consecutive days, optionally only for shifts with specific tags. You can configure two types of patterns using Please note that if you use a pattern starting or ending with In case there are multiple shifts on a single day, you can configure the pattern to match all the shifts, or any of the shifts using the The pattern satisfiability defines if the pattern is Please note that You may also specify the weight of this pattern to make it more important than another pattern (the default value is |
|
|
false |
array |
Rules tied to shift overlap. Use this to allow employees to work overlapping shifts with specified tags. |
|
3.3.3. Shift
Unit of work that has to be covered by an employee. Each shift has a start and end time and can have various requirements (e.g. skills required).
Name | Required | Format | Description | Example |
---|---|---|---|---|
Id |
true |
string |
Unique string identifier of the shift. |
|
true |
string, ISO-8601 |
Start time of the shift. |
|
|
End |
true |
string, ISO-8601 |
End time of the shift. |
|
false |
string |
Cost group of the shift. In conjunction with the cost group of the employee, it is used to calculate the cost of the shift assignment. |
|
|
false |
array |
Location of the shift. |
|
|
false |
array |
List of required shift skills. Only an employee that has all of the shift’s required skills can be assigned to a shift. |
|
|
false |
array |
List of preferred shift skills. An employee that has more of the shift’s preferred skills will be preferred over an employee with less of the shift’s preferred skills when assigning this shift. |
|
|
false |
array |
List of risk factors associated with this shift. An employee cannot be assigned to a shift that is associated with any of their prohibited risk factors (for instance, selected employees cannot be exposed to COVID-19 shift). |
|
|
false |
array |
List of shift tags. Use to express additional shift data (e.g. shift type, department). |
|
|
false |
array |
List of preferred shift employees. Use to express employees that are preferred to work on a shift. |
|
|
false |
array |
List of preferred shift employees. Use to express employees that are unpreferred to work on a shift. |
|
|
false |
array |
List of prohibited shift employees. Use to express employees that are prohibited to work on a shift. |
|
|
false |
int |
Deprecated - use |
|
|
false |
string |
Defines priority for shift assignment. There are 10 built-in priorities where "1" is the highest priority and "10" is the lowest priority. Default built-in priority is "10". These built-in priorities use exponential penalty weights, where priority "1" is 10 times more important than priority "2", priority "2" is 10 times more important than priority "3" and so on. Optionally, you can override these weights, or define custom priorities in the unassigned shift rule. In case the custom priorities are used, there is no default value for the priority attribute, and you need to provide a value. |
|
|
Pinned |
false |
boolean |
Shift pin. Use to fix shift assignment to a specific employee / no employee ( |
|
Employee |
false |
reference |
Employee assigned to the shift. Can be changed by the solver depending on the value of |
|
3.3.4. Global rules configuration
Configuration of global rules that apply to all employees and shifts (e.g. fairness configuration).
Name | Required | Format | Description | Example |
---|---|---|---|---|
false |
array |
Configuration of balance time worked rules. Use to make sure the number of minutes worked across shifts, that match the conditions specified, is balanced across employees.
The rule takes historic data into account.
Use the |
|
|
false |
array |
Configuration of balance shift count rules. Use to make sure the number of shifts worked, that match the conditions specified, is balanced across employees.
The rule takes historic data into account.
Use the |
|
|
false |
array |
Configuration of hourly demand rules. Rules tied to hourly demand. Use this to express global preference, or a requirement to fulfill " |
|
|
false |
array |
Configuration of costs rule. Use this to make sure the total costs of shift assignments are in the required range. Please see Timezones and Daylight Saving Time (DST) when working with multiple time zones or DST. |
|
|
false |
array |
Rules tied to a period (e.g. DAY, WEEK, MONTH, SCHEDULE). Use this to express a global preference, or a requirement to work a certain number of shifts in a period, optionally only for shifts with specific tags. Please see Timezones and Daylight Saving Time (DST) when working with multiple time zones or DST. |
|
|
false |
array |
Configuration of disruption rules. Use this to make sure the disruptions caused by resolving an existing problem are minimized. |
`"disruptionRules": [ { "id": "minimizeDisruptionShortTerm", "start": "2024-05-01", "end": "2024-05-14", "multiplier": 3 }, { "id": "minimizeDisruptionLongTerm", "start": "2024-05-15", "end": "2024-07-01", "multiplier": 1 } ] |
|
false |
array |
Configuration of shift tag match rules. Use this to express a requirement, or a preference of an employee to work specific shift types. |
|
|
false |
object |
Configuration of unassigned shift rule. Use this to configure the priorities of shift assignments and configure custom priorities and assignment type. See Unassigned shift rule for more information. |
|
3.3.5. Schedule Parameterization
3.3.5.1. Periods
Configuration for periods used in the schedule. The following builtin periods are available:
-
DAY
: Spans a single day and occurs on every day being scheduled. -
WEEK
: Spans 7 days, starting at the specifiedweekStart
in the Schedule Parameterization. Repeats for every week being scheduled (including partial weeks). -
MONTH
: Spans the entire month. Has a variable amount of days depending on the days in the month. Repeats for every month being scheduled (including partial months). -
SCHEDULE
: Spans the entire schedule. -
MONDAY
: A single day span that repeats for each Monday being scheduled. -
TUESDAY
: A single day span that repeats for each Tuesday being scheduled. -
WEDNESDAY
: A single day span that repeats for each Wednesday being scheduled. -
THURSDAY
: A single day span that repeats for each Thursday being scheduled. -
FRIDAY
: A single day span that repeats for each Friday being scheduled. -
SATURDAY
: A single day span that repeats for each Saturday being scheduled. -
SUNDAY
: A single day span that repeats for each Sunday being scheduled.
Name | Required | Format | Description | Example |
---|---|---|---|---|
Week Start |
false |
string, Weekday ALLCAPS |
The day each week inside the |
|
Periods |
false |
array |
List of custom periods. Each custom period has an id used to identify it in period rule, and a list of date spans that the custom period covers. The date spans can vary in duration, and do not need to be continuous. The boundaries of the date spans are inclusive. |
|
false |
object |
Travel configuration. Every employee can define location. Similarly, shifts can define location. Together with travel configuration, these attributes are used to calculate travel related rules, such as maximum distance between an employee and a shift. The configuration can exclude some of the shifts from the maximum travel distance limit, based on the employee’s requiredShiftTags and preferredShiftTags attributes. For example, we want to enforce a limit of 100 km between an employee and a shift, but we want to exclude shifts that belong to the same team as the employee. |
|
3.3.6. Planning window
The planning window is the time interval to schedule for.
Typically, it is derived automatically and does not need to be supplied by user, except the case when there is a multi-day pattern rule starting or ending with one or more OFF
elements.
Example planning window definition from Monday 2024-02-05 00:00
to Sunday 2024-02-11 23:59:59
:
{ "employees": [ ... ], "shifts": [ ... ], "planningWindow": { "start": "2024-02-05T00:00+01:00", "end": "2024-02-12T:00:00+01:00" } }
Please note that the start
time is treated as inclusive, while the end
as exclusive.
If omitted, the planning window interval is derived as follows:
-
start
: the start of the earliest of all shifts with time part adjusted to 00:00 (midnight).
Example: the earliest shift start = 2024-10-10T08:00+01:00
→ window start = 2024-10-10T00:00+01:00
.
-
end
: the next day after the start of the latest of all shifts with time part adjusted to 00:00 (midnight).
Example: the latest shift start = 2024-10-10T08:00+01:00
→ window end = 2024-10-11T00:00+01:00
.
3.3.7. Tags and tag types
Tags provide additional data to domain objects, such as employees and shifts. An example of a tag could be country 'Belgium', department 'A', or employment type 'Contractor'.
Tags can be used to filter out specific employees or shifts in rules.
Imagine a case where we want to apply Balance time worked constraints, but exclude external contractors and one-off shifts from the consideration.
We follow a convention of using includeEmployeeTags
, or excludeEmployeeTags
to filter out employees, and using includeShiftTags
, or excludeShiftTags
to filter out shifts in the rules.
These basic filters don’t require the user to enumerate all the tags and their categories explicitly in the input payload as a part of top-level tags
and tagTypes
collection.
Tags can be grouped into tag types.
An example of a tag type could be 'Country', 'Department', or 'Employment type'.
Some rules, such as Employee works shift with matching preferred shift tags, or configuration objects as Travel configuration require additional tag information, meaning the user needs to enumerate all referenced tags and their categories explicitly in the input payload as a part of top-level tags
and tagTypes
collection.
3.3.8. Tags
Name | Required | Format | Description | Example |
---|---|---|---|---|
Id |
true |
string |
Unique string identifier of the tag. |
|
Tag type |
true |
string |
Identifiers of the tag type. |
|
3.3.9. Tag types
Name | Required | Format | Description | Example |
---|---|---|---|---|
Id |
true |
string |
Unique string identifier of the tag type. |
|
4. Constraints
4.1. Hard constraints
4.1.1. Required skill missing
Employee possesses several skills. Shift can define one or more required skills. The constraint triggers if the employee does not have all the skills required by the shift. The skills need to be valid for the whole duration of the shift. Use the skill’s validityDateTimeSpans attribute to define the validity of a skill.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023", "missingSkills": [ "Nurse" ] }
4.1.2. Overlapping shift
The constraint triggers if multiple shifts assigned to the same employee overlap. Employee contract can define several allow overlapping shift rules.
If defined, only shifts containing tags defined by the allow overlapping shift rule’s includeShiftTags attribute can overlap with other shifts.
With shiftTagMatches set to ALL
, all tags defined by the overlapping shift rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the overlapping shift rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the allow overlapping shift rule’s excludeShiftTags attribute can overlap with other shifts.
With shiftTagMatches set to ALL
, all tags defined by the overlapping shift rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the overlapping shift rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Score analysis justification example:
{ "shift1": "icu-afternoon-10-11-2023", "shift2": "icu-afternoon-10-11-2023", "employee": "Beth Jones" }
4.1.3. Minutes worked per period not in required range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of minutes worked by the employee in a period is below the value of the period rule’s minutesWorkedMin, or above the value of period rule minutesWorkedMax.
-
Value of period rule satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included in the total number of minutes worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule’s excludeShiftTags attribute are included in the total number of minutes worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax480MinutesPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "minutesWorked": 600 }
4.1.4. Shifts worked per period not in required range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of shifts assigned to the employee in a period is below the value of the period rule’s shiftsWorkedMin, or above the value of period rule shiftsWorkedMax.
-
Value of period rule satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule’s excludeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax1ShiftPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "shiftsWorked": 2 }
4.1.5. Locations worked per period not in required range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
The number of the shift locations assigned to the employee in a period is above the value of the period rule’s locationsWorkedMax.
-
The value of the period rule’s satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of locations worked.
With shiftTagMatches set to ALL
, all tags defined by the period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule excludeShiftTags attribute are included in the total number of locations worked.
With shiftTagMatches set to ALL
, all tags defined by the period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s locationsWorkedPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax1LocationPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "locationsWorked": 2 }
4.1.6. Days worked per period not in required range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of days when a shift is assigned to the employee in a period is below the value of the period rule’s daysWorkedMin, or above the value of the period rule’s daysWorkedMax.
-
Value of the period rule’s satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by period rule excludeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The day is considered worked if the employee is assigned to at least one shift that starts on that day. Shifts that start on the previous day and end on the current day are not considered.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax4DaysWorkedPerWeek", "dateSpan": { "start": "2023-11-13T00:00:00Z", "end": "2023-11-20T00:00:00Z" }, "daysWorked": 5 }
4.1.7. Shift types worked per period not in required range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of unique shift types assigned to the employee in a period is below the value of the period rule’s shiftTypesWorkedMin, or above the value of the period rule’s shiftTypesWorkedMax.
-
A shift has exactly one tag defined by the shiftTypeTagCategories attribute. The value of this tag defines the shift type.
-
Value of the period rule’s satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by period rule excludeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The day is considered worked if the employee is assigned to at least one shift that starts on that day. Shifts that start on the previous day and end on the current day are not considered.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax2MorningShiftsWorkedPerWeek", "dateSpan": { "start": "2023-11-13T00:00:00Z", "end": "2023-11-20T00:00:00Z" }, "shiftTypesWorked": 4 }
4.1.8. Consecutive days worked not in required range for employee
Employee contract can define several consecutive days worked rules`. The constraint triggers if all conditions below apply:
-
Number of consecutive days when a shift is assigned to the employee in a period is below the value of consecutive days worked rule minimum, or above the value of consecutive days worked rule maximum.
-
Value of the period rule’s satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by consecutive days worked rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by consecutive days worked rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the rule’s excludeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by consecutive days worked rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by consecutive days worked rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
If defined, shifts containing a tag defined by the rule’s shiftTypeTagCategories form a sequence based on the value of the tag, for example a sequence of consecutive "morning" shifts. The shift must always have at most one tag defined by the rule’s shiftTypeTagCategories attribute.
The day is considered worked if the employee is assigned to at least one shift that starts on that day. Shifts that start on the previous day and end on the current day are not considered. In case there are no shifts that satisfy the rule’s filters, not attaining the minimum does cause the constraint violation.
Score analysis justification example:
{ "employee": "Beth Jones", "consecutiveDaysWorkedRule": "BethMax2ConsecutiveMorningDaysWorked", "shiftTypeTagCategory": "Morning", "sequenceStartDate": "2023-11-13", "sequenceEndDate": "2023-11-27" }
4.1.9. Shifts worked per period not in required range
Global rules configuration can define one or more minimum or maximum number of shifts worked per period. This is useful to express a global requirement to fulfill a certain number of shifts in a period, optionally only for shifts, or employees with specific tags. The constraint triggers if all conditions below apply:
-
Number of shifts assigned in a period is below the value of the rule’s shiftsWorkedMin, or above the value of the rule’s shiftsWorkedMax.
-
Value of period rule satisfiability attribute is set to
REQUIRED
.
If defined, only employees containing tags defined by rule’s includeEmployeeTags attribute are included in the total number of shifts worked.
With employeeTagMatches set to ALL
, all tags defined by the rule’s includeEmployeeTags attribute have to be present in the employee.
With employeeTagMatches set to ANY
, at least one tag defined by the rule’s includeEmployeeTags attribute has to be present in the employee.
If defined, only employees not containing tags defined by the rule’s excludeEmployeeTags attribute are included in the total number of shifts worked.
With employeeTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the employee.
With employeeTagMatches set to ANY
, any of the tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee.
The rule can define either includeEmployeeTags or excludeEmployeeTags, not both.
If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule’s excludeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Configuration example for a requirement to staff at most 3 administrative shifts per day, including only full time employees.
"minimumMaximumShiftsPerPeriod": [ { "id": "AtMost3AdministrativeShiftsPerDay", "period": "DAY", "includeEmployeeTags": ["Full-time"], "includeShiftTags": ["Administrative"], "shiftsWorkedMax": 3 }
Score analysis justification example:
{ "periodRule": "AtMost3AdministrativeShiftsPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "shiftsWorked": 4 }
4.1.10. Costs per period not in required range
Global rules configuration can define one or more costs rules. The constraint makes sure the total costs of shift assignments, that match tags specified, are in the required range.
The employee defines a cost group. The shift defines a cost group. The costs rule requires a list of employee shift cost details that expresses the cost of assigning the employee to the shift.
The constraint triggers if all conditions below apply:
-
Total costs of shifts assigned in a period is below the value of the costs rule’s totalCostsMin, or above the value of the costs rule’s totalCostsMax.
-
Value of the period rule’s satisfiability attribute is set to
REQUIRED
.
Note you need to define the cost detail for each employee cost group and shift cost group combination that should be included in the total costs. Undefined employee cost group and shift cost group combinations are not included in the total costs.
If defined, only employees containing tags defined by the rule’s includeEmployeeTags attribute are included in the total costs.
With employeeTagMatches set to ALL
, all tags defined by the rule’s includeEmployeeTags attribute have to be present in the employee.
With employeeTagMatches set to ANY
, at least one tag defined by the rule’s includeEmployeeTags attribute has to be present in the employee.
If defined, only employees not containing tags defined by the rule’s excludeEmployeeTags attribute are included in the total costs.
With employeeTagMatches set to ALL
, all tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee.
With employeeTagMatches set to ANY
, any of the tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee.
The rule can define either includeEmployeeTags or excludeEmployeeTags, not both.
If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the total costs.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the rule’s excludeShiftTags attribute are included in the total costs.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Score analysis justification example:
{ "costsRule": "Max20kPerMonth", "dateSpan": { "start": "2023-11-01T00:00:00Z", "end": "2023-12-01T00:00:00Z" }, "cost": 22000 }
4.1.11. Employee is not paired with required employee
Employee can define several required employee pairings. The pairings express employees that have to work together at the same time. The constraint triggers for each shift assigned to the employee that does not overlap with a shift assigned to the required employee.
Score analysis justification example:
{ "employee1": "Beth Jones", "employee2": "Ann Green", "shift": "icu-afternoon-10-11-2023", "employeePairing": { "pairedEmployee": "Ann Green", "onlyForShiftTags": [ "Training" ] } }
4.1.12. Employee is paired with prohibited employee
Employee can define several prohibited employee pairings. The pairings express employees that cannot work together at the same time. The constraint triggers for each shift assigned to the employee that overlaps with a shift assigned to the prohibited employee.
Score analysis justification example:
{ "employee1": "Beth Jones", "employee2": "Ann Green", "shift1": "icu-afternoon-10-11-2023", "shift2": "standard-afternoon-10-11-2023", "employeePairing": { "pairedEmployee": "Ann Green", "onlyForShiftTags": [ "High risk" ] } }
4.1.13. Employee has prohibited risk factor associated with shift
Employee can define several prohibited risk factors. Shift can define one or more risk factors. The constraint triggers if the employee is assigned to a shift that contains one or more risk factors defined by the employee.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023", "riskFactors": [ "COVID-19" ] }
4.1.14. Prohibited employee assigned
Shift can define one or more prohibited employees. The constraint triggers if the shift is assigned to one of the employees listed in the shift’s prohibited employees collection.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023" }
4.1.15. Employee works during unavailable time
Employee can define several unavailable time spans. The span defines a period when the employee cannot work (e.g. time off). The constraint triggers if the employee is assigned to a shift that matches optional shift tag criteria and overlaps with one or more unavailable time spans defined by the employee.
If defined, only shifts containing tags defined by unavailable time for employee includeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the unavailable time for employee includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the unavailable time for employee includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by preferred time for employee excludeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the unavailable time for employee excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the unavailable time for employee excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023", "overlappingTimeSpans": [ { "start": "2023-11-10T12:00:00Z", "end": "2023-11-10T16:00:00Z" } ] }
4.1.16. Employee does not work during available time
Employee can define several available time spans. If defined, the spans defines the only periods when the employee is available. Otherwise, the employee is available to be scheduled for the entire schedule (except when prohibited by unavailable time spans). The constraint triggers if the employee is assigned to a shift that is not contained by one or more available time spans defined by the employee that matches the optional shift tag criteria.
If defined, only shifts containing tags defined by available time for employee includeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the unavailable time for employee includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the unavailable time for employee includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by preferred time for employee excludeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the unavailable time for employee excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the unavailable time for employee excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023" }
4.1.17. Employee works shifts with non-matching required shift tags
Global rules configuration can define one or more shift tag match rules. The constraint makes sure the employees are assigned to the shifts based on their shift type requirement.
Imagine an organization that contains multiple departments.
Each department contains multiple teams.
We want to create a schedule for shifts that belong to specific departments and teams.
For example a shift in Department A
.
Employees also belong to specific departments and can only work shifts within their department.
For example an employee has to work in Department A
, not in Department Y
We define a tag hierarchy as described in section Tags and tag types:
"tagTypes": [ { "id": "Department" } ], "tags": [ { "id": "Department A", "tagType": "Department" }, { "id": "Department B", "tagType": "Department" } ]
We define shifts that reference some of the tags:
"shifts": [ { "id": "ShiftDepartmentA", "start": "2025-11-10T12:00:00Z", "end": "2025-11-10T16:00:00Z", "tags": [ "Department A" ] }, { "id": "ShiftDepartmentB", "start": "2025-11-11T12:00:00Z", "end": "2025-11-11T16:00:00Z", "tags": [ "Department B" ] } ]
We define employees that express requirement to work shifts with some of the tags. This is done via the requiredShiftTags attribute:
"employees": [ { "id": "EmployeeTeamX", "contracts": [ "Full time employee" ], "requiredShiftTags": [ "Department A" ] }, { "id": "EmployeeDepartmentB", "contracts": [ "Full time employee" ], "requiredShiftTags": [ "Department B" ] } ]
We define a rule that validates that employees assigned to shifts that match their required tags. The rule states that whenever a shift is assigned to an employee and the required tag does not match the shift tags, we penalize such assignments.
For example, EmployeeDepartmentA
has a required shift tag Department A
.
If they are assigned to the shift ShiftDepartmentA
which has the tag Department A
(tag type Department
), we don’t penalize such assignments.
If they are assigned to the shift ShiftDepartmentB
which has the tag Department B
(tag type Department
), we penalize such assignments.
"shiftTagMatchRules": [ { "id": "MatchDepartment", "satisfiability": "REQUIRED" } ]
The constraint triggers if all the conditions below apply:
-
An employee that defines requiredShiftTags is assigned to a shift that defines tags and some of the tags are included in both collections.
-
The value of the period rule’s satisfiability attribute is set to
REQUIRED
.
Score analysis justification example:
{ "rule": "MatchDepartment", "employee": "EmployeeDepartmentA", "shift": "ShiftDepartmentB", "nonMatchingTags": [ "Department A" ] }
4.1.18. Employee has prohibited shift near day off request
Employee contract can define several avoid shift close to day off request rules. The rules define types of shifts that should be avoided before / after a day off. The constraint triggers if all conditions below apply:
-
Shift is assigned to the employee in a day preceding a day off and the shift contains one or more tags defined by the rule prohibitedPriorShiftTags attribute.
-
Shift is assigned to the employee in a day following a day off and the shift contains one or more tags defined by the rule prohibitedAfterShiftTags attribute.
-
Value of the period rule’s satisfiability attribute is set to
PROHIBITED
.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-evening-10-11-2023", "avoidShiftCloseToDayOffRequestRule": "noEveningShiftBeforeDayOff" }
4.1.19. Minutes between shifts not in required range for employee
Employee contract can define several minutes between shifts rules. The constraint triggers if all the conditions below apply:
If the value of minimumConsecutivePriorShifts attribute is set to 1
:
-
The employee is assigned to two shifts and the duration between the first shift’s end and the second shift’s start is either below the minimum or above the maximum specified in the rule.
-
Value of minutes between rule’s satisfiability attribute is set to
REQUIRED
.
If the value of minimumConsecutivePriorShifts attribute is set to 2
:
-
The employee is assigned to a consecutive daily sequence of two shifts and other shift. The duration between the end of the first sequence defined by shift’s end and the other shift’s start is either below the minimum or above the maximum specified in the rule.
-
Value of minutes between rule’s satisfiability attribute is set to
REQUIRED
. -
Value of requiredPriorShiftTags needs to be specified to identify the prior sequence, for example a sequence of night shifts.
If defined, only shifts containing tags defined by minutes between shifts rule’s requiredPriorShiftTags attribute can be the first shift.
With shiftTagMatches set to ALL
, all tags defined by the minutes between shifts rule’s requiredPriorShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the minutes between shifts rule’s requiredPriorShiftTags attribute has to be present in the shift.
If defined, only shifts containing tags defined by minutes between shifts rule’s requiredAfterShiftTags attribute can be the first shift.
With shiftTagMatches set to ALL
, all tags defined by the minutes between shifts rule’s requiredAfterShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the minutes between shifts rule’s requiredAfterShiftTags attribute has to be present in the shift.
Score analysis justification example:
{ "employee": "Beth Jones", "shift1": "icu-morning-10-11-2023", "shift2": "icu-afternoon-10-11-2023", "minutesBetweenShiftsRule": "minimum600minutes", "violationInMinutes": 120 }
4.1.20. Employee does not have required daily shift pairing
Employee contract can define several daily shift pairings. The constraint triggers if all the conditions below apply:
-
The employee is assigned to a shift matching the rule’s shiftTags and is not assigned to a shift matching the rule’s pairedShiftTags on a day defined by the rule’s dayOffset attribute. The offset is applied to a date of the first shift and can be both positive, or negative.
-
Value of the daily shift pairing rule’s satisfiability attribute is set to
REQUIRED
.
With shiftTagMatches set to ALL
, all tags defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute have to be present in the shift to match.
With shiftTagMatches set to ANY
, at least one tag defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute has to be present in the shift.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-morning-10-11-2023", "dailyShiftPairingRule": "saturdayWithSunday" }
4.1.21. Employee has prohibited daily shift pairing
Employee contract can define several daily shift pairings. The constraint triggers if all the conditions below apply:
-
The employee is assigned to a shift matching the rule’s shiftTags and is assigned to a shift matching the rule’s pairedShiftTags on a day defined by the rule’s dayOffset attribute. The offset is applied to a date of the first shift and can be both positive, or negative.
-
Value of the daily shift pairing rule’s satisfiability attribute is set to
PROHIBITED
.
With shiftTagMatches set to ALL
, all tags defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute have to be present in the shift to match.
With shiftTagMatches set to ANY
, at least one tag defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute has to be present in the shift.
Score analysis justification example:
{ "employee": "Beth Jones", "shift1": "icu-late-friday", "shift2": "icu-early-saturday", "dailyShiftPairingRule": "lateFridayNotWithEarlySaturday" }
4.1.22. Employee does not work required single day shift sequence pattern
Employee contract can define several single day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee does not work the exact sequence of shifts on a particular day, as declared in the rule’s pattern attribute. Number of shifts the employee works on given day needs to match the size of the pattern.
-
Value of the single day shift sequence pattern rule’s satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the single day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
Use the constraint configuration’s employeeDoesNotWorkSingleDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequence": { "matchElements": [ { "shift": "ICU-Morning", "matchType": "MATCH" }, { "shift": "ICU-Night", "matchType": "NO_MATCH" } ] }, "patternRule": "MorningAfternoon" }
4.1.23. Employee works prohibited single day shift sequence pattern
Employee contract can define several single day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee works the exact sequence of shifts on a particular day, as declared in the rule’s pattern attribute. Number of shifts the employee works on given day needs to match the size of the pattern.
-
Value of the single day shift sequence pattern rule’s satisfiability attribute is set to
PROHIBITED
.
If defined, only shifts containing tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the single day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
Use the constraint configuration’s employeeWorksProhibitedSingleDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequence": { "matchElements": [ { "shift": "ICU-Morning", "matchType": "MATCH" }, { "shift": "ICU-Afternoon", "matchType": "MATCH" } ] }, "patternRule": "MorningAfternoon" }
4.1.24. Employee does not work required multi day shift sequence pattern
Employee contract can define several multi day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee does not work the exact sequence of shifts, or day offs, spanning across consecutive days, as declared in the rule’s pattern attribute.
-
Value of the multi day shift sequence pattern rule’s satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the multi day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
In case there are multiple shifts on the same day, use the pattern element’s shiftMatches attribute to define the matching behavior.
With shiftMatches set to ALL
, all shifts need to match the tag criteria of the pattern element on that particular day.
With shiftMatches set to ANY
, any shift needs to match the tag criteria of the pattern element on that particular day.
The default value of shiftMatches attribute is ALL
.
Use the constraint configuration’s employeeDoesNotWorkRequiredMultiDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequences": [ { "matchElements": [ { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Late", "matchType": "MATCH" }, { "shift": "ICU-Night", "matchType": "NO_MATCH" } ] } ], "patternRule": "EarlyEarlyNightNight" }
4.1.25. Employee works prohibited multi day shift sequence pattern
Employee contract can define several multi day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee works the exact sequence of shifts, or day offs, spanning across consecutive days, as declared in the rule’s pattern attribute.
-
Value of the multi day shift sequence pattern rule’s satisfiability attribute is set to
PROHIBITED
.
If defined, only shifts containing tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the multi day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
In case there are multiple shifts on the same day, use the pattern element’s shiftMatches attribute to define the matching behavior.
With shiftMatches set to ALL
, all shifts need to match the tag criteria of the pattern element on that particular day.
With shiftMatches set to ANY
, any shift needs to match the tag criteria of the pattern element on that particular day.
The default value of shiftMatches attribute is ALL
.
Use the constraint configuration’s employeeWorksProhibitedMultiDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequences": [ { "matchElements": [ { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Late", "matchType": "MATCH" }, { "shift": "ICU-Late", "matchType": "MATCH" } ] } ], "patternRule": "EarlyEarlyNightNight" }
4.1.26. Maximum employee to shift travel distance exceeded
Schedule parametrization can define travel configuration.
The constraint makes sure the maximum travel distance between the employee location and shift location does not exceed the maxEmployeeToShiftTravelDistanceInMeters
limit defined in the travel configuration.
The configuration allows you to exclude some of the shifts from the maximum travel distance limit, based on the employee’s requiredShiftTags and preferredShiftTags attributes.
For example, we want to enforce a limit of 100 km between an employee and a shift, but we want to exclude shifts that belong to the same team as the employee.
The constraint triggers if all the following conditions apply:
-
Shift’s location is defined.
-
Employee’s location is defined.
-
_object_attributes_schedule_parameterization_travel_configuration[Travel configuration] is defined in the schedule parametrization.
-
The distance between employee location and shift location exceeds the
maxEmployeeToShiftTravelDistanceInMeters
limit in travel configuration. -
If excludeMatchingShiftTagTypes is configured, there is no match between the employee’s preferredShiftTags, or requiredShiftTags and the shift’s tags for those excluded shift type tags.
If defined, only shifts containing tags defined by the travel configuration’s includeShiftTags attribute are included in the maximum travel distance check.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the travel configuration’s excludeShiftTags attribute are included in the maximum travel distance check.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, but not both.
Configuration example to set the maximum employee travel distance to 40km for all shifts.
"travelConfiguration": { "maxEmployeeToShiftTravelDistanceInMeters": 40000 }
Configuration example to set the maximum employee travel distance to 40km for ICU shifts.
"travelConfiguration": { "includeShiftTags": ["ICU"], "maxEmployeeToShiftTravelDistanceInMeters": 40000 }
Configuration example to set the maximum employee travel distance to 40km for ICU shifts, or Cardiology shifts.
"travelConfiguration": { "includeShiftTags": ["ICU", "Cardiology"], "shiftTagMatches": "ANY", "maxEmployeeToShiftTravelDistanceInMeters": 40000 }
Score analysis justification example:
"justification": { "shift": "ICU-shift-location-A", "employee": "Ann Green", "distanceInMeters": 42000 }
4.1.27. Minimum time between shifts including travel not met
Schedule parametrization can define travel configuration.
The constraint makes sure the minimum number of minutes between shifts that have different locations and are assigned to the same employee follows the minMinutesBetweenShiftsInDifferentLocations
limit defined in the travel configuration.
The constraint triggers if all conditions below apply:
-
Shift’s location is defined.
-
Employee’s location is defined.
-
_object_attributes_schedule_parameterization_travel_configuration[Travel configuration] is defined in the schedule parametrization.
-
The number of minutes between two shifts at different locations, that are assigned to the same employee, is below the
minMinutesBetweenShiftsInDifferentLocations
limit defined in travel configuration.
If defined, only shifts containing tags defined by the travel configuration’s includeShiftTags attribute are included in the maximum travel distance check.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the travel configuration’s excludeShiftTags attribute are included in the maximum travel distance check.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, but not both.
Configuration example to set the minimum number of minutes between any employee’s shifts in different locations to 240 minutes.
"travelConfiguration": { "minMinutesBetweenShiftsInDifferentLocations": 240 }
Configuration example to set the minimum number of minutes between employee’s ICU shifts in different locations to 240 minutes.
"travelConfiguration": { "includeShiftTags": ["ICU"], "minMinutesBetweenShiftsInDifferentLocations": 240 }
Configuration example to set the minimum number of minutes between employee’s ICU shifts, or Cardiology shifts in different locations to 240 minutes.
"travelConfiguration": { "includeShiftTags": ["ICU", "Cardiology], "shiftTagMatches": "ANY", "minMinutesBetweenShiftsInDifferentLocations": 240 }
Score analysis justification example:
"justification": { "shift1": "ICU-shift-location-A", "shift2": "ICU-shift-location-B", "employee": "Ann Green" }
4.2. Medium constraints
4.2.1. Unassigned mandatory shift
The constraint penalizes mandatory shifts (see Mandatory and optional shifts) that are not assigned to any employee. The size of the penalty depends on the shift’s priority and its weight. High priority shifts are more likely to be assigned, compared to low priority shifts.
The model defines 10 built-in priorities, where 1 is the highest priority and 10 is the lowest priority. The default built-in priority is 10. These built-in priorities use exponential penalty weights, where priority 1 is 10 times more important than priority 2, priority 2 is 10 times more important than priority 3 and so on. Optionally, you can override these weights, or define custom priorities in the unassigned shift rule. In case the custom priorities are used, there is no default value for the priority attribute, and you need to provide a value.
You can also define the assignment priority by setting the shift’s assignmentPriority attribute. This feature has been deprecated as of 0.25.0. The payload should be updated to use the priority attribute instead. If both priority and assignmentPriority attributes are used in the dataset, a validation error is thrown. If the unassigned shift rule is configured and assignmentPriority is used in the dataset, a validation error is thrown. |
Consider a case with two morning shifts:
-
Morning-head-nurse with high assignment priority 1
-
Morning-trainee-nurse with lower assignment priority 5
Whenever the solver is unable to assign both shifts, since that would lead to a hard score violation, it might decide to keep one of the shifts unassigned. In the example above, it potentially leaves 'Morning-trainee-nurse' shift unassigned, since it has a lower assignment priority.
Score analysis justification example:
"justification": { "shift": "Morning-trainee-nurse" }
If 10 built-in priorities are not enough, you can define custom priority levels.
These custom priorities are defined in the priorityWeights
attribute of the unassigned shift rule.
The weights of the priorities need to be defined in descending order, where the first element of the array has the highest weight.
All priorities referenced in the dataset need to be defined in the priorityWeights
attribute and their weight need to be configured.
"unassignedShiftRule": { "id": "unassignedShiftRule", "priorityWeights": [ { "priority": "1", "weight": 20 }, { "priority": "2", "weight": 19 }, ... { "priority": "20", "weight": 1 } ] }
4.2.1.1. Mandatory and optional shifts
In most scenarios, assigning one more shift is preferable to satisfying a soft constraint.
This is the default behaviour of the Unassigned mandatory shift where the shifts are considered mandatory
.
However, in some cases the conformance with a strong soft constraint, such as a multi-day pattern rule or employee preference, might be preferred over assigning one more extra shift.
The shifts which can be left unassigned in favor of not breaking a very strong soft constraint are referred to as optional
shifts.
A shift can be declared as optional
by associating it with a specific priority with the OPTIONAL
assignment
attribute:
"unassignedShiftRule": { "id": "unassignedShiftRule", "priorityWeights": [ { "priority": "1", "weight": 20, "assignment": "MANDATORY" }, { "priority": "2", "weight": 19, "assignment": "OPTIONAL" } ] }
All shifts with "priority": "2"
are considered optional
and their assignment will not be preferred over satisfying soft constraints.
4.2.2. Shifts worked not in required hourly demand range
Global rules configuration can define one or more minimum maximum shifts per hourly demand rules. The constraint makes sure the total number of shift assignments in hourly intervals, that match tags specified, are in the required range, optionally only for shifts with specific tags.
The constraint triggers if all conditions below apply:
-
Number of shifts worked in a hourly demand interval is below the value of the demand rule’s minDemand, or above the value of demand rule’s maxDemand.
-
Value of the demand rule’s satisfiability attribute is set to
REQUIRED
.
If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule’s excludeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Use the constraint configuration’s shiftsWorkedNotInRequiredHourlyDemandRangeWeight attribute to update the weight of the constraint.
Score analysis justification example:
"justification": { "hourlyDemandRule": "HourlyDemand", "startDateTime": "2024-05-06T07:00:00Z", "shiftsWorked": 25 }
4.3. Soft constraints
4.3.1. Unassigned optional shift
The constraint penalizes optional shifts (see Mandatory and optional shifts) that are not assigned to any employee. The size of the penalty depends on the shift’s priority and its weight. High priority shifts are more likely to be assigned, compared to low priority shifts.
The penalty is calculated the same as for Unassigned mandatory shift, just on the soft level. See Unassigned mandatory shift constraint description for more details.
Use the constraint configuration’s unassignedOptionalShiftWeight attribute to update the weight of the constraint.
Score analysis justification example:
"justification": { "shift": "Morning-trainee-nurse" }
4.3.2. Employee assignment disrupted on replanning
Global rules configuration can define one or more disruption rules. The constraint makes sure the disruptions caused by resolving an existing problem are minimized. This includes changes of the employee assigned to a shift, compared to the original schedule. Consider a case where you need to re-plan an already published schedule due to an unexpected employee absence. You want to minimize the impact of the re-planning on the schedule and the employees who might have already made plans based on the original schedule. Disruptions that are close to the time of the re-planning possibly have more impact than disruptions that are further away.
The constraint triggers if all conditions below apply:
If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the disruption check.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the rule’s excludeShiftTags attribute are included in the disruption checks.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeAssignmentDisruptedOnReplanningWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "currentEmployee": "Ann" "originalEmployee": "Beth", "shift": "ICU-Morning-01-05", "disruptionRule": "MinimimizeDisruptionShortTerm" }
4.3.3. Preferred skill missing
Employee possesses several skills. Shift can define one or more preferred skills. The constraint triggers if the employee does not have all the skills defined by the shift. The skills need to be valid for the whole duration of the shift. Use the skill’s validityDateTimeSpans attribute to define the validity of a skill.
Use the constraint configuration’s preferredSkillMissingWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023", "missingSkills": [ "Nurse" ] }
4.3.4. Minutes worked per period not in preferred range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of minutes worked by the employee in a period is below the value of the period rule’s minutesWorkedMin, or above the value of the period rule’s minutesWorkedMax.
-
Value of the period rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of minutes worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by period rule excludeShiftTags attribute are included in the total number of minutes worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s minutesAssignedPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax480MinutesPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "minutesWorked": 600 }
4.3.5. Shifts worked per period not in preferred range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of shifts assigned to the employee in a period is below the value of the period rule’s shiftsWorkedMin, or above the value of the period rule’s shiftsWorkedMax.
-
Value of the period rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by period rule excludeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s shiftsAssignedPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax1ShiftPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "shiftsWorked": 2 }
4.3.6. Locations worked per period not in preferred range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
The number of shift locations assigned to the employee in a period is above the value of the period rule’s locationsWorkedMax.
-
The value of the period rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by the period rule includeShiftTags attribute are included in the total number of locations worked.
With shiftTagMatches set to ALL
, all tags defined by the period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule excludeShiftTags attribute are included in the total number of locations worked.
With shiftTagMatches set to ALL
, all tags defined by the period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s locationsWorkedPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax1LocationPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "locationsWorked": 2 }
4.3.7. Days worked per period not in preferred range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of days when a shift is assigned to the employee in a period is below the value of the period rule’s daysWorkedMin, or above the value of the period rule’s daysWorkedMax.
-
Value of the period rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by period rule excludeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The day is considered worked if the employee is assigned to at least one shift that starts on that day. Shifts that start on the previous day and end on the current day are not considered.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s daysWorkedPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax4DaysWorkedPerWeek", "dateSpan": { "start": "2023-11-13T00:00:00Z", "end": "2023-11-20T00:00:00Z" }, "daysWorked": 5 }
4.3.8. Shift types worked per period not in preferred range for employee
Employee contract can define several period rules. The constraint triggers if all conditions below apply:
-
Number of unique shift types assigned to the employee in a period is below the value of the period rule’s shiftTypesWorkedMin, or above the value of the period rule’s shiftTypesWorkedMax.
-
A shift has exactly one tag defined by the shiftTypeTagCategories attribute. The value of this tag defines the shift type.
-
Value of the period rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by period rule excludeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The day is considered worked if the employee is assigned to at least one shift that starts on that day. Shifts that start on the previous day and end on the current day are not considered.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s shiftTypesWorkedPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "periodRule": "BethMax2MorningShiftsWorkedPerWeek", "dateSpan": { "start": "2023-11-13T00:00:00Z", "end": "2023-11-20T00:00:00Z" }, "shiftTypesWorked": 4 }
4.3.9. Consecutive days worked not in preferred range for employee
Employee contract can define several consecutive days worked rules. The constraint triggers if all conditions below apply:
-
Number of consecutive days when a shift is assigned to the employee in a period is below the value of consecutive days worked rule minimum, or above the value of consecutive days worked rule maximum.
-
Value of the period rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by consecutive days worked rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by consecutive days worked rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by period rule excludeShiftTags attribute are included in the total number of days worked.
With shiftTagMatches set to ALL
, all tags defined by consecutive days worked rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by consecutive days worked rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The day is considered worked if the employee is assigned to at least one shift that starts on that day. Shifts that start on the previous day and end on the current day are not considered.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s consecutiveDaysWorkedNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "consecutiveDaysWorkedRule": "BethMax2ConsecutiveMorningDaysWorked", "shiftTypeTagCategory": "Morning", "sequenceStartDate": "2023-11-13", "sequenceEndDate": "2023-11-27" }
4.3.10. Shifts worked not in preferred hourly demand range
Global rules configuration can define one or more minimum maximum shifts per hourly demand rules. The constraint makes sure the total number of shift assignments in hourly intervals, that match tags specified, are in the required range, optionally only for shifts with specific tags.
The constraint triggers if all conditions below apply:
-
Number of shifts worked in a hourly demand interval is below the value of the demand rule’s minDemand, or above the value of demand rule’s maxDemand.
-
Value of the demand rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule’s excludeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Use the constraint configuration’s shiftsWorkedNotInPreferredHourlyDemandRangeWeight attribute to update the weight of the constraint.
Score analysis justification example:
"justification": { "hourlyDemandRule": "HourlyDemand", "startDateTime": "2024-05-06T07:00:00Z", "shiftsWorked": 25 }
4.3.11. Balance shifts worked for minimum hourly demand
Global rules configuration can define one or more minimum maximum shifts per hourly demand rules. The constraint makes sure the total number of shift assignments, that match tags specified, are distributed evenly across the hourly intervals. The constraint takes the minimum demand into account, optionally only for shifts with specific tags. For example, if the minimum demand throughout the whole day is 5 shifts and the shift supply is higher than the demand, the constraint makes sure that the extra shifts are distributed evenly across the day, as opposed to assigning them all in the first hour of the day.
The constraint triggers if all conditions below apply:
-
Number of shifts worked in a hourly demand interval differs from the value of the demand rule’s minDemand.
If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by period rule includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule’s excludeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by period rule excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Use the constraint configuration’s balanceShiftsWorkedForMinimumHourlyDemandWeight attribute to update the weight of the constraint.
Score analysis justification example:
"justification": { "hourlyDemandRule": "HourlyDemand", "startDateTime": "2024-05-06T07:00:00Z", "targetDemand": 30, "shiftsWorked": 25 }
4.3.12. Shifts worked per period not in preferred range
Global rules configuration can define one or more minimum or maximum number of shifts worked per period. This is useful to express a global preference to fulfill a certain number of shifts in a period, optionally only for shifts, or employees with specific tags. The constraint triggers if all conditions below apply:
-
Number of shifts assigned in a period is below the value of the rule’s shiftsWorkedMin, or above the value of the rule’s shiftsWorkedMax.
-
Value of period rule satisfiability attribute is set to
PREFERRED
.
If defined, only employees containing tags defined by rule’s includeEmployeeTags attribute are included in the total number of shifts worked.
With employeeTagMatches set to ALL
, all tags defined by the rule’s includeEmployeeTags attribute have to be present in the employee.
With employeeTagMatches set to ANY
, at least one tag defined by the rule’s includeEmployeeTags attribute has to be present in the employee.
If defined, only employees not containing tags defined by the rule’s excludeEmployeeTags attribute are included in the total number of shifts worked.
With employeeTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the employee.
With employeeTagMatches set to ANY
, any of the tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee.
The rule can define either includeEmployeeTags or excludeEmployeeTags, not both.
If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the period rule’s excludeShiftTags attribute are included in the total number of shifts worked.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Configuration example for a preference to staff at most 3 administrative shifts per day, including only full time employees.
"minimumMaximumShiftsPerPeriod": [ { "id": "AtMost3AdministrativeShiftsPerDay", "period": "DAY", "satisfiability": "PREFERRED", "includeEmployeeTags": ["Full-time"], "includeShiftTags": ["Administrative"], "shiftsWorkedMax": 3 }
Score analysis justification example:
{ "periodRule": "AtMost3AdministrativeShiftsPerDay", "dateSpan": { "start": "2023-11-10T00:00:00Z", "end": "2023-11-11T00:00:00Z" }, "shiftsWorked": 4 }
4.3.13. Costs per period not in preferred range
Global rules configuration can define one or more costs rules. The constraint makes sure the total costs of shift assignments, that match tags specified, are in the required range.
The employee defines a cost group. The shift defines a cost group. The costs rule requires a list of employee shift cost details that expresses the cost of assigning the employee to the shift.
The constraint triggers if all conditions below apply:
-
Total costs of shifts assigned in a period is below the value of the costs rule’s totalCostsMin, or above the value of the costs rule’s totalCostsMax.
-
Value of the period rule’s satisfiability attribute is set to
PREFERRED
.
Note you need to define the cost detail for each employee cost group and shift cost group combination that should be included in the total costs. Undefined employee cost group and shift cost group combinations are not included in the total costs.
If defined, only employees containing tags defined by the rule’s includeEmployeeTags attribute are included in the total costs.
With employeeTagMatches set to ALL
, all tags defined by the rule’s includeEmployeeTags attribute have to be present in the employee.
With employeeTagMatches set to ANY
, at least one tag defined by the rule’s includeEmployeeTags attribute has to be present in the employee.
If defined, only employees not containing tags defined by the rule’s excludeEmployeeTags attribute are included in the total costs.
With employeeTagMatches set to ALL
, all tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee.
With employeeTagMatches set to ANY
, any of the tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee.
The rule can define either includeEmployeeTags or excludeEmployeeTags, not both.
If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the total costs.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the rule’s excludeShiftTags attribute are included in the total costs.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Use the constraint configuration’s costsPerPeriodNotInPreferredRangeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "costsRule": "Max20kPerMonth", "dateSpan": { "start": "2023-11-01T00:00:00Z", "end": "2023-12-01T00:00:00Z" }, "cost": 22000 }
4.3.14. Employee is paired with preferred employee
Employee can define several preferred employee pairings. The pairings express employees that prefer working together at the same time. The constraint triggers for each shift assigned to the employee that overlaps with a shift assigned to the preferred employee.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeIsPairedWithPreferredEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee1": "Beth Jones", "employee2": "Ann Green", "shift1": "icu-afternoon-10-11-2023", "shift2": "standard-afternoon-10-11-2023", "employeePairing": { "pairedEmployee": "Ann Green", "onlyForShiftTags": [ "Training" ] } }
4.3.15. Employee is paired with unpreferred employee
Employee can define several unpreferred employee pairings. The pairings express employees that prefer not to work together at the same time. The constraint triggers for each shift assigned to the employee that overlaps with a shift assigned to the unpreferred employee.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeIsPairedWithUnpreferredEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee1": "Beth Jones", "employee2": "Ann Green", "shift1": "icu-afternoon-10-11-2023", "shift2": "standard-afternoon-10-11-2023", "employeePairing": { "pairedEmployee": "Ann Green", "onlyForShiftTags": [ "High risk" ] } }
4.3.16. Employee works during preferred time
Employee contract can define several preferred time spans. The span defines a period when the employee prefers to work. The constraint triggers if the employee is assigned to a shift that matches optional shift tag criteria and overlaps with one or more preferred time spans defined by the employee.
If defined, only shifts containing tags defined by preferred time for employee includeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the preferred time for employee includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the preferred time for employee includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by preferred time for employee excludeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the preferred time for employee excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the preferred time for employee excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeWorksDuringPreferredTimeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023", "overlappingTimeSpans": [ { "start": "2023-11-10T06:00:00Z", "end": "2023-11-10T18:00:00Z" } ] }
4.3.17. Employee works during unpreferred time
Employee contract can define several unpreferred time spans. The span defines a period when the employee prefers not to work. The constraint triggers if the employee is assigned to a shift that matches optional shift tag criteria and overlaps with one or more unpreferred time spans defined by the employee.
If defined, only shifts containing tags defined by unpreferred time for employee includeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the unpreferred time for employee includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the unpreferred time for employee includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by unpreferred time for employee excludeShiftTags attribute are included.
With shiftTagMatches set to ALL
, all tags defined by the unpreferred time for employee excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the unpreferred time for employee excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeWorksDuringUnpreferredTimeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023", "overlappingTimeSpans": [ { "start": "2023-11-10T12:00:00Z", "end": "2023-11-10T16:00:00Z" } ] }
4.3.18. Employee works shifts with matching preferred shift tags
Global rules configuration can define one or more shift tag match rules. The constraint makes sure the employees are assigned to the shifts based on their shift type preference.
Imagine an organization that contains multiple departments.
Each department contains multiple teams.
We want to create a schedule for shifts that belong to specific departments and teams.
For example a shift in Department A
and team Team X
.
Employees also belong to specific departments and teams.
Moreover, the employees can work a shift in a different department, or team, if needed.
For example an employee preferrably works in Department A
and team Team X
, but can also take shifts in Department Y
.
The former assignment should be preferred if possible.
We define a tag hierarchy as described in section Tags and tag types:
"tagTypes": [ { "id": "Department" }, { "id": "Team" } ], "tags": [ { "id": "Team X", "tagType": "Team" }, { "id": "Team Y", "tagType": "Team" }, { "id": "Department A", "tagType": "Department" }, { "id": "Department B", "tagType": "Department" } ]
We define shifts that reference some of the tags:
"shifts": [ { "id": "ShiftTeamX", "start": "2025-11-10T12:00:00Z", "end": "2025-11-10T16:00:00Z", "tags": [ "Team X", "Department A" ] }, { "id": "ShiftTeamY", "start": "2025-11-11T12:00:00Z", "end": "2025-11-11T16:00:00Z", "tags": [ "Team Y", "Department A" ] }, { "id": "ShiftDepartmentB", "start": "2025-11-12T12:00:00Z", "end": "2025-11-12T16:00:00Z", "tags": [ "Department B" ] } ]
We define employees that express preference to work shifts with some of the tags. This is done with the preferredShiftTags attribute:
"employees": [ { "id": "EmployeeTeamX", "contracts": [ "Full time employee" ], "preferredShiftTags": [ "Team X", "Department A" ] }, { "id": "EmployeeDepartmentB", "contracts": [ "Full time employee" ], "preferredShiftTags": [ "Department B" ] } ]
We define a rule that expresses how likely employees are to be assigned shifts that match their preferred tags. The rule states that whenever a shift is assigned to an employee and the preferred tag matches shift tags, we reward such assignment with a multiplier, depending on the shift type of the tag.
For example, EmployeeTeamX
has preferred shift tags Team X
and Department A
.
If they are assigned to the shift ShiftTeamX
which has the tags Team X
(tag type Team
) and Department A
(tag type Department
), we reward with multipliers 1,000,000 and 1,000 respectively.
If they are assigned to the shift ShiftTeamY
which has the tags Team Y
(tag type Team
) and Department A
(tag type Department
), we reward with multipliers 1,000, since only the department matches.
If they are assigned to the shift ShiftDepartmentB
which has the tags Department B
(tag type Department
), we don’t reward, since none of the tags match.
"shiftTagMatchRules": [ { "id": "MatchOrganization", "satisfiability": "PREFERRED", "tagTypeMatchMultipliers": { "Team": 1000000, "Department": 1000 } } ]
The constraint triggers if all the conditions below apply:
-
An employee that defines preferredShiftTags is assigned to a shift that defines tags and some of the tags are included in both collections.
-
The value of the period rule’s satisfiability attribute is set to
PREFERRED
.
Use the constraint configuration’s employeeWorksShiftWithPreferredShiftTagsWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "rule": "MatchOrganization", "employee": "EmployeeTeamX", "shift": "ShiftTeamX", "matchingTags": [ "Department A", "Team X" ] }
4.3.19. Employee has unpreferred shift near day off request
Employee contract can define several avoid shift close to day off request rules. The rules define types of shifts that should be avoided before / after a day off. The constraint triggers if all conditions below apply:
-
Shift is assigned to the employee in a day preceding a day off and the shift contains one or more tags defined by the rule prohibitedPriorShiftTags attribute.
-
Shift is assigned to the employee in a day following a day off and the shift contains one or more tags defined by the rule prohibitedAfterShiftTags attribute.
-
Value of the rule’s satisfiability attribute is set to
UNPREFERRED
.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeHasUnpreferredShiftNearDayOffRequestWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-evening-10-11-2023", "avoidShiftCloseToDayOffRequestRule": "noEveningShiftBeforeDayOff" }
4.3.20. Preferred employee assigned
Shift can define one or more preferred employees. The constraint triggers if the shift is assigned to one of the employees listed in the shift’s preferred employees collection.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s preferredEmployeeAssignedWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023" }
4.3.21. Unpreferred employee assigned
Shift can define one or more unpreferred employees. The constraint triggers if the shift is assigned to one of the employees listed in the shift’s unpreferred employees collection.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s unpreferredEmployeeAssignedWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-afternoon-10-11-2023" }
4.3.22. Balance time worked
Global rules configuration can define one or more balance time worked rules. The constraint makes sure the total number of minutes worked across shifts, that match the specified tags, is balanced across employees that match the specified tags. This avoids situations where some employees work more time than others.
Please see Load balancing and fairness for further information about the fairness concept.
If defined, only employees containing tags defined by the balance time worked rule’s includeEmployeeTags attribute are balanced.
With employeeTagMatches set to ALL
, all tags defined by the balance time worked rule’s includeEmployeeTags attribute have to be present in the employee.
With employeeTagMatches set to ANY
, at least one tag defined by the balance time worked rule’s includeEmployeeTags attribute has to be present in the employee.
If defined, only employees not containing tags defined by the balance time worked rule’s excludeEmployeeTags attribute are balanced.
With employeeTagMatches set to ALL
, all tags defined by the balance time worked rule’s excludeShiftTags attribute cannot be present in the employee.
With employeeTagMatches set to ANY
, any of the tags defined by the the balance time worked rule’s excludeEmployeeTags attribute cannot be present in the employee.
The rule can define either includeEmployeeTags or excludeEmployeeTags, not both.
If defined, only shifts containing tags defined by the balance time worked rule’s includeShiftTags attribute are balanced.
With shiftTagMatches set to ALL
, all tags defined by the balance time worked rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the balance time worked rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the balance time worked rule’s excludeShiftTags attribute are balanced.
With shiftTagMatches set to ALL
, all tags defined by the balance time worked rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the balance time worked rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Use employeeToPublishedMinutesWorked attribute to specify the number of minutes worked by each employee in the past.
Use the constraint configuration’s balanceTimeWorkedWeight attribute to update the weight of the constraint.
4.3.23. Balance shift count
Global rules configuration can define one or more balance shift count rules. The constraint makes sure the total number of shifts worked, that match the specified tags, is balanced across employees that match the specified tags. This avoids situations where some employees work more shifts than others.
Please see Load balancing and fairness for further information about the fairness concept.
If defined, only employees containing tags defined by the balance shift count rule’s includeEmployeeTags attribute are balanced.
With employeeTagMatches set to ALL
, all tags defined by the balance shift count rule’s includeEmployeeTags attribute have to be present in the employee.
With employeeTagMatches set to ANY
, at least one tag defined by the balance shift count rule’s includeEmployeeTags attribute has to be present in the employee.
If defined, only employees not containing tags defined by the balance shift count rule’s excludeEmployeeTags attribute are balanced.
With employeeTagMatches set to ALL
, all tags defined by the balance shift count rule’s excludeShiftTags attribute cannot be present in the employee.
With employeeTagMatches set to ANY
, any of the tags defined by the balance shift count rule’s excludeEmployeeTags attribute cannot be present in the employee.
The rule can define either includeEmployeeTags or excludeEmployeeTags, not both.
If defined, only shifts containing tags defined by the balance shift count rule’s includeShiftTags attribute are balanced.
With shiftTagMatches set to ALL
, all tags defined by the balance shift count rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the balance shift count rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the balance shift count rule’s excludeShiftTags attribute are balanced.
With shiftTagMatches set to ALL
, all tags defined by the balance shift count rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the balance shift count rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
Use employeeToPublishedShiftCount attribute to specify the number of shifts worked by each employee in the past.
Use the constraint configuration’s balanceShiftCountWeight attribute to update the weight of the constraint.
4.3.24. Minutes between shifts not in preferred range for employee
Employee contract can define several minutes between shifts rules. The constraint triggers if all the conditions below apply:
-
The employee is assigned to two shifts and the duration between the first shift’s end and the second shift’s start is either below the minimum or above the maximum specified in the rule.
-
Value of minutes between rule’s satisfiability attribute is set to
PREFERRED
. -
Value of requiredPriorShiftTags needs to be specified to identify the prior sequence, for example a sequence of night shifts.
If defined, only shifts containing tags defined by minutes between shifts rule’s requiredPriorShiftTags attribute can be the first shift.
With shiftTagMatches set to ALL
, all tags defined by the minutes between shifts rule’s requiredPriorShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the minutes between shifts rule’s requiredPriorShiftTags attribute has to be present in the shift.
If defined, only shifts containing tags defined by minutes between shifts rule’s requiredAfterShiftTags attribute can be the first shift.
With shiftTagMatches set to ALL
, all tags defined by the minutes between shifts rule’s requiredAfterShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the minutes between shifts rule’s requiredAfterShiftTags attribute has to be present in the shift.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s minutesBetweenShiftsNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift1": "icu-morning-10-11-2023", "shift2": "icu-afternoon-10-11-2023", "minutesBetweenShiftsRule": "minimum600minutes", "violationInMinutes": 120 }
4.3.25. Minimize gaps between shifts for employee
Employee contract can define several minimize gaps between shifts rules. The constraint makes sure that shifts close to each other are preferred for an employee, in case the employee is eligible to work multiple shifts per day.
Imagine a case, where we have 3 shifts on a day:
-
Morning shift - 9:00 - 12:00
-
Afternoon shift - 13:00 - 16:00
-
Late shift - 17:00 - 20:00
In case we assigned an employee to the Morning shift and the Late shift, it leaves them with a 5-hour gap between the shifts, which is undesirable. A preferred solution would be to assign them to the Morning shift and the Afternoon shift, or the Afternoon shift and the Late shift, since those pairs of shifts only have 1-hour gap between them. This constraint prefers closer assignments. The shorter the break between the shifts, the better.
To avoid situations, where we reward pairs of shifts that are separated by multiple days, the constraint requires a definition of a time scope.
Only shifts that are close enough to each other are considered.
Use the rule’s maximumMinutesBetweenSplitShifts to define the length of the scope.
The default value of maximumMinutesBetweenSplitShifts is 120 minutes.
Looking at the example above, if the maximumMinutesBetweenSplitShifts is configured to 120
minutes, the Morning shift and the Afternoon shifts match, since they are only separated by 1 hour.
The same applies to the Afternoon shift and the Late shift.
The combination of the Morning shift and Late shift does not match though, since they are separated by 5 hours, which is above the limit of 2 hours.
The constraint triggers if all the following conditions apply:
-
The employee is assigned to two shifts and the duration between the first shift’s end and the second shift’s start is below the maximumMinutesBetweenSplitShifts specified in the rule.
If defined, only shifts containing tags defined by minutes between shifts rule’s requiredPriorShiftTags attribute can be the first shift.
With shiftTagMatches set to ALL
, all tags defined by the minimize gaps between shifts rule’s requiredPriorShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the minimize gaps between shifts rule’s requiredPriorShiftTags attribute has to be present in the shift.
If defined, only shifts containing tags defined by minutes between shifts rule’s requiredAfterShiftTags attribute can be the first shift.
With shiftTagMatches set to ALL
, all tags defined by the minimize gaps between shifts rule’s requiredAfterShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the minimize gaps between shifts rule’s requiredAfterShiftTags attribute has to be present in the shift.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s minimizeGapsBetweenShiftsForEmployeeWeight attribute to update the weight of the constraint.
Score analysis justification example:
"justification": { "employee": "Beth Jones", "shift1": "ICU morning", "shift2": "ICU afternoon", "minimizeGapsBetweenShiftsRule": "MinimizeGapsBetweenShiftsRule", "minutesBetweenShifts": 60
4.3.26. Employee does not have preferred daily shift pairing
Employee contract can define several daily shift pairings. The constraint triggers if all the conditions below apply:
-
The employee is assigned to a shift matching the rule’s shiftTags and is not assigned to a shift matching the rule’s pairedShiftTags on a day defined by the rule’s dayOffset attribute. The offset is applied to a date of the first shift and can be both positive, or negative.
-
Value of the daily shift pairing rule’s satisfiability attribute is set to
PREFERRED
.
With shiftTagMatches set to ALL
, all tags defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute have to be present in the shift to match.
With shiftTagMatches set to ANY
, at least one tag defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute has to be present in the shift.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeDoesNotHavePreferredDailyShiftPairingWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift": "icu-morning-10-11-2023", "dailyShiftPairingRule": "saturdayWithSunday" }
4.3.27. Employee has unpreferred daily shift pairing
Employee contract can define several daily shift pairings. The constraint triggers if all the conditions below apply:
-
The employee is assigned to a shift matching the rule’s shiftTags and is assigned to a shift matching the rule’s pairedShiftTags on a day defined by the rule’s dayOffset attribute. The offset is applied to a date of the first shift and can be both positive, or negative.
-
Value of the daily shift pairing rule’s satisfiability attribute is set to
UNPREFERRED
.
With shiftTagMatches set to ALL
, all tags defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute have to be present in the shift to match.
With shiftTagMatches set to ANY
, at least one tag defined by the daily shift pairing rule’s shiftTags/pairedShiftTags attribute has to be present in the shift.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeHasUnpreferredDailyShiftPairingWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "employee": "Beth Jones", "shift1": "icu-late-friday", "shift2": "icu-early-saturday", "dailyShiftPairingRule": "lateFridayNotWithEarlySaturday" }
4.3.28. Employee works preferred single day shift sequence pattern
Employee contract can define several single day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee works the exact sequence of shifts on a particular day, as declared in the rule’s pattern attribute. Number of shifts the employee works on given day needs to match the size of the pattern.
-
Value of the single day shift sequence pattern rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the single day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeWorksPreferredSingleDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequence": { "matchElements": [ { "shift": "ICU-Morning", "matchType": "MATCH" }, { "shift": "ICU-Afternoon", "matchType": "MATCH" } ] }, "patternRule": "MorningAfternoon" }
4.3.29. Employee works unpreferred single day shift sequence pattern
Employee contract can define several single day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee works the exact sequence of shifts on a particular day, as declared in the rule’s pattern attribute. Number of shifts the employee works on given day needs to match the size of the pattern.
-
Value of the single day shift sequence pattern rule’s satisfiability attribute is set to
UNPREFERRED
.
If defined, only shifts containing tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the single day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the single day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeWorksUnpreferredSingleDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequence": { "matchElements": [ { "shift": "ICU-Morning", "matchType": "MATCH" }, { "shift": "ICU-Afternoon", "matchType": "MATCH" } ] }, "patternRule": "MorningAfternoon" }
4.3.30. Employee works preferred multi day shift sequence pattern
Employee contract can define several multi day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee works the exact sequence of shifts, or day offs, spanning across consecutive days, as declared in the rule’s pattern attribute.
-
Value of the multi day shift sequence pattern rule’s satisfiability attribute is set to
PREFERRED
.
If defined, only shifts containing tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the multi day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
In case there are multiple shifts on the same day, use the pattern element’s shiftMatches attribute to define the matching behavior.
With shiftMatches set to ALL
, all shifts need to match the tag criteria of the pattern element on that particular day.
With shiftMatches set to ANY
, any shift needs to match the tag criteria of the pattern element on that particular day.
The default value of shiftMatches attribute is ALL
.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeWorksPreferredMultiDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequences": [ { "matchElements": [ { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Late", "matchType": "MATCH" }, { "shift": "ICU-Late", "matchType": "MATCH" } ] } ], "patternRule": "EarlyEarlyNightNight" }
4.3.31. Employee works unpreferred multi day shift sequence pattern
Employee contract can define several multi day shift sequence pattern rules. The constraint triggers if all the conditions below apply:
-
The employee works the exact sequence of shifts, or day offs, spanning across consecutive days, as declared in the rule’s pattern attribute.
-
Value of the multi day shift sequence pattern rule’s satisfiability attribute is set to
UNPREFERRED
.
If defined, only shifts containing tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the multi day shift sequence pattern rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute are included in the sequence.
With shiftTagMatches set to ALL
, all tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the multi day shift sequence pattern rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, not both.
The default value of shiftTagMatches attribute is ALL
.
In case there are multiple shifts on the same day, use the pattern element’s shiftMatches attribute to define the matching behavior.
With shiftMatches set to ALL
, all shifts need to match the tag criteria of the pattern element on that particular day.
With shiftMatches set to ANY
, any shift needs to match the tag criteria of the pattern element on that particular day.
The default value of shiftMatches attribute is ALL
.
The rule is more likely to be satisfied for employees with higher employee priority.
Use the constraint configuration’s employeeWorksUnpreferredMultiDayShiftSequencePatternWeight attribute to update the weight of the constraint.
Score analysis justification example:
{ "matchSequences": [ { "matchElements": [ { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Early", "matchType": "MATCH" }, { "shift": "ICU-Late", "matchType": "MATCH" }, { "shift": "ICU-Late", "matchType": "MATCH" } ] } ], "patternRule": "EarlyEarlyNightNight" }
4.3.32. Minimize travel distance
Schedule parametrization can define travel configuration. The constraint makes sure the distance traveled between employee’s location and shift’s location is minimized.
The constraint triggers if all of the following conditions apply:
If defined, only shifts containing tags defined by the travel configuration’s includeShiftTags attribute are included in the maximum travel distance check.
With shiftTagMatches set to ALL
, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift.
With shiftTagMatches set to ANY
, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.
If defined, only shifts not containing tags defined by the travel configuration’s excludeShiftTags attribute are included in the maximum travel distance check.
With shiftTagMatches set to ALL
, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
With shiftTagMatches set to ANY
, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.
The rule can define either includeShiftTags or excludeShiftTags, but not both.
Use the constraint configuration’s minimizeTravelDistanceWeight attribute to update the weight of the constraint.
Configuration example to minimize the distance travelled for all shifts.
"travelConfiguration": { }
Configuration example to minimize the distance travelled for all ICU shifts:
"travelConfiguration": { "includeShiftTags": ["ICU"] }
Configuration example to minimize the distance travelled for all ICU shifts, or Cardiology shifts.
"travelConfiguration": { "includeShiftTags": ["ICU", "Cardiology], "shiftTagMatches": "ANY" }
Score analysis justification example:
"justification": { "employee": "Ann Green", "shift": "ICU-shift-location-A", "distanceInMeters": 5500 }
5. Output structure
5.1. Run information
Contains information about the solver run, such as the run identifier and solver status.
"run": { "id": "3ffe8e6c-0b09-408b-b610-7550e8e401e6", "name": "BASIC", "submitDateTime": "2024-05-16T10:00:45.676469+02:00", "startDateTime": "2024-05-16T10:00:45.720273+02:00", "completeDateTime": null, "solverStatus": "SOLVING_ACTIVE", "score": "0hard/0medium/-1505soft", "tags": [] }
5.2. Model output
Contains solution data, such as shifts and employees assigned to them.
"modelOutput": { "shifts": [ { "id": "1", "employee": "Elsa Li" }, { "id": "2", "employee": "Elsa Watt" } ], }
6. Additional features
6.1. Score analysis
Use this feature to understand the score structure of your schedule. It provides a detailed breakdown of the score, including the score of each constraint and justifications. Justifications are objects that contribute to violating, or meeting the constraint, for example an employee and two overlapping shifts that are assigned to them. This is especially useful when you want to highlight the violations in your user interface.
The score analysis is automatically calculated and stored at the end of each solver run.
The score analysis endpoint optionally accepts a boolean includeJustifications
query parameter to control whether the justifications are included in the response.
This can be useful to reduce the response size when you only need a top-level score breakdown.
GET /v1/schedules/{id}/score-analysis
{ "score": "0hard/-100medium/-600soft", "constraints": [ { "name": "Employee is paired with preferred employee", "weight": "0hard/0medium/1soft", "score": "0hard/0medium/0soft", "matches": [] }, { "name": "Employee works during preferred time", "weight": "0hard/0medium/1soft", "score": "0hard/0medium/4320soft", "matches": [] }...
GET /v1/schedules/{id}/score-analysis?includeJustifications=true
{ "score": "0hard/-100medium/-600soft", "constraints": [ { "name": "Employee is paired with preferred employee", "weight": "0hard/0medium/1soft", "score": "0hard/0medium/0soft", "matches": [] }, { "name": "Employee works during preferred time", "weight": "0hard/0medium/1soft", "score": "0hard/0medium/4320soft", "matches": [ { "score": "0hard/0medium/360soft", "justification": { "shift": "11", "employee": "Beth Jones", "overlappingTimeSpans": [ { "start": "2024-03-12T00:00:00Z", "end": "2024-03-13T00:00:00Z", "includeShiftTags": [], "excludeShiftTags": [], "shiftTagMatches": "ALL" } ] } }...
Consider other use case where you have solved a schedule and want to fine tune it manually afterward. For example, assign a shift to a different employee. Use the score analysis to understand the impact of the change on the score and to validate that the new schedule is feasible.
POST /v1/schedules/score-analysis?includeJustifications=true
The endpoint accepts a schedule object in the request body.
{ "score": "0hard/0medium/-1200soft", "constraints": [ { "name": "Employee is paired with preferred employee", "weight": "0hard/0medium/1soft", "score": "0hard/0medium/0soft", "matches": [] }, { "name": "Employee works during unpreferred time", "weight": "0hard/0medium/1soft", "score": "0hard/0medium/-960soft", "matches": [ { "score": "0hard/0medium/-480soft", "justification": { "shift": "177", "employee": "Dan Jones21", "overlappingTimeSpans": [ { "start": "2024-03-19T00:00:00Z", "end": "2024-03-20T00:00:00Z", "includeShiftTags": [], "excludeShiftTags": [], "shiftTagMatches": "ALL" } ] } }...
6.2. Recommend Employee
Use this feature to react to abrupt changes in daily operations. Consider a case where an unexpected emergency happens, and you need to find an employee to handle it, while respecting the current schedule. The Recommend Employee API allows you to get multiple suggestions on staffing the new shift in a quick way. The employee recommendations are sorted by quality, with the best fit first.
POST /v1/schedules/{id}/recommendations/recommend-employees
6.2.1. Recommend Employee API input
Description of Recommend Employee API input.
Name | Required | Format | Description | Example |
---|---|---|---|---|
Max number of recommendations |
true |
int |
Upper limit for a number of employees to recommend for a new shift. |
|
Fit shift id |
true |
string |
Identifier of the shift to get the employee recommendations for. The shift with given identifier needs
to be a part of the |
|
Config |
false |
object |
Configuration that allows to customize constraint weights. |
|
Model input |
true |
object |
Model input with schedule that contains shift with identifier specified by |
`"modelInput": { "contracts": [ { "id": "Default Contract", "consecutiveDaysWorkedRules": [ { "minimum": null, "maximum": 6, … } ` |
6.2.2. Recommend Employee API output
Description of Recommend Employee API output.
Name | Format | Description | Example |
---|---|---|---|
Score diff |
string |
Total score difference between the new solution with the fitted shift and the solution without the fitted shift. |
|
Constraint diffs |
array |
Per-constraint score difference between the new solution with the fitted shift and the solution without the fitted shift. |
`"constraintDiffs": [ { "score": "0hard/100medium/0soft", "constraintName": "Unassigned shift" }, … ` |
Employee id |
string |
Identifier of the recommended employee. |
`"employeeId": "Amy Smith" ` |