Docs
  • Solver
  • Models
    • Field Service Routing
    • Employee Shift Scheduling
  • Platform
Try models
  • Employee Shift Scheduling
  • Employee Shift Scheduling User Guide

Employee Shift Scheduling

    • Introduction
    • Planning AI concepts
    • Metrics and optimization goals
    • Getting started with employee shift scheduling
    • Understanding the API
    • Employee Shift Scheduling User Guide
    • Employee resource constraints
      • Employee availability
      • Employee contracts
      • Employee contracts: Period rules
      • Employee contracts: Shift rules
      • Fairness
      • Pairing employees
      • Shift travel and locations
    • Shift service constraints
      • Alternative shifts
      • Demand and supply
      • Resource-limited planning
      • Shift sequence patterns: single day shifts
      • Shift sequence patterns: daily shift pairings
      • Skills and risk factors
    • Recommendations
    • Real-time planning
    • Time zones and Daylight Saving Time (DST)
    • New and noteworthy
    • Upgrading to the latest versions
    • Feature requests

Employee Shift Scheduling User Guide

1. Terms

Term Description

Employee

Employee that can be assigned to a shift.

Contract

Employee contract that defines settings specific to a group of employees (e.g. maximum number of minutes worked per month).

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).

Shift group

Group of shifts with different assignment criteria (e.g. single shift assigned within a group).

Global rules configuration

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.

Example 1. List sample datasets REST API endpoint call

GET /v1/demo-data

Example 2. Get sample dataset REST API endpoint call

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.

Example 3. Submit problem dataset REST API endpoint call

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.

Example 4. Check status REST API endpoint call

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.

Example 5. Terminate solving REST API endpoint call

DELETE /v1/schedules/{id}

2.1.5. Get all solving processes

Get info about the status of all solving processes.

Example 6. Terminate solving REST API endpoint call

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 containing:

    • spentLimit - The maximum duration to keep the solver running (ISO 8601 Duration). If omitted, no maximum duration will be set (platform limits will apply).

    • unimprovedSpentLimit - The maximum unimproved score duration, i.e. if the score has not improved during this period, the solver will terminate (ISO 8601 Duration). If omitted, the diminished returns termination will be used.

      The diminished returns termination is the recommended default setting. This termination is desirable since it terminates based on the relative rate of improvement, and behaves similarly on different hardware and different problem instances. unimprovedSpentLimit should be set only when necessary.
  • 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 Time zones 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.

"id": "Elsa Green"

Contracts

false

array

Identifiers of employee contracts.

"contracts": [ "Default Contract" ]

Priority

false

enum

Employee priority. Employee preferences are more likely to be satisfied for employees with higher priority.

"priority": "NORMAL"

Cost group

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.

"costGroup": "Senior 1"

Location

false

array

Location of the employee.

"location": [51.0441461, 3.7336349]

Skills

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.

"skills": [ { "id": "LCSW cert", "validityDateTimeSpans": [ { "start": "2023-12-11T00:00:00Z", "end": "2024-01-11T00:00:00Z" } ] } ]

Tags

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).

"tags": [ "Part time" ]

Preferred shift tags

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.

"preferredShiftTags": [ "Department A", "Team X" ]

Required shift tags

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.

"requiredShiftTags": [ "Department A" ]

Prohibited risk factors

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).

"prohibitedRiskFactors": [ "COVID-19" ]

Preferred pairings

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.

"preferredPairings": [ { "pairedEmployee": "Elsa Li", "onlyForShiftTags": [ "afternoon" ] } ]

Unpreferred pairings

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.

"unpreferredPairings": [ { "pairedEmployee": "Elsa Li", "onlyForShiftTags": [ "afternoon" ] } ]

Required pairings

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.

"requiredPairings": [ { "pairedEmployee": "Elsa Li", "onlyForShiftTags": [ "afternoon" ] } ]

Prohibited pairings

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.

"prohibitedPairings": [ { "pairedEmployee": "Elsa Li", "onlyForShiftTags": [ "afternoon" ] } ]

Preferred time spans

false

array

List of preferred time spans. Use to express time spans where employee prefers to work, optionally only for shifts with specific tags.

