Employee Scheduling User Guide

1. Introduction

Employee scheduling is the process of efficiently assigning work shifts and tasks to employees. The goal is to create schedules that minimize labor costs, ensure proper coverage, and satisfy various constraints such as employee availability and labor laws.

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

Global rules configuration

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

3. Architecture

Under the hood, the application includes Timefold Enterprise Solver - scalable optimization engine that can solve complex constraint satisfaction problems.

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

3.1. Typical user workflow

3.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}

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

3.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 schedule. Use id attribute returned by submit dataset step.

Example 4. Check status REST API endpoint call

GET /v1/schedules/{id}

3.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}

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

4. Input structure

Input payload consists of a model input representing a schedule and a configuration

4.1. Configuration

4.1.1. Run configuration

Provides an optional name of the solving run and termination settings.

Termination allows to optionally set spentLimit attribute to specify the maximum time the solver can spend on solving the problem. Use unimprovedSpentLimit to set the maximum time the solver can spend without improving the best solution.

"run": {
  "name": "SMALL",
  "termination": {
    "spentLimit": "PT10M",
    "unimprovedSpentLimit": "PT5M"
  }
}

4.1.2. Model configuration

Provides an optional configuration of the model, for example specifying the weight of constraints.

4.1.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
  }
}

4.2. Model input

Contains the schedule to be solved. This includes employees, shifts and other data.

4.2.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" ]

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"

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:00", "end": "2024-01-11T00:00:00" } ] } ]

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

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:00", "end": "2023-11-09T00:00:00", "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:00", "end": "2023-11-09T00:00:00", "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:00", "end": "2023-11-09T00:00:00", "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:00", "end": "2023-11-09T00:00:00", "includeShiftTags": [ "Location London" ], "excludeShiftTags": null, "shiftTagMatches": "ALL" } ]

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

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.

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

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

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", "prohibitedPriorShiftTags": [ "NIGHT" ], "prohibitedAfterShiftTags": [ "MORNING", "DEPARTMENT_A" ], "shiftTagMatches": "ANY", "satisfiability": "REQUIRED" } ]

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.

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

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 sequence of shifts that should, or should not follow each other on the same day, optionally only for shifts with specific tags.

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

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

"multiDayShiftSequencePatternRules": [ { "id": "earlyOffLateOffPattern", "satisfiability": "REQUIRED", "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" } ]

4.2.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:00"

End

true

string, ISO-8601

End time of the shift.

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

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"

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

Defines priority for shift assignment where 1 is the highest priority and 5 is the lowest priority.

"assignmentPriority": 2

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"

4.2.4. Global rules configuration

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

Name Required Format Description Example

Balance shift count rule

false

array

Configuration of balance shift count rule. Use to make sure the number of shifts worked, that match conditions specified is balanced across employees. The rule takes historic data into account. Use employeeToPublishedShiftCountForTag attribute to specify the number of shifts worked by each employee in the past.

"balanceShiftTagByShiftCount": [ { "id": "balanceNightShiftCountForPartTimeEmployees", "includeEmployeeTags": null, "excludeEmployeeTags": [ "Part time" ], "employeeTagMatches": "ALL", "includeShiftTags": [ "NIGHT" ], "excludeShiftTags": null, "shiftTagMatches": "ALL", "employeeToPublishedShiftCountForTag": { "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. Note: Experimental API subject to change.

"minimumMaximumShiftsPerHourlyDemand": [ { "id": "HourlyDemand", "includeShiftTags": [ "Location A" ], "demandDetails": [ { "startDateTime": "2024-05-01T00:00:00", "endDateTime": "2024-05-01T01:00:00", "minDemand": 20 }, { "startDateTime": "2024-05-01T01:00:00", "endDateTime": "2024-05-01T02:00:00", "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.

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

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.

"minimumMaximumShiftsPerPeriod": [ { "id": "min3ShiftsPerDay", "period": "DAY", "satisfiability": "PREFERRED", "includeShiftTags": [ "ICU" ] "shiftsWorkedMin": 3 }

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

4.2.5. Schedule Parameterization

4.2.5.1. Periods

Configuration for periods used in the schedule. The following builtin periods are available:

  • DAY: Spans a single day and occurs on every day being scheduled.

  • WEEK: Spans 7 days, starting at the 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" } ]}]

5. Constraints

5.1. Hard constraints

5.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"
  ]
}

5.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"
}

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

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:00",
    "end": "2023-11-11T00:00:00"
  },
  "minutesWorked": 600
}

5.1.4. Shifts worked per period not in required range for employee

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

  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.

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:00",
    "end": "2023-11-11T00:00:00"
  },
  "shiftsWorked": 2
}

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

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:00",
    "end": "2023-11-20T00:00:00"
  },
  "daysWorked": 5
}

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

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:00",
    "end": "2023-11-20T00:00:00"
  },
  "shiftTypesWorked": 4
}

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

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

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

