Решает проблему планирования фиксированных смен из заданного SolveShiftSchedulingRequest
, назначая сотрудников на смены таким образом, чтобы предпочтения сотрудников в отношении планирования были максимальными, а нарушения ограничений планирования были сведены к минимуму.
HTTP-запрос
POST https://optimization.googleapis.com/v1/scheduling:solveShiftScheduling
URL-адрес использует синтаксис транскодирования gRPC .
Тело запроса
Тело запроса содержит данные следующей структуры:
JSON-представление |
---|
{ "requestId": string, "solveParameters": { object ( |
Поля | |
---|---|
requestId | Идентификатор проблемы или запроса. |
solveParameters | Параметры для управления единственным решением проблемы. |
employees[] | Все доступные сотрудники подлежат планированию. |
shifts[] | Все смены формируют график. |
coverageRequirements[] | Требования к покрытию для всего горизонта планирования. Они определяют количество сотрудников, которые должны выполнять каждую роль или обладать навыками в течение определенного периода времени или списка идентификаторов смен. Все требования к покрытию должны быть указаны либо с указанием временных окон, либо со списком идентификаторов смен (но не с тем и другим). Временные окна (если они предусмотрены) для требований к покрытию не могут перекрываться для каждого данного местоположения. Уровень приоритета по умолчанию для каждого из этих ограничений — |
roleIds[] | Список всех возможных ролей среди сотрудников. У каждого сотрудника должна быть хотя бы одна роль, которую ему можно назначить на смену. Роль относится к конкретному рабочему заданию в течение смены (например, дипломированная медсестра, шеф-повар, официант и т. д.). Когда сотрудника назначают на смену, ему также назначается одна конкретная роль. |
skillIds[] | Список всех возможных навыков среди сотрудников. Навык относится к любой дополнительной квалификации, которую может иметь сотрудник, не относящейся к конкретной назначаемой работе (например, сертификаты, знание языков и т. д.). Этот список может быть пустым. Когда сотрудника назначают на смену, он должен обладать всеми навыками, необходимыми для этой смены. |
locationIds[] | Список всех возможных мест набора смен в графике. Этот список может быть пустым. Указание разных местоположений может оказаться полезным, например, когда менеджер медсестры хочет запланировать работу нескольких медсестер в разных отделениях больницы или, например, менеджер отеля хочет распределить сотрудников по нескольким отелям. |
budgetRequirements[] | Спецификация бюджета для задачи планирования. Уровень приоритета по умолчанию для каждого из этих требований — |
assignmentsHint[] | Перемещайте задания, чтобы использовать их в качестве предварительного решения (так называемого подсказки к решению) проблемы планирования. Подсказки о назначении игнорируются, если назначение противоречит неназначаемой смене или запросу планирования. |
Тело ответа
Ответ для API планирования рабочей силы. Для каждого shiftAssignments
будет пустым, если возвращаемый solutionStatus
имеет значение NOT_SOLVED_DEADLINE_EXCEEDED
или INFEASIBLE
. Если возвращенное solutionStatus
имеет значение OPTIMAL
или FEASIBLE
, то shiftAssignments
возвращается допустимое назначение смены. Для допустимого назначения смены сохраняются следующие свойства:
- Каждый идентификатор сотрудника содержится в наборе сотрудников, указанном в запросе.
- Каждый идентификатор роли, назначенный сотруднику, содержится в наборе идентификаторов ролей для данного сотрудника.
- Идентификатор каждой смены содержится в наборе смен, указанном в запросе.
- Каждый идентификатор смены не является одним из неназначаемых идентификаторов смены для данного сотрудника.
- Сотрудник никогда не будет назначен на две перекрывающиеся смены.
- Для данного расписания ни одно из ограничений или запросов с уровнем приоритета
PRIORITY_MANDATORY
не нарушено.
В случае успеха тело ответа содержит данные следующей структуры:
JSON-представление |
---|
{ "requestId": string, "solutionStatus": enum ( |
Поля | |
---|---|
requestId | Идентификатор запроса, с которым связан этот ответ. |
solutionStatus | Статус возвращенного решения. Если решение не является ВОЗМОЖНЫМ или ОПТИМАЛЬНЫМ, другие поля в этом прототипе могут быть пустыми. Если статус NOT_SOLVED_DEADLINE_EXCEEDED, ограничение по времени было достигнуто без нахождения возможного решения или определения его существования. Запросы могут оказаться невыполнимыми, если ограничения уровня приоритета ОБЯЗАТЕЛЬНО не могут быть удовлетворены полностью. |
shiftAssignments[] | Список всех заданий. Каждый |
statusMessage | Если |
РешитьПараметры
Параметры, управляющие единственным решением задачи планирования смен.
JSON-представление |
---|
{ "timeLimit": string } |
Поля | |
---|---|
timeLimit | Максимальное время, которое решатель должен потратить на решение задачи. Если не установлено, по умолчанию — 1 минута. Это значение не является жестким пределом и не учитывает накладные расходы на связь. Ожидаемая задержка решения проблемы может немного превышать это значение. Длительность в секундах, содержащая до девяти дробных цифр и оканчивающаяся на « |
Сотрудник
Сотрудник из числа сотрудников, подлежащих планированию.
JSON-представление |
---|
{ "id": string, "roleIds": [ string ], "skillIds": [ string ], "shiftPreferences": [ { object ( |
Поля | |
---|---|
id | Уникальный идентификатор, присвоенный этому сотруднику. |
roleIds[] | Идентификаторы ролей, которые может выполнять этот сотрудник. Должна быть указана хотя бы одна роль. При назначении сотрудника на смену ему также назначается одна роль из этого списка. Сотруднику могут быть назначены различные роли во время окна планирования. |
skillIds[] | Идентификаторы навыков, которыми обладает этот сотрудник. Этот список может быть пустым. Когда сотрудника назначают на смену, он использует любое подмножество навыков, перечисленных здесь, для удовлетворения требований к навыкам на протяжении всей назначенной смены. |
shiftPreferences[] | Изменить предпочтения этого сотрудника. Указанные здесь смены представляют собой смены, на которые сотрудник предпочел бы быть назначен во время окна планирования. Идентификаторы смен, указанные в |
schedulingConstraints[] | Список ограничений планирования для этого сотрудника. Уровень приоритета по умолчанию для каждого из этих ограничений — |
resourceConstraints[] | Любые дополнительные ограничения планирования, не указанные в |
shiftRequests[] | Список заявок на смену для сотрудника. Запрос может заключаться в назначении или не назначении сотрудника на определенные смены. Любые фиксированные назначения планирования для сотрудника могут быть представлены с помощью |
hourlyContract | Контракт, в котором указаны регулярные и сверхурочные почасовые ставки для сотрудника. |
ShiftPreference
Числовое предпочтение для определенного идентификатора смены.
JSON-представление |
---|
{ "shiftId": string, "preference": integer } |
Поля | |
---|---|
shiftId | Идентификатор смены, для которой указано предпочтение. |
preference | Более высокие значения предпочтения означают более желательный сдвиг. |
Ограничение планирования
Особое ограничение графика для конкретного сотрудника. Указанное ограничение применяется только в течение заданного интервала [startDateTime, endDateTime)
.
JSON-представление |
---|
{ "priority": enum ( |
Поля | |
---|---|
priority | Уровень приоритета для этого ограничения планирования. Приоритет по умолчанию для всех ограничений планирования — |
startDateTime | Время начала применения этого ограничения планирования (включительно). |
endDateTime | Время окончания применения этого ограничения планирования (эксклюзивное). |
type поля объединения. Указанный тип ограничения. Каждое ограничение применяется только в течение указанного выше временного окна. type может быть только одним из следующих: | |
minimumMinutes | Минимальное количество минут, в течение которых сотрудник может работать. Если сотрудник назначен на смену, которая перекрывает (полностью или частично) временное окно, в этот подсчет включается количество минут, в течение которых смена перекрывает временное окно. |
maximumMinutes | Максимальное количество минут, в течение которых сотрудник может работать во временном окне. Если сотрудник назначен на смену, которая перекрывает (полностью или частично) временное окно, в этот подсчет включается количество минут, в течение которых смена перекрывает временное окно. |
minimumConsecutiveWorkDays | Минимальное количество дней подряд, в течение которых сотрудник может работать. Сотрудник работает в определенный день, если ему назначена смена, которая начинается в этот день. Любая смена, на которую назначен сотрудник и которая начинается во временном окне, включается в этот подсчет. |
maximumConsecutiveWorkDays | Максимальное количество дней подряд, в течение которых сотрудник может работать. Сотрудник работает в определенный день, если ему назначена смена, которая начинается в этот день. Любая смена, на которую назначен сотрудник и которая начинается во временном окне, включается в этот подсчет. |
minimumShiftCount | Минимальное количество смен, в течение которых может работать сотрудник. В этот подсчет включается любая смена, на которую назначен сотрудник и которая полностью совпадает с временным окном. |
maximumShiftCount | Максимальное количество смен, в течение которых может работать сотрудник. В этот подсчет включается любая смена, на которую назначен сотрудник и которая полностью совпадает с временным окном. |
minimumRestMinutes | Минимальное количество минут, в течение которых сотрудник должен отдыхать после окончания одной смены, прежде чем его переведут на другую смену. Это ограничение применяется к каждой паре смен, полностью включенных в [ |
Приоритет
Уровень приоритета для любого ограничения графика сотрудника или требований к покрытию. К ним относятся SchedulingConstraint
, ResourceConstraint
, ShiftRequest
и CoverageRequirement
. Поскольку могут существовать противоречивые ограничения, не всегда возможно удовлетворить каждое ограничение. Таким образом, каждый тип ограничений имеет приоритет (задаваемый пользователем или значение по умолчанию), который информирует решатель об относительной важности всех ограничений, заданных для полного расписания.
Перечисления | |
---|---|
PRIORITY_UNSPECIFIED | Неизвестный уровень приоритета. |
PRIORITY_LOW | Самый низкий уровень приоритета. Ограничения с этим приоритетом менее важны, чем другие ограничения. Они в первую очередь рассматриваются на предмет нарушения, если невозможно найти осуществимое решение. |
PRIORITY_MEDIUM | Уровень приоритета средний. Ограничения с этим приоритетом более важны, чем ограничения с приоритетом PRIORITY_LOW , но менее важны, чем ограничения с приоритетом PRIORITY_HIGH . Если допустимое решение не может быть найдено после ослабления всех ограничений с приоритетом PRIORITY_LOW , то следующими на предмет нарушения считаются ограничения с приоритетом PRIORITY_MEDIUM . |
PRIORITY_HIGH | Самый высокий уровень приоритета. Ограничения с этим уровнем приоритета являются наиболее важными. Их нарушение следует рассматривать в последнюю очередь, если допустимое решение не может быть найдено после ослабления ограничений более низких уровней приоритета. |
PRIORITY_MANDATORY | Уровень приоритета, который представляет собой то, что не может быть нарушено решателем. Если решатель возвращает SolutionStatus.INFEASIBLE , это может быть связано со слишком большим количеством ограничений PRIORITY_MANDATORY . |
РесурсОграничение
Общее ограничение, ограничивающее количество определенного «ресурса», используемого сотрудником. Это абстрактная версия более конкретного SchedulingConstraint
, более гибкая для пользователя. Многие ограничения планирования, которые нельзя указать в SchedulingConstraint.type
можно вместо этого указать с помощью этого сообщения.
JSON-представление |
---|
{
"priority": enum ( |
Поля | |
---|---|
priority | Уровень приоритета этого ограничения ресурса. Приоритет по умолчанию для всех ограничений ресурсов — |
resourceUsages | Количество ресурсов, используемых сменами. Например, если это ограничение применяется к минимальному и максимальному количеству часов, отработанных сотрудником на определенной неделе, то эта карта будет содержать смены, происходящие на этой неделе, и продолжительность каждой смены в часах. Объект, содержащий список пар |
minimumResourceUsage | Минимальное использование ресурсов для удовлетворения ограничения ресурсов. |
maximumResourceUsage | Максимальное использование ресурсов для удовлетворения ограничения ресурсов. |
ShiftRequest
Просьба сотрудника о назначении или не назначении на определенные смены.
JSON-представление |
---|
{ "priority": enum ( |
Поля | |
---|---|
priority | Уровень приоритета этого запроса планирования. Приоритет по умолчанию для всех запросов планирования — |
shiftIds[] | Идентификаторы смены запроса на планирование. |
type | Тип запроса, например, может ли запрос быть назначен или не назначен набору смен. |
Статус работы
Независимо от того, работает сотрудник или нет.
Перечисления | |
---|---|
WORK_STATUS_UNSPECIFIED | Неизвестный статус работы. |
STATUS_WORK | Статус, представляющий работающего сотрудника. |
STATUS_NOT_WORK | Статус, представляющий неработающего сотрудника. |
Почасовой контракт
Указывает базовую почасовую ставку, разницу в ставках и множители сверхурочной работы для определения компенсации сотруднику. Обратите внимание, что правила в разных местах могут требовать разных расчетов компенсации за сверхурочную работу. Решающая программа аппроксимирует компенсацию за сверхурочную работу, чтобы либо минимизировать приблизительную общую стоимость, либо уложиться в бюджет (см. BudgetRequirement
). Он не предназначен в качестве инструмента для расчета заработной платы.
JSON-представление |
---|
{
"baseHourlyRate": number,
"hourlyRateShiftDifferentials": {
string: number,
...
},
"overtimePeriods": [
{
object ( |
Поля | |
---|---|
baseHourlyRate | Компенсация за работу в сверхурочное время. Если к сотруднику применяются несколько ставок, разница в ставках применяется относительно этой базовой почасовой ставки. Кроме того, если существует несколько ставок, базовая почасовая ставка должна быть минимальной из этих ставок. |
hourlyRateShiftDifferentials | Разница в почасовой ставке, выплачиваемая сверх Объект, содержащий список пар |
overtimePeriods[] | Список всех периодов, для которых необходимо рассчитать сверхурочную работу. Эти периоды не должны пересекаться. |
Период сверхурочной работы
Фиксированный и регулярно повторяющийся период (обычно 168 часов или семь последовательных 24-часовых периодов), который используется для определения суммы компенсации за сверхурочную работу. Каждый период имеет множитель сверхурочной работы (например, 1,5) относительно baseHourlyRate
и ограничение на количество часов, которые считаются обычной (не сверхурочной) работой. Любая смена, которая перекрывается с временным окном startDateTime
(включительно) и endDateTime
(исключительно), засчитывается в общее количество часов, отработанных за период. Если перекрытие частичное, учитываются только перекрывающиеся часы.
JSON-представление |
---|
{ "overtimeMultiplier": number, "startDateTime": { object ( |
Поля | |
---|---|
overtimeMultiplier | Множитель для расчета почасовой ставки за сверхурочную работу (должен быть больше или равен 1,0). Почасовая ставка сверхурочной работы обычно рассчитывается как |
startDateTime | Время начала дополнительного периода. Если смена перекрывает это время, часы такой смены отсчитываются от |
endDateTime | Время окончания сверхурочной работы. Если смена перекрывает это время, часы такой смены отсчитываются до |
maximumRegularHours | Максимальное количество рабочих часов, оплачиваемых по обычной ставке (без сверхурочной работы). Эта величина должна быть положительной. |
Сдвиг
Смена определяет фиксированный временной интервал, в течение которого сотрудники могут работать.
JSON-представление |
---|
{ "id": string, "locationId": string, "startDateTime": { object ( |
Поля | |
---|---|
id | Уникальный идентификатор, присвоенный этой смене. |
locationId | Идентификатор локации, в которой работает данная смена. Это может быть пусто. |
startDateTime | Время начала смены (включительно). |
endDateTime | Время окончания смены (эксклюзивное). В настоящее время решатель допускает только смены продолжительностью менее 24 часов. |
breakRules[] | Список нарушений правил, возникающих во время смены. Сотрудникам, работающим в эту смену, назначается перерыв по |
BreakRule
Правило, определяющее время начала перерыва в смене и его продолжительность. Список всех возможных перерывов, которые учитываются, определяется с шагом ruleIncrementMinutes
. Например, если правило перерыва моделирует 30-минутный перерыв, который может начаться с 10:00 до 11:00, а шаг правила составляет 20 минут, учитываются следующие списки перерывов: [10:00, 10 :30], [10:20, 10:50], [10:40, 11:10], [11:00, 11:30].
JSON-представление |
---|
{ "earliestStartTime": { object ( |
Поля | |
---|---|
earliestStartTime | Самое раннее время начала перерыва (включительно). Можно установить только |
latestStartTime | Самое позднее время начала перерыва (включительно). Можно установить только |
durationMinutes | Продолжительность перерыва в минутах. |
ruleIncrementMinutes | [Необязательно] Приращение времени в минутах для всех перерывов, которые могут учитываться в этом правиле перерывов. Если не установлено, по умолчанию используется |
Требование к покрытию
Требование покрытия определяет количество сотрудников, необходимых для выполнения набора ролей и/или навыков в течение определенного периода времени и в данном месте. Интервалы DateTime в определенном месте не могут перекрываться. Альтернативно, вместо временного окна и местоположения может быть предоставлен список идентификаторов смен. Этому требованию могут соответствовать только сотрудники, которым может быть назначена конкретная роль (или которые обладают определенными навыками).
Для данной роли и/или навыка требование покрытия выполняется, когда по крайней мере количество сотрудников targetEmployeeCount
работает в каждый момент временного окна (или для каждой смены shiftIds
). Напротив, требование покрытия нарушается, если в любой момент временного окна (или для любой из смен shiftIds
) количество сотрудников, работающих в течение временного окна, меньше, чем targetEmployeeCount
. Больше работающих сотрудников, чем targetEmployeeCount
по-прежнему соответствует требованию, но решающая программа сводит к минимуму чрезмерную численность персонала.
JSON-представление |
---|
{ "startDateTime": { object ( |
Поля | |
---|---|
startDateTime | Время начала требования к покрытию (включительно). Если установлено, |
endDateTime | Время окончания требования к страховому покрытию (эксклюзивное). Если установлено, |
locationId | Место, где требуются сотрудники. |
shiftIds[] | Если этот параметр установлен, требования к роли и навыкам применяются индивидуально к каждому идентификатору смены в этом списке. ЕслиshiftIds непусты, то |
roleRequirements[] | Требуемое количество сотрудников, которые будут назначены на указанные роли в течение временного окна. Для каждого идентификатора роли должно быть указано не более одного |
skillRequirements[] | Требуемое количество сотрудников с указанными навыками, назначенных на смены в течение временного окна. Для каждого идентификатора навыка должно быть указано не более одного |
РольТребование
Требуемое количество сотрудников, которые будут назначены на указанную роль в течение временного окна.
JSON-представление |
---|
{
"roleId": string,
"targetEmployeeCount": integer,
"priority": enum ( |
Поля | |
---|---|
roleId | Идентификатор роли для требования. |
targetEmployeeCount | Желаемое количество сотрудников, назначенных на эту роль в течение временного окна. |
priority | Уровень приоритета для этого ограничения требования. Приоритет по умолчанию для всех ограничений ресурсов — |
Требование к навыку
Необходимое количество сотрудников, работающих в течение определенного временного окна и обладающих указанными навыками.
JSON-представление |
---|
{
"skillId": string,
"targetEmployeeCount": integer,
"priority": enum ( |
Поля | |
---|---|
skillId | Идентификатор навыка для требования. |
targetEmployeeCount | Желаемое количество сотрудников с заданной квалификацией, работающих в течение определенного временного окна. |
priority | Уровень приоритета для этого ограничения требования. Приоритет по умолчанию для всех ограничений ресурсов — |
Требование к бюджету
Бюджетные требования на заданный интервал.
JSON-представление |
---|
{ "totalBudget": number, "startDateTime": { object ( |
Поля | |
---|---|
totalBudget | Общий бюджет за заданный интервал. Общий бюджет должен быть указан, если приоритет равен Если |
startDateTime | Время начала применения этого бюджета. Если время начала не указано, оно устанавливается как самое раннее время начала всех заданных смен. |
endDateTime | Время окончания применения этого бюджета. Если время окончания не указано, оно устанавливается как самое позднее время окончания всех заданных смен. |
priority | Уровень приоритета для удовлетворения бюджетных требований в течение указанного временного окна. Приоритет по умолчанию — Обратите внимание: если этот приоритет выше, чем другие приоритеты ограничений, и если |
Назначение смены
Сотрудник, которому предстоит сменить роль.
JSON-представление |
---|
{
"employeeId": string,
"shiftId": string,
"roleId": string,
"breaks": [
{
object ( |
Поля | |
---|---|
employeeId | Назначаемый идентификатор сотрудника. |
shiftId | Идентификатор смены, присвоенный сотруднику. |
roleId | Идентификатор роли, назначенной сотруднику на смену. |
breaks[] | Список перерывов для этой смены. |
Перерыв
Период времени, в течение которого сотрудник прерывает свою работу во время смены.
JSON-представление |
---|
{
"startDateTime": {
object ( |
Поля | |
---|---|
startDateTime | Время начала перерыва. |
durationMinutes | Продолжительность перерыва в минутах. |
Статус решения
Статус решения (т. е. расписания) указывается в ответе решателя.
Перечисления | |
---|---|
SOLUTION_STATUS_UNSPECIFIED | Неопределенный статус ответа. |
FEASIBLE | Возвращенное расписание возможно, но может быть неоптимальным. |
OPTIMAL | Возвращенный график является оптимальным. |
INFEASIBLE | Для данных ограничений не существует приемлемого расписания. Решающая программа может вернуть это значение, если какое-либо подмножество ограничений с уровнем приоритета PRIORITY_MANDATORY не может быть удовлетворено. |
NOT_SOLVED | Расписание не найдено. |
NOT_SOLVED_DEADLINE_EXCEEDED | В указанный срок расписание не найдено. |