"preferredTimeSpans": [ { "start": "2023-11-08T00:00:00Z", "end": "2023-11-09T00:00:00Z", "includeShiftTags": [ "Location London" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" } ]

Unpreferred time spans

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.

"unpreferredTimeSpans": [ { "start": "2023-11-08T00:00:00Z", "end": "2023-11-09T00:00:00Z", "includeShiftTags": [ "Location London" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" } ]

Unavailable time spans

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.

"unavailableTimeSpans": [ { "start": "2023-11-08T00:00:00Z", "end": "2023-11-09T00:00:00Z", "includeShiftTags": [ "Location London" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" } ]

Available time spans

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.

"availableTimeSpans": [ { "start": "2023-11-08T00:00:00Z", "end": "2023-11-09T00:00:00Z", "includeShiftTags": [ "Location London" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" } ]

Time zone offset

false

string

Time zone offset is now deprecated in favour of Time zone ID.

The employee time zone offset to UTC.

Taken into account by employee period rules, see Time zones and Daylight Saving Time (DST).

The default value is "Z" for UTC+0.

"zoneOffset": "+01:00"

Time zone ID

false

time zone id

The ID of the time zone where the employee resides.

Taken into account by employee period rules, see Time zones and Daylight Saving Time (DST).

The default value is "Z" for UTC+0 with no DST active.

"timeZoneId": "Europe/Brussels"

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.

"id": "Default Contract"

Priority

false

string

A weight that determines how many times a contract will penalise. The REQUIRED rules of contracts are not affected by this weight, so only the soft score will be impacted if a priority is set. By default, the highest priority is "1" and the lowest priority is "10". They respectively have the weights: 10 and 1. This means that a contract with priority "1" will have 10 times the impact of an identical contract with priority "10".

"priority": 6

Consecutive days worked rules

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 shiftTypeTagCategories attribute to work with sequences of shifts having the same tag, for example "morning" and "night". The shift must always have at most one tag defined by the shiftTypeTagCategories attribute, meaning that the shift cannot have both "morning" and "night" tags.

Consecutive days worked rules with a minimum and REQUIRED satisfiability are deprecated. Only set minima with PREFERRED satisfiability.

shiftTagMatches can be set to ALL or ANY. If omitted, the default is ALL.

"consecutiveDaysWorkedRules": [ { "id": "min3Max5ConsecutiveICUDays" "minimum": 3, "maximum": 5, "satisfiability": "REQUIRED", "includeShiftTags": [ "ICU" ] "excludeShiftTags": null, "shiftTagMatches": "ALL", "shiftTypeTagCategories": null } ]

Period rules

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 shiftTypeTagCategories attribute to work with groups of shifts having the same tag, for example "morning" and "night". The shift must always have at most one tag defined by the shiftTypeTagCategories attribute, meaning that the shift cannot have both "morning" and "night" tags. Use this to express minimum, or maximum unique shift types that an employee works in a period, for example a preference to work only "morning" shifts. The period rule can optionally define a ruleValidityDateTimeSpan to limit the rule to a specific time span. To learn more about period rule validity, please see the Employee contract period rule.

"periodRules": [ { "id": "max480ICUMinutesPerDay", "period": "DAY", "satisfiability": "REQUIRED", "includeShiftTags": [ "ICU" ] "excludeShiftTags": null, "shiftTagMatches": "ALL", "minutesWorkedMin": null, "minutesWorkedMax": 480, "minutesLoggedMin": null, "minutesLoggedMax": null, "shiftsWorkedMin": null, "shiftsWorkedMax": null, "daysWorkedMin": null, "daysWorkedMax": null, "shiftTypesTagCategories": null, "shiftTypesWorkedMin": null, "shiftTypesWorkedMax": null, "locationsWorkedMax": null, "uniqueTagsLimit": null, "shiftStartTimeDifferenceInMinutesMax": null, "daysOffLimit": null, "consecutiveDaysOffLimit": null, }

Rolling window rules

false

array

Rules that use a rolling window approach. This validates that minimum/maximum are met in any configured number of consecutive hours, days, or weeks. Use this to express preferences/requirements of employees to work a certain number of minutes/shifts/days in a rolling window, optionally only for shifts with specific tags, for example, a maximum of 3 ICU shifts in any consecutive 7 days.

"rollingWindowRules": [ { "id": "Max5ShiftsInAny7ConsecutiveDays", "includeShiftTags": ["ICU"], "rollingWindow": { "type": "DAILY", "length": 7 }, "shiftsWorkedLimit": { "shiftsWorkedMax": 5 } } ]

Shift rotation rules

false

array

Configuration of shift rotation rules. Use this to configure rotation patterns of shifts,"
" for example alternating a week of day shifts and a week of night shifts.

"shiftRotationRules": [ { "id": "rotateShortAndLongShiftsWeekly", "rotationPeriod": { "builtInRotationPeriod": "WEEK" }, "rotationGroups": [ { "id": "shortShifts", "includeShiftTags": [ "short" ], "shiftTagMatches": "ANY" }, { "id": "longShifts", "includeShiftTags": [ "long" ], "shiftTagMatches": "ANY" } ]

Avoid shift close to day off request rules

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.

"avoidShiftCloseToDayOffRequestRules": [ { "id": "noNightAndMorningShiftsNearDayOff", "avoidPriorShiftTags": [ "NIGHT" ], "avoidAfterShiftTags": [ "MORNING", "DEPARTMENT_A" ], "shiftTagMatches": "ANY", "satisfiability": "PROHBITED" } ]

Minutes between shifts rules

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 minimumConsecutivePriorShifts attribute to work with a daily sequence of prior shifts. Use this to express minimum or maximum minutes between a sequence of shifts and another shift, for example a need to take 48 hours off after a sequence of "night" shifts. The current implementation supports values 1 (default), or 2 for minimumConsecutivePriorShifts attribute. Additionally, the rule can optionally define a scope. The scope will limit which pairs of shifts the rule is applied to. The scope excludes shift pairs where the start of the later shift is after the end of the prior shift plus the scope duration.

"minutesBetweenShiftsRules": [ { "id": "min600MinutesBetweenNightAndICUShift", "requiredPriorShiftTags": [ "NIGHT" ], "requiredAfterShiftTags": [ "ICU" ], "minimumConsecutivePriorShifts": 1, "shiftTagMatches": "ANY", "satisfiability": "REQUIRED", "minimumMinutesBetweenShifts": 600, "maximumMinutesBetweenShifts": null, "scope": { "type": "duration", "duration": "P1D" } } ]

Minimize gaps between shifts rules

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.

"minimizeGapsBetweenShiftsRules": [ { "id": "minimizeGapsBetweenShiftsRule", "requiredPriorShiftTags": [ "split-shift" ], "requiredAfterShiftTags": [ "split-shift" ], "shiftTagMatches": "ANY", "maximumMinutesBetweenSplitShifts": 120 } ]

Daily shift pairing rules

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.

"dailyShiftPairingRules": [ { "id": "noAfternoonShiftWithMorningShiftNextDay", "shiftTags": [ "AFTERNOON", ], "pairedShiftTags": [ "MORNING" ], "dayOffset": 1, "shiftTagMatches": "ANY", "satisfiability": "PROHIBITED" } ]

Single day shift sequence pattern rules

false

array

Settings for shift sequence patterns that span across a single day. Use this to specify a pattern of shifts that should, or should not follow each other on the same day, optionally only for shifts with specific tags. Use ordered to specify whether following the pattern order is required, by default this is true.

Please note that REQUIRED patterns are being deprecated, and will be replaced by high-weight PREFERRED patterns.

"singleDayShiftSequencePatternRules": [ { "id": "earlyShiftFollowedByLateShift", "satisfiability": "REQUIRED", "pattern": [ { "includeShiftTags": [ "Early" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" }, { "includeShiftTags": [ "Late" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" } ], ordered: true } ]

Multi day shift sequence pattern rules

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 type attribute: ON and OFF. The ON pattern requires that employee works on the specified day, while the OFF pattern requires that employee does not work on the specified day.

Please note that if you use a pattern starting or ending with OFF, you must specify the planning window interval to ensure the pattern matches properly throughout the period you are planning for.

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 shiftMatches attribute.

The pattern satisfiability defines if the pattern is PREFERRED, PROHIBITED, or UNPREFERRED: Matching a PROHIBITED pattern adds a hard penalty to the solution score. Matching a PREFERRED pattern adds a soft reward, while matching an UNPREFERRED pattern adds a soft penalty to the solution score.

Please note that REQUIRED patterns have been deprecated, and will be replaced by high-weight PREFERRED patterns.

You may also specify the weight of this pattern to make it more important than another pattern (the default value is 1). For example, setting the weight to 2 will make the reward/penalty of this pattern’s elements count twice when matched.

"multiDayShiftSequencePatternRules": [ { "id": "earlyOffLateOffPattern", "satisfiability": "PREFERRED", "weight": 2, "pattern": [ { "type": "ON", "includeShiftTags": [ "Early" ], "excludeShiftTags": null, "shiftTagMatches": "ALL", "shiftMatches": "ALL" }, { "type": "OFF", }, { "type": "ON", "includeShiftTags": [ "Late" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" }, { "type": "OFF" } ] } ]

Allow overlapping shifts rules

false

array

Rules tied to shift overlap. Use this to allow employees to work overlapping shifts with specified tags.

"allowOverlappingShiftsRules": [ { "id": "allowOverlapWithOnCallShift", "includeShiftTags": [ "On call" ] "excludeShiftTags": null, "shiftTagMatches": "ALL" } ]

Travel Configurations

false

array

These TravelConfigurations allow for more fine grain control over the maximum travel distance to a shift and the minimum time between shifts, than the TravelConfiguration defined in the Schedule Parametrization (which is deprecated). The rules defined on the contracts also allow for a ruleValidityDateTimeSpan to be set, in which they are active.

When the validityDateTimeSpans of 2 rules of a contract overlap, a validation warning will be triggered and if the tags don’t exclude each other, matching shifts will be penalized for each of the overlapping rules.

Global Travel Configurations are now deprecated.

Each employee can only specify 1 contract that has travel configurations.

"travelConfigurations": [ { "id": "travelDistanceAndTimeBetweenShifts" "maxEmployeeToShiftTravelDistanceInMeters": 99999, "minMinutesBetweenShiftsInDifferentLocations": 239, "ruleValidityDateTimeSpan": { "start": "2023-12-11T00:00:00Z", "end": "2024-01-11T00:00:00Z" }, "includeShiftTags": ["morning"], "excludeShiftTags": ["evening"], "shiftTagMatches": "ANY", "excludeMatchingShiftTagTypes": ["Team"] } ]

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.

"icu-afternoon-10-11-2023"

Start

true

string, ISO-8601

Start time of the shift.

"start": "2023-11-11T09:00:00Z"

End

true

string, ISO-8601

End time of the shift.

"end": "2023-11-11T17:00:00Z"

Logged time

false

string, ISO-8601 Duration

The logged duration of the shift. It can be used to specify an alternative shift duration for contractual period rules.

"loggedTime": "PT4H30M"

Cost group

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.

"costGroup": "Project A long shift"

Location

false

array

Location of the shift.

"location": [51.0441461, 3.7336349]

Required skills

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.

"requiredSkills": [ "Nurse" ]

Preferred skills

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.

"preferredSkills": [ "Volunteer" ]

Risk factors

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).

"riskFactors": [ "COVID-19" ]

Tags

false

array

List of shift tags. Use to express additional shift data (e.g. shift type, department).

"tags": [ "AFTERNOON", "DEPARTMENT_A" ]

Preferred employees

false

array

List of preferred shift employees. Use to express employees that are preferred to work on a shift.

"preferredEmployees": [ "Elsa Green" ]

Unpreferred employees

false

array

List of preferred shift employees. Use to express employees that are unpreferred to work on a shift.

"unpreferredEmployees": [ "Elsa Green" ]

Prohibited employees

false

array

List of prohibited shift employees. Use to express employees that are prohibited to work on a shift.

"prohibitedEmployees": [ "Elsa Green" ]

Assignment priority

false

int

Deprecated - use priority field. Defines priority for shift assignment where 1 is the highest priority and 5 is the lowest priority.

"assignmentPriority": 2

Priority

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.

"priority": "5"

Pinned

false

boolean

Shift pin. Use to fix shift assignment to a specific employee / no employee (employee attribute).

"pinned": false

Employee

false

reference

Employee assigned to the shift. Can be changed by the solver depending on the value of pinned attribute.

"employee": "Amy Smith"

3.3.4. Shift Group

Group of shifts with different assignment criteria (e.g. single shift assigned within a group). Each shift can belong to at most one group.

Name Required Format Description Example

Id

true

string

Unique string identifier of the group.

"Group A"

Tags

false

array

List of shift tags. Use to express additional shift group data (e.g. shift group type, department).

"tags": [ "GROUP_A", "DEPARTMENT_B" ]

Shifts

false

array

List of shifts identifiers belonging to this group. A shift can belong to at most one shift group.

"shifts": [ "2025-01-01-morning", "2025-01-01-afternoon" ]

3.3.5. Global rules configuration

Configuration of global rules that apply to all employees and shifts (e.g. fairness configuration).

Name Required Format Description Example

Balance time worked rules

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 employeeToPublishedMinutesWorked attribute to specify the number of minutes worked by each employee in the past.

"balanceTimeWorkedRules": [ { "id": "balanceNightShiftTimeWorkedForPartTimeEmployees", "includeEmployeeTags": null, "excludeEmployeeTags": [ "Part time" ], "employeeTagMatches": "ALL", "includeShiftTags": [ "NIGHT" ], "excludeShiftTags": null, "shiftTagMatches": "ALL", "employeeToPublishedMinutesWorked": { "Elsa Green": 9600 } } ]"

Balance shift count rules

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 employeeToPublishedShiftCount attribute to specify the number of shifts worked by each employee in the past.

"balanceShiftCountRules": [ { "id": "balanceNightShiftCountForPartTimeEmployees", "includeEmployeeTags": null, "excludeEmployeeTags": [ "Part time" ], "employeeTagMatches": "ALL", "includeShiftTags": [ "NIGHT" ], "excludeShiftTags": null, "shiftTagMatches": "ALL", "employeeToPublishedShiftCount": { "Elsa Green": 20 } } ]"

Hourly demand rules

false

array

Configuration of hourly demand rules. Rules tied to hourly demand. Use this to express global preference, or a requirement to fulfill "
"a certain number of shifts in hourly intervals, optionally only for shifts with specific tags.

Hourly demand rules with a minimum and REQUIRED satisfiability are deprecated. Only set minima with PREFERRED satisfiability.

"minimumMaximumShiftsPerHourlyDemand": [ { "id": "HourlyDemand", "includeShiftTags": [ "Location A" ], "demandDetails": [ { "startDateTime": "2024-05-01T00:00:00Z", "endDateTime": "2024-05-01T01:00:00Z", "minDemand": 20 }, { "startDateTime": "2024-05-01T01:00:00Z", "endDateTime": "2024-05-01T02:00:00Z", "minDemand": 22 } ] } ]

Costs rule

false

array

Configuration of costs rule. Use this to make sure the total costs of shift assignments are in the required range.

Costs rules with a minimum and REQUIRED satisfiability are deprecated. Only set minima with PREFERRED satisfiability.

Please see Time zones and Daylight Saving Time (DST) when working with multiple time zones or DST.

"costsRules": [ { "id": "max10kPerPayPeriod", "period": "PAY_PERIOD", "includeShiftTags": null, "excludeShiftTags": null, "shiftTagMatches": "ALL", "satisfiability": "PREFERRED", "employeeShiftCostDetails": [ { "employeeCostGroup": "EMPLOYEE_COST_GROUP_A", "shiftCostGroup": "SHIFT_COST_GROUP_A", "cost": 20 }, { "employeeCostGroup": "EMPLOYEE_COST_GROUP_B", "shiftCostGroup": "SHIFT_COST_GROUP_A", "cost": 50 }, { "employeeCostGroup": "EMPLOYEE_COST_GROUP_A", "shiftCostGroup": "SHIFT_COST_GROUP_B", "cost": 20 }, { "employeeCostGroup": "EMPLOYEE_COST_GROUP_B", "shiftCostGroup": "SHIFT_COST_GROUP_B", "cost": 80 } ], "totalCostsMin": null, "totalCostsMax": 10000, "zoneOffset": "Z", "periodShiftOverlapKind": "START_ONLY" } ]

Minimum maximum number of shifts worked per period

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.

shiftTagMatches can be set to ALL or ANY. If omitted, the default is ALL.

Setting a minimum with REQUIRED satisfiability is deprecated. Only set minima with PREFERRED satisfiability.

Please see Time zones and Daylight Saving Time (DST) when working with multiple time zones or DST.

"minimumMaximumShiftsPerPeriod": [ { "id": "min3ShiftsPerDay", "period": "DAY", "satisfiability": "PREFERRED", "includeEmployeeTags": [ "Full-Time" ], "includeShiftTags": [ "ICU" ], "shiftTagMatches": "ALL", "shiftsWorkedMin": 3, "zoneOffset": "Z" }

Disruption rules

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 } ]

Shift tag match rules

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.

"shiftTagMatchRules": [ { "id": "matchOrgUnit", "satisfiability": "PREFERRED", "tagTypeMatchMultipliers": { "Team": 1000000, "Department": 1000 } } ]

Unassigned shift rule

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.

"unassignedShiftRule": { "id": "unassignedShiftRule", "priorityWeights": [ { "priority": "1", "weight": 100 }, { "priority": "2", "weight": 10, "assignment": "OPTIONAL" }, { "priority": "custom", "weight": 1, "assignment": "MANDATORY" } ] }

Shift group rules

false

array

Configuration of shift group rules. Use this to control how shifts are assigned within a group, for example making sure that only one shift is assigned within a group. See Required shift group assignment mode not met rule for more information.

"shiftGroupRules": [ { "id": "singleShiftForDepartmentAGroups", "includeGroupTags": ["DEPARTMENT_A"], "assignmentMode": { "type": "SINGLE_SHIFT" } } ]

Concurrent shifts rules

false

array

Configuration of concurrent shifts rules. Use this to limit how many shifts can take place at the same time, for example, if the shifts use a shared resource with limited capacity.

"concurrentShiftsRules": [ { "id": "noMoreThan2ConcurrentShiftsForResourceA", "includeShiftTags": ["Resource-A"], "concurrentShiftsMax": 2 } ]

3.3.6. Schedule Parameterization

3.3.6.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 specified weekStart 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 WEEK period should start on.

"TUESDAY"

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.

"periods": [ { "id": "PAY_PERIOD", "dateSpans": [ { "start": "2023-01-01", "end": "2023-01-15" } ]}]

Travel configuration

false

object

Deprecated use travel configurations in contracts instead.

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.

"travelConfiguration": { "maxEmployeeToShiftTravelDistanceInMeters": 100000, "minMinutesBetweenShiftsInDifferentLocations": 240, "excludeMatchingShiftTagTypes": ["Team"] }

3.3.7. 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.8. 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.9. Tags

Name Required Format Description Example

Id

true

string

Unique string identifier of the tag.

"id": "Belgium"

Tag type

true

string

Identifiers of the tag type.

"tagType": "Country"

3.3.10. Tag types

Name Required Format Description Example

Id

true

string

Unique string identifier of the tag type.

"id": "Country"

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:

  1. 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.

  2. Value of period rule satisfiability attribute is set to REQUIRED.

Setting a minutesWorkedMin with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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. Logged minutes worked per period not in required range for employee

Employee contracts can define several period rules. The constraint triggers if all conditions below apply:

  1. Number of minutes logged by the employee in a period is below the value of the period rule’s minutesLoggedMin, or above the value of period rule minutesLoggedMax.

  2. Value of period rule satisfiability attribute is set to REQUIRED.

Setting a minutesLoggedMin with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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"
  },
  "minutesLogged": 600
}

4.1.5. 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:

  1. 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.

  2. Value of period rule satisfiability attribute is set to REQUIRED.

Setting a shiftsWorkedMin with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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.6. Unique tags per period not in required range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The number of tags defined by the unique tags limit’s includeTagTypes, on shifts assigned to the employee in a period is above the value of the period rule’s unique tags limit’s tagsMax. Only the tags of the types defined on the unique tags limit’s includeTagTypes are counted.

  2. The value of the period rule’s satisfiability attribute is set to REQUIRED.

The tags and their types need to be configured as documented in Tags and tag types.

If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the calculation of the total number of unique tags per period. 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 calculation of the total number of unique tags per period. 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.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": "Beth3UniqueTagsPerDay",
  "dateSpan": {
    "start": "2023-11-10T00:00:00Z",
    "end": "2023-11-11T00:00:00Z"
  },
  "uniqueTagAmount": 4
}

4.2. Shift start time difference in minutes per period not in required range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The time between the earliest shift and the latest shift in this period is larger than this period rule’s shiftStartTimeDifferenceInMinutesMax.

  2. 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 calculation of the difference in shift start times. 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 calculation of the difference in shift start times. 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.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": "maxShiftStartTimeDifferenceOf60min",
  "dateSpan": {
    "start": "2023-11-10T00:00:00Z",
    "end": "2023-11-11T00:00:00Z"
  },
  "shiftStartTimeDifference": 120
}

4.2.1. 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:

  1. The number of the shift locations assigned to the employee in a period is above the value of the period rule’s locationsWorkedMax.

  2. 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.

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.2.2. Days off per period not in required range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The number of days off during a period is lower than the defined minimum: daysOffLimit.daysOffMin. The includeDays field on the daysOffLimit determines which days will be counted to the total number of days off. If the daysOffLimit is not defined all days will be counted towards the total, else only the supplied days will be counted. E.g. includeDays is set to ["SUNDAY"] and daysOffMin is set to 3 so the constraint will verify that at least 3 sundays are free of shifts.

  2. 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 days off. 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 days off. 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.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": max3SundaysOffPerMonth"",
  "dateSpan": {
    "start": "2023-11-01T00:00:00Z",
    "end": "2023-12-01T00:00:00Z"
  },
  "daysOff": 5
}

4.2.3. Consecutive days off per period not in required range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The number of consecutive days off during a period is lower than the defined minimum: consecutiveDaysOffLimit.consecutiveDaysOffMin.

  2. 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 consecutive days off. 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 consecutive days off. 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.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": "min2ConsecutiveDaysOffPerWeek",
  "dateSpan": {
    "start": "2023-11-01T00:00:00Z",
    "end": "2023-11-08T00:00:00Z"
  },
  "consecutiveDaysOff": 1
}

4.2.4. 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:

  1. 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.

  2. Value of the period rule’s satisfiability attribute is set to REQUIRED.

Setting a daysWorkedMin with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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.2.5. 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:

  1. 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.

  2. A shift has exactly one tag defined by the shiftTypeTagCategories attribute. The value of this tag defines the shift type.

  3. Value of the period rule’s satisfiability attribute is set to REQUIRED.

Setting a shiftTypesWorkedMin with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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.2.6. 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:

  1. 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.

  2. Value of the period rule’s satisfiability attribute is set to REQUIRED.

Setting a minimum with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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.2.7. Shifts worked in rolling window not in required range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is above the value of the rule’s shiftsWorkedLimit.shiftsWorkedMax.

  2. Value of the 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 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.

The rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Combination of HOURLY rolling window and shiftsWorkedLimit is not yet supported and will be provided in future versions.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Max2IcuShiftsPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "shiftsWorked": 3
}

4.2.8. Days worked in rolling window not in required range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is above the value of the rule’s daysWorkedLimit.daysWorkedMax.

  2. Value of the 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 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 days 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.

The rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Combination of HOURLY rolling window and daysWorkedLimit is not yet supported and will be provided in future versions.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Max5WorkingDaysPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "daysWorked": 6
}

4.2.9. Minutes worked in rolling window not in required range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is above the value of the rule’s minutesWorkedLimit.minutesWorkedMax.

  2. Value of the 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 minutes 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 minutes 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.

The rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Max2400MinutesPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "minutesWorked": 2600
}

4.2.10. Consecutive days off in rolling window not in required range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is below the value of the rule’s consecutiveDaysOffLimit.consecutiveDaysOffMin.

  2. Value of the 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 calculation of the days off. 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 calculation of the days off. 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 rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Combination of HOURLY rolling window and consecutiveDaysOffLimit is not yet supported and will be provided in future versions.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Min2ConsecutiveDaysOffPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "maxConsecutiveDaysOff": 1
}

4.2.11. Consecutive minutes off in rolling window not in required range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of consecutive minutes between shifts assigned to the employee in a rolling window is below the value of the rule’s consecutiveMinutesOffLimit.consecutiveMinutesOffMin.

  2. Value of the 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 calculation of the minutes off. 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 calculation of the minutes off. 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 rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Min2400ConsecutiveMinutesOffPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "maxConsecutiveMinutesOff": 2000
}

4.2.12. Required shift rotation not met for employee

Employee contracts can define shift rotation rules.

Use this to make sure that the employee’s shift types alternate in consecutive periods, for example, "morning" shifts on week 1 and "evening" shifts on week 2.

The constraint triggers if all conditions below apply:

  1. Employee works the same shift type in two consecutive periods.

  2. Value of the rule’s satisfiability attribute is set to REQUIRED.

The period is defined by the builtInRotationPeriod attribute. At the moment, we support builtInRotationPeriod.type WEEK.

The shift type is defined by the rotationGroups attribute. Create a rotation group for each shift type, or a group of similar shift types. For example, you can create a group that includes "morning" shifts and another group that includes both "afternoon" and "evening" shifts.

If defined, only shifts containing tags defined by the rule’s rotationGroups.includeShiftTags attribute are included in the group. With shiftTagMatches set to ALL, all tags defined by the rule’s rotationGroups.includeShiftTags attribute have to be present in the shift. With shiftTagMatches set to ANY, at least one tag defined by the rule’s rotationGroups.includeShiftTags attribute has to be present in the shift. The rule can define either includeShiftTags or excludeShiftTags, not both.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "shift1": "morning-week-25",
  "shift2": "morning-week-26",
  "shiftRotationRule": "rotate-shift-types-weekly"
}

4.2.13. 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:

  1. 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.

  2. Value of period rule satisfiability attribute is set to REQUIRED.

Setting a shiftsWorkedMin with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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.2.14. Required shift group assignment mode not met

Global rules configuration can define one or more shift group rules. Use this to control how shifts are assigned within a group, for example making sure that only one shift is assigned within a group, optionally only for shift groups with specific tags.

The constraint triggers if the value of the rule’s assignmentMode attribute is defined.

If defined, only shift groups containing tags defined by rule’s includeGroupTags attribute are matched by the rule. By default, all shift groups are matched.

The model currently supports one assignment mode type: SINGLE_SHIFT. This mode enforces that at most one shift is assigned within a group.

Consider a use case where you have a piece of work that needs to be done by an employee. Perhaps a demonstration of a new product, or a repair job. There are different possible time slots for the work, but it will only be done once.

First, define a shift for every possible time slot.

"shifts": [
  {
    "id": "product-demo-01-20-2025-1",
    "start": "2025-01-20T08:00:00Z",
    "end": "2025-01-20T12:00:00Z"
  },
  {
    "id": "product-demo-01-20-2025-2",
    "start": "2025-01-20T10:00:00Z",
    "end": "2025-01-20T14:00:00Z"
  },
  {
    "id": "product-demo-01-20-2025-3",
    "start": "2025-01-20T14:00:00Z",
    "end": "2025-01-20T18:00:00Z"
  }
]

Then, create a shift group for the work.

"shiftGroups": [
  {
    "id": "product-demo",
    "shifts": ["product-demo-01-20-2025-1", "product-demo-01-20-2025-2", "product-demo-01-20-2025-3"]
  }
]

Finally, create a shift group rule that enforces that only one shift is assigned within the group.

"shiftGroupRules": [
  {
    "id": "global-single-shift-per-group",
    "assignmentMode": {
      "type": "SINGLE_SHIFT"
    }
  }
]

Score analysis justification example:

{
  "shiftGroupRule": "global-single-shift-per-group",
  "shiftGroup": "product-demo",
  "groupShiftsWorked": 2
}

4.2.15. Concurrent shifts worked not in required range

Global rules configuration can define one or more concurrent shifts rules. The constraint makes sure the number of shifts, that take place at the same time, are in the required range.

The constraint triggers if the number of concurrent shifts exceed the value of the rule’s concurrentShiftsMax attribute.

If defined, only shifts containing tags defined by the period rule’s includeShiftTags attribute are included. 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. 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 rule’s ruleValidityDateTimeSpan attribute to optionally define the validity of the rule.

Consider a use case where you have a limited number of stalls available for a product demonstration. At most two stalls can be used at the same time.

"concurrentShiftsRules": [
{
  "id": "noMoreThan2ConcurrentShiftsForProductDemo",
  "includeShiftTags": ["Stall-A"],
  "concurrentShiftsMax": 2
}]

Score analysis justification example:

{
  "concurrentShiftsRule": "noMoreThan2ConcurrentShiftsForProductDemo",
  "intervalStart": "2025-05-01T08:00:00Z"
  "intervalEnd": "2025-05-01T12:00:00Z"
}

4.2.16. 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:

  1. 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.

  2. Value of the period rule’s satisfiability attribute is set to REQUIRED.

Setting a totalCostsMin with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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:

By default, this type of rule only counts shifts if the shifts started within the defined period. If you define a rule that says that an employee can only work 1 shift a day, then it won’t count a night shift that started on the previous day but ends at e.g. 6 a.m. This means that the solver will still try to assign a shift to this day. To change this behavior change the field periodShiftOverlapKind from START_ONLY to START_AND_END.

{
  "costsRule": "Max20kPerMonth",
  "dateSpan": {
    "start": "2023-11-01T00:00:00Z",
    "end": "2023-12-01T00:00:00Z"
  },
  "cost": 22000
}

4.2.17. 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.2.18. 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.2.19. 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.2.20. 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.2.21. 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.2.22. 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.2.23. 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:

  1. An employee that defines requiredShiftTags is assigned to a shift that defines tags and some of the tags are included in both collections.

  2. 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.2.24. 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:

  1. 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 avoidPriorShiftTags attribute.

  2. 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 avoidAfterShiftTags attribute.

  3. 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.2.25. 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:

  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.

  2. Value of minutes between rule’s satisfiability attribute is set to REQUIRED.

If the value of minimumConsecutivePriorShifts attribute is set to 2:

  1. 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.

  2. Value of minutes between rule’s satisfiability attribute is set to REQUIRED.

  3. 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.2.26. 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:

  1. 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.

  2. 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.

By default ordered is set to true this means that shifts will only match in the order the patterns are defined in. If it is set to false shifts will match the other pattern requirements (like tags) in any order.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "shift": "icu-morning-10-11-2023",
  "dailyShiftPairingRule": "saturdayWithSunday"
}

4.2.27. Employee has prohibited daily shift pairing

Employee contract can define several daily shift pairings. The constraint triggers if all the conditions below apply:

  1. 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.

  2. 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.

By default ordered is set to true this means that shifts will only match in the order the patterns are defined in. If it is set to false shifts will match the other pattern requirements (like tags) in any order.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "shift1": "icu-late-friday",
  "shift2": "icu-early-saturday",
  "dailyShiftPairingRule": "lateFridayNotWithEarlySaturday"
}

4.2.28. 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:

  1. 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.

  2. Value of the single day shift sequence pattern rule’s satisfiability attribute is set to REQUIRED.

Setting a pattern with REQUIRED satisfiability is being deprecated. Set it with PREFERRED satisfiability instead.

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.2.29. 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:

  1. 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.

  2. 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.2.30. 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:

  1. 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.

  2. 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.2.31. 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:

  1. The employee works the exact sequence of shifts, or day offs, spanning across consecutive days, as declared in the rule’s pattern attribute.

  2. 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.2.32. Maximum employee to shift travel distance exceeded

Employee contracts 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:

  1. Shift’s location is defined.

  2. Employee’s location is defined.

  3. Travel configuration is defined in the schedule parametrization.

  4. The distance between employee location and shift location exceeds the maxEmployeeToShiftTravelDistanceInMeters limit in travel configuration.

  5. 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.2.33. Minimum time between shifts including travel not met

Employee contracts 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:

  1. Shift’s location is defined.

  2. Employee’s location is defined.

  3. Travel configuration is defined in the schedule parametrization.

  4. 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.3. Medium constraints

4.3.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.

Prior to 0.25.0 you could define the assignment priority by setting the shift’s assignmentPriority attribute. This feature was deprecated in 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.3.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.3.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:

  1. 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.

  2. Value of the demand rule’s satisfiability attribute is set to REQUIRED.

Setting a minDemand with REQUIRED satisfiability is deprecated. Set it with PREFERRED satisfiability instead.

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.4. Soft constraints

4.4.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.4.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:

  1. Original employee assigned to a shift differs from the employee assigned to the shift after the solving finished.

  2. The shift start is within the time window defined by the disruption rule’s start and end attributes. The boundaries of the time window are inclusive.

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.4.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.4.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:

  1. 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.

  2. 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.4.5. Minutes logged per period not in preferred range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. Number of minutes logged by the employee in a period is below the value of the period rule’s minutesLoggedMin, or above the value of the period rule’s minutesLoggedMax.

  2. 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 minutesLoggedPerPeriodNotInPreferredRangeForEmployeeWeight 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"
  },
  "minutesLogged": 600
}

4.4.6. 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:

  1. 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.

  2. 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.4.7. Days off per period not in preferred range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The number of days off during a period is lower than the defined minimum or higher than the defined maximum, respectively daysOffLimit.daysOffMin and daysOffLimit.daysOffMax. The includeDays field on the daysOffLimit determines which days will be counted to the total number of days off. If the daysOffLimit is not defined all days will be counted towards the total, else only the supplied days will be counted. E.g. includeDays is set to ["SUNDAY"], daysOffMax is set to 5 and daysOffMin is set to 3 so the constraint will verify that at least 3 and at most 5 sundays are free of shifts.

  2. The 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 off. 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 days off. 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 daysOffPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": "max3SundaysOffPerMonth",
  "dateSpan": {
    "start": "2023-11-01T00:00:00Z",
    "end": "2023-12-01T00:00:00Z"
  },
  "daysOff": 5
}

4.4.8. Consecutive days off per period not in preferred range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The number of consecutive days off during a period is lower than the defined minimum: consecutiveDaysOffLimit.consecutiveDaysOffMin.

  2. The 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 consecutive days off. 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 consecutive days off. 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 daysOffPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": "min2ConsecutiveDaysOffPerWeek",
  "dateSpan": {
    "start": "2023-11-01T00:00:00Z",
    "end": "2023-11-08T00:00:00Z"
  },
  "consecutiveDaysOff": 1
}

4.4.9. Unique tags per period not in preferred range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The number of tags defined by the unique tags limit’s includeTagTypes, on shifts assigned to the employee in a period is above the value of the period rule’s unique tags limit’s tagsMax. Only the tags of the types defined on the unique tags limit’s includeTagTypes are counted.

  2. The value of the period rule’s satisfiability attribute is set to PREFERRED.

The tags and their types need to be configured as documented in Tags and tag types.

If defined, only shifts containing tags defined by period rule includeShiftTags attribute are included in the calculation of the total number of unique tags per period. 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 calculation of the total number of unique tags per period. 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 uniqueTagsPerPeriodNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": "Beth3UniqueTagsPerDay",
  "dateSpan": {
    "start": "2023-11-10T00:00:00Z",
    "end": "2023-11-11T00:00:00Z"
  },
  "uniqueTagAmount": 4
}

4.5. Shift start time difference in minutes per period not in preferred range for employee

Employee contract can define several period rules. The constraint triggers if all conditions below apply:

  1. The time between the earliest shift and the latest shift in this period is larger than this period rule’s shiftStartTimeDifferenceInMinutesMax.

  2. The 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 calculation of the difference in shift start times. 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 calculation of the difference in shift start times. 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.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "periodRule": "maxShiftStartTimeDifferenceOf60min",
  "dateSpan": {
    "start": "2023-11-10T00:00:00Z",
    "end": "2023-11-11T00:00:00Z"
  },
  "shiftStartTimeDifference": 120
}

4.5.1. 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:

  1. The number of shift locations assigned to the employee in a period is above the value of the period rule’s locationsWorkedMax.

  2. 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.5.2. 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:

  1. 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.

  2. 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.5.3. 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:

  1. 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.

  2. A shift has exactly one tag defined by the shiftTypeTagCategories attribute. The value of this tag defines the shift type.

  3. 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.5.4. 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:

  1. 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.

  2. 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.5.5. Shifts worked in rolling window not in preferred range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is above the value of the rule’s shiftsWorkedLimit.shiftsWorkedMax.

  2. Value of the rule’s satisfiability attribute is set to PREFERRED.

If defined, only shifts containing tags defined by the 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.

The rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Combination of HOURLY rolling window and shiftsWorkedLimit is not yet supported and will be provided in future versions.

The rule is more likely to be satisfied for employees with higher employee priority.

Use the constraint configuration’s shiftsWorkedInRollingWindowNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Max2IcuShiftsPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "shiftsWorked": 3
}

4.5.6. Days worked in rolling window not in preferred range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is above the value of the rule’s daysWorkedLimit.daysWorkedMax.

  2. Value of the rule’s satisfiability attribute is set to PREFERRED.

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 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 days 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.

The rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Combination of HOURLY rolling window and daysWorkedLimit is not yet supported and will be provided in future versions.

The rule is more likely to be satisfied for employees with higher employee priority.

Use the constraint configuration’s daysWorkedInRollingWindowNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Max5WorkingDaysPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "daysWorked": 6
}

4.5.7. Minutes worked in rolling window not in preferred range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is above the value of the rule’s minutesWorkedLimit.minutesWorkedMax.

  2. Value of the rule’s satisfiability attribute is set to PREFERRED.

If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the total number of minutes 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 minutes 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.

The rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

The rule is more likely to be satisfied for employees with higher employee priority.

Use the constraint configuration’s minutesWorkedInRollingWindowNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Max2400MinutesPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "minutesWorked": 2600
}

4.5.8. Consecutive days off in rolling window not in preferred range for employee

Employee contracts can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of shifts assigned to the employee in a rolling window is below the value of the rule’s consecutiveDaysOffLimit.consecutiveDaysOffMin.

  2. Value of the rule’s satisfiability attribute is set to PREFERRED.

If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the calculation of the days off. 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 calculation of the days off. 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 rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

Combination of HOURLY rolling window and consecutiveDaysOffLimit is not yet supported and will be provided in future versions.

The rule is more likely to be satisfied for employees with higher employee priority.

Use the constraint configuration’s consecutiveDaysOffInRollingWindowNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Min2ConsecutiveDaysOffPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "maxConsecutiveDaysOff": 1
}

4.5.9. Consecutive minutes off in rolling window not in preferred range for employee

Employee contract can define rolling window rules. The constraint triggers if all conditions below apply:

  1. Number of consecutive minutes between shifts assigned to the employee in a rolling window is below the value of the rule’s consecutiveMinutesOffLimit.consecutiveMinutesOffMin.

  2. Value of the rule’s satisfiability attribute is set to PREFERRED.

If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the calculation of the minutes off. 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 calculation of the minutes off. 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 rolling window is defined by the rollingWindow attribute. There are three types of rolling windows - HOURLY, DAILY, and WEEKLY. Configure the length of the rolling window by setting the rollingWindow.size attribute.