Note you need to define the cost detail for each employee cost group and shift cost group combination that should be included in the total costs. Undefined employee cost group and shift cost group combinations are not included in the total costs.

If defined, only employees containing tags defined by the rule’s includeEmployeeTags attribute are included in the total costs. With employeeTagMatches set to ALL, all tags defined by the rule’s includeEmployeeTags attribute have to be present in the employee. With employeeTagMatches set to ANY, at least one tag defined by the rule’s includeEmployeeTags attribute has to be present in the employee.

If defined, only employees not containing tags defined by the rule’s excludeEmployeeTags attribute are included in the total costs. With employeeTagMatches set to ALL, all tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee. With employeeTagMatches set to ANY, any of the tags defined by the rule’s excludeEmployeeTags attribute cannot be present in the employee.

The rule can define either includeEmployeeTags or excludeEmployeeTags, not both.

If defined, only shifts containing tags defined by the rule’s includeShiftTags attribute are included in the total costs. With shiftTagMatches set to ALL, all tags defined by the rule’s includeShiftTags attribute have to be present in the shift. With shiftTagMatches set to ANY, at least one tag defined by the rule’s includeShiftTags attribute has to be present in the shift.

If defined, only shifts not containing tags defined by the rule’s excludeShiftTags attribute are included in the total costs. With shiftTagMatches set to ALL, all tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift. With shiftTagMatches set to ANY, any of the tags defined by the rule’s excludeShiftTags attribute cannot be present in the shift.

The rule can define either includeShiftTags or excludeShiftTags, not both.

Score analysis justification example:

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

5.1.9. 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"
    ]
  }
}

5.1.10. 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"
    ]
  }
}

5.1.11. 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"
  ]
}

5.1.12. 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"
}

5.1.13. 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:00",
      "end": "2023-11-10T16:00:00"
    }
  ]
}

5.1.14. 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"
}

5.1.15. 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 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 period rule’s satisfiability attribute is set to PROHIBITED.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "shift": "icu-evening-10-11-2023",
  "avoidShiftCloseToDayOffRequestRule": "noEveningShiftBeforeDayOff"
}

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

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
}

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

Score analysis justification example:

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

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

Score analysis justification example:

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

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

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

5.1.20. 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 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"
}

5.1.21. 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 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"
}

5.1.22. 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 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"
}

5.2. Medium constraints

5.2.1. Shifts worked not in required hourly demand range

Note: Experimental API subject to change.

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.

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 constraint configuration’s shiftsWorkedNotInRequiredHourlyDemandRangeWeight attribute to update the weight of the constraint.

Score analysis justification example:

"justification": {
  "hourlyDemandRule": "HourlyDemand",
  "startDateTime": "2024-05-06T07:00:00",
  "shiftsWorked": 25
}

5.3. Soft constraints

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

Use 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"
}

5.3.2. 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 constraint configuration’s preferredSkillMissingWeigh attribute to update the weight of the constraint.

Score analysis justification example:

{
  "employee": "Beth Jones",
  "shift": "icu-afternoon-10-11-2023",
  "missingSkills": [
    "Nurse"
  ]
}

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

Use 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:00",
    "end": "2023-11-11T00:00:00"
  },
  "minutesWorked": 600
}

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

Use 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:00",
    "end": "2023-11-11T00:00:00"
  },
  "shiftsWorked": 2
}

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

Use 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:00",
    "end": "2023-11-20T00:00:00"
  },
  "daysWorked": 5
}

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

Use 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:00",
    "end": "2023-11-20T00:00:00"
  },
  "shiftTypesWorked": 4
}

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

Use 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"
}

5.3.8. 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 constraint configuration’s shiftsWorkedNotInPreferredHourlyDemandRangeWeight attribute to update the weight of the constraint.

Score analysis justification example:

"justification": {
  "hourlyDemandRule": "HourlyDemand",
  "startDateTime": "2024-05-06T07:00:00",
  "shiftsWorked": 25
}

5.3.9. Balance shifts worked for minimum hourly demand

Note: Experimental API subject to change.

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 constraint configuration’s balanceShiftsWorkedForMinimumHourlyDemandWeight attribute to update the weight of the constraint.

Score analysis justification example:

"justification": {
  "hourlyDemandRule": "HourlyDemand",
  "startDateTime": "2024-05-06T07:00:00",
  "targetDemand": 30,
  "shiftsWorked": 25
}

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

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

Score analysis justification example:

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

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

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

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

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

5.3.13. Employee works during preferred time

Employee contract can define several preferred time spans. The span defines a period when the employee prefers to work. The constraint triggers if the employee is assigned to a shift that matches optional shift tag criteria and overlaps with one or more preferred time spans defined by the employee.

If defined, only shifts containing tags defined by preferred time for employee includeShiftTags attribute are included. With shiftTagMatches set to ALL, all tags defined by the preferred time for employee includeShiftTags attribute have to be present in the shift. With shiftTagMatches set to ANY, at least one tag defined by the preferred time for employee includeShiftTags attribute has to be present in the shift.

If defined, only shifts not containing tags defined by preferred time for employee excludeShiftTags attribute are included. With shiftTagMatches set to ALL, all tags defined by the preferred time for employee excludeShiftTags attribute cannot be present in the shift. With shiftTagMatches set to ANY, any of the tags defined by the preferred time for employee excludeShiftTags attribute cannot be present in the shift.

The rule can define either includeShiftTags or excludeShiftTags, not both.

Use 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:00",
      "end": "2023-11-10T18:00:00"
    }
  ]
}

5.3.14. Employee works during unpreferred time

Employee contract can define several unpreferred time spans. The span defines a period when the employee prefers not to work. The constraint triggers if the employee is assigned to a shift that matches optional shift tag criteria and overlaps with one or more unpreferred time spans defined by the employee.

If defined, only shifts containing tags defined by unpreferred time for employee includeShiftTags attribute are included. With shiftTagMatches set to ALL, all tags defined by the unpreferred time for employee includeShiftTags attribute have to be present in the shift. With shiftTagMatches set to ANY, at least one tag defined by the unpreferred time for employee includeShiftTags attribute has to be present in the shift.

If defined, only shifts not containing tags defined by unpreferred time for employee excludeShiftTags attribute are included. With shiftTagMatches set to ALL, all tags defined by the unpreferred time for employee excludeShiftTags attribute cannot be present in the shift. With shiftTagMatches set to ANY, any of the tags defined by the unpreferred time for employee excludeShiftTags attribute cannot be present in the shift.

The rule can define either includeShiftTags or excludeShiftTags, not both.

Use 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:00",
      "end": "2023-11-10T16:00:00"
    }
  ]
}

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

Use 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"
}

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

Use 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"
}

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

Use 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"
}

5.3.18. 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 tags specified is balanced across employees that match tags specified. This avoids situations where some employees work more shifts than others.

If defined, only employees containing tags defined by 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 period rule 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 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 period rule 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 constraint configuration’s balanceShiftCountWeight attribute to update the weight of the constraint.

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

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.

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

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

Use 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"
}

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

Use 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"
}

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

Use 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"
}

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

Use 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"
}

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

Use 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"
}

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

Use 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"
}

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/-7200medium/-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/-7200medium/-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:00",
                "end": "2024-03-13T00:00:00",
                "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:00",
                    "end": "2024-03-20T00:00:00",
                    "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.

Example 13. Get employee recommendations for a new shift

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

6.2.1. Recommend Employee API input

Description of Recommend Employee API input.

Name Required Format Description Example

Max number of recommendations

true

int

Upper limit for a number of employees to recommend for a new shift.

"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/48000medium/-480soft"

Constraint diffs

array

Per-constraint score difference between the new solution with the fitted shift and the solution without the fitted shift.

`"constraintDiffs": [ { "score": "0hard/48000medium/0soft", "constraintName": "Unassigned shift" }, …​ `

Employee id

string

Identifier of the recommended employee.

`"employeeId": "Amy Smith" `