The rule is more likely to be satisfied for employees with higher employee priority.

Use the constraint configuration’s consecutiveMinutesOffInRollingWindowNotInPreferredRangeForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "rollingWindowRule": "Min2400ConsecutiveMinutesOffPer7RollingDays",
  "dateTimeSpan": {
    "start": "2025-01-01T00:00:00Z",
    "end": "2025-01-08T00:00:00Z"
  },
  "maxConsecutiveMinutesOff": 2000
}

4.5.10. Preferred shift rotation not met for employee

Employee contracts can define shift rotation rules.

Use this to make sure that the employee’s shift types alternate in consecutive periods, for example, "morning" shifts on week 1 and "evening" shifts on week 2.

The constraint triggers if all conditions below apply:

  1. Employee works the same shift type in two consecutive periods.

  2. Value of the rule’s satisfiability attribute is set to PREFERRED.

The period is defined by the builtInRotationPeriod attribute. At the moment, we support builtInRotationPeriod.type WEEK.

The shift type is defined by the rotationGroups attribute. Create a rotation group for each shift type, or a group of similar shift types. For example, you can create a group that includes "morning" shifts and another group that includes both "afternoon" and "evening" shifts.

If defined, only shifts containing tags defined by the rule’s rotationGroups.includeShiftTags attribute are included in the group. With shiftTagMatches set to ALL, all tags defined by the rule’s rotationGroups.includeShiftTags attribute have to be present in the shift. With shiftTagMatches set to ANY, at least one tag defined by the rule’s rotationGroups.includeShiftTags attribute has to 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 preferredShiftRotationNotMetForEmployeeWeight attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "shift1": "morning-week-25",
  "shift2": "morning-week-26",
  "shiftRotationRule": "rotate-shift-types-weekly"
}

4.5.11. 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:

  1. 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.

  2. 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.5.12. 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:

  1. 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.5.13. 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:

  1. 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.

  2. 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.5.14. 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:

  1. 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.

  2. 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.

By default, this type of rule only counts shifts if the shifts started within the defined period. If you define a rule that says that an employee can only work 1 shift a day, then it won’t count a night shift that started on the previous day but ends at e.g. 6 a.m. This means that the solver will still try to assign a shift to this day. To change this behavior change the field periodShiftOverlapKind from START_ONLY to START_AND_END.

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.5.15. 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.5.16. 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.5.17. Employee works during preferred time

Employee 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.5.18. Employee works during unpreferred time

Employee 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.5.19. 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:

  1. An employee that defines preferredShiftTags is assigned to a shift that defines tags and some of the tags are included in both collections.

  2. 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.5.20. 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:

  1. 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.

  2. 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.

  3. 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.5.21. 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.5.22. 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.5.23. 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.5.24. 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.5.25. 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:

  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.

  2. Value of minutes between rule’s satisfiability attribute is set to PREFERRED.

  3. 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.5.26. 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:

  1. 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.5.27. 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:

  1. 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.

  2. 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.

By default ordered is set to true this means that shifts will only match in the order the patterns are defined in. If it is set to false shifts will match the other pattern requirements (like tags) in any order.

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.5.28. Employee has unpreferred daily shift pairing

Employee contract can define several daily shift pairings. The constraint triggers if all the conditions below apply:

  1. 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.

  2. 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.

By default ordered is set to true this means that shifts will only match in the order the patterns are defined in. If it is set to false shifts will match the other pattern requirements (like tags) in any order.

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.5.29. 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:

  1. 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.

  2. 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.5.30. 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:

  1. 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.

  2. 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.5.31. 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:

  1. The employee works the exact sequence of shifts, or day offs, spanning across consecutive days, as declared in the rule’s pattern attribute.

  2. 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.5.32. 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:

  1. The employee works the exact sequence of shifts, or day offs, spanning across consecutive days, as declared in the rule’s pattern attribute.

  2. 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.5.33. Minimize travel distance

Employee contracts 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:

  1. Shift’s location is defined.

  2. Employee’s location is defined.

  3. Travel configuration is defined in the schedule parametrization.

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",
  "activeDateTime": "2024-05-16T10:00:45.820273+02:00",
  "completeDateTime": null,
  "shutdownDateTime": null,
  "solverStatus": "SOLVING_ACTIVE",
  "score": "0hard/0medium/-1505soft",
  "tags": []
}

The run is associated with five key timestamps, each marking a distinct phase in the process:

  • submitDateTime: The moment the run is submitted. At this stage, the run is queued and has not yet begun solving. The run status is SOLVING_SCHEDULED.

  • startDateTime: The moment the run begins initializing. During this phase, the run is not solving yet, but the model is being built and enriched with external data (e.g., incorporating map information for models involving geographical locations). The run status is SOLVING_STARTED.

  • activeDateTime: The moment the solving phase begins. At this stage, the actual problem-solving process starts. The run status is SOLVING_ACTIVE.

  • completeDateTime: The moment the solving phase concludes. At this point, the run has finished solving but has not yet undergone any post-processing (e.g., score analysis or waypoint enrichment for geographical models). The run status is either SOLVING_COMPLETED or SOLVING_FAILED.

  • shutdownDateTime: The moment the post-processing phase finishes. All tasks, including post-processing, are completed, and the run is fully finalized.

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.

Example 7. Get score analysis for a schedule without justifications

GET /v1/schedules/{id}/score-analysis

Example 8. Sample score analysis result without justifications
{
  "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": []
    }...
Example 9. Get score analysis for a schedule with justifications

GET /v1/schedules/{id}/score-analysis?includeJustifications=true

Example 10. Sample score analysis result including justifications
{
  "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.

Example 11. Calculate score analysis for a schedule including justifications

POST /v1/schedules/score-analysis?includeJustifications=true

The endpoint accepts a schedule object in the request body.

Example 12. Sample score analysis result
{
  "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.

The Recommend Employee API 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 for each recommendation.

Example 13. Get employee recommendations for a new shift without justifications

POST /v1/schedules/{id}/recommendations/recommend-employees

Example 14. Get employee recommendations for a new shift with justifications

POST /v1/schedules/{id}/recommendations/recommend-employees?includeJustifications=true

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.

"maxNumberOfRecommendations": 3

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 modelInput schedule.

"fitShiftId": "icu-emergency-10-11-2023"

Config

false

object

Configuration that allows to customize constraint weights.

"config": { "unpreferredEmployeeAssignedWeight": "1" }

Model input

true

object

Model input with schedule that contains shift with identifier specified by fitShiftId attribute.

`"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.

"scoreDiff": "0hard/100medium/-480soft"

Constraint diffs

array

Per-constraint score difference between the new solution with the fitted shift and the solution without the fitted shift. Includes the array of matches when includeJustifications=true query parameter was set.

`"constraintDiffs": [ { "score": "0hard/100medium/0soft", "constraintName": "Unassigned shift", "matches": [ …​ ], "matchCount": 2 }, …​ `

Employee id

string

Identifier of the recommended employee.

`"employeeId": "Amy Smith" `

  • © 2025 Timefold BV
  • Timefold.ai
  • Documentation
  • Changelog
  • Send feedback
  • Privacy
  • Legal
    • Light mode
    • Dark mode
    • System default