.. _working-schedule: Рабочее расписание ==================================== .. note:: Для использования рабочего расписания необходимо наличие лицензии "features.working-schedule" Без наличия лицензии рабочее расписание при расчетах будет учитывать только обычные выходные дни без учета производственного календаря. **Рабочее расписание** и **производственный календарь** — два взаимосвязанных инструмента для управления рабочим временем в системе. - **Производственный календарь** фиксирует нерабочие, праздничные и сокращённые дни — то, что отклоняется от стандартного графика. - **Рабочее расписание** определяет обычный распорядок рабочих дней: рабочие дни недели, время начала и окончания, часовой пояс и привязанный производственный календарь. Совместно они позволяют гибко настраивать рабочий график сотрудников и используются в различных модулях системы — например, для расчёта SLA в модуле «Service Desk». .. contents:: :depth: 3 Рабочее расписание используется для четырех видов операций: 1. Добавить рабочее время к определенной дате и времени. 2. Добавить рабочие дни к определенной дате. 3. Рассчитать количество рабочих дней между двумя датами. 4. Рассчитать количество рабочих дней между двумя датами с временем. Привязка рабочего расписания к пользователю или группе ------------------------------------------------------------ Для привязки рабочего расписания к пользователю или группе нужно создать ассоциацию ``has-working-schedule:schedule`` Часовые пояса -------------------------- При расчетах на основе рабочего расписания используется следующая логика при обработке часовых поясов: Если мы делаем расчеты с учетом рабочего времени, то есть следующие варианты: 1. В дате часовой пояс не указан — используется часовой пояс из рабочего расписания, результат не будет содержать часовой пояс. 2. В дате часовой пояс указан — дата/время, которые получает сервис, он переводит в часовой пояс рабочего расписания. После выполнения всех операций результат переводится в исходный часовой пояс. Настройка рабочего расписания ------------------------------------------------------------ В системе предусмотрены 2 сущности для настройки работы рабочего расписания. Производственный календарь ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Сущность нужна для формирования списка дат, которые изменяют обычный распорядок рабочих дней. Журнал **"Производственный календарь" (Рабочее пространство "Раздел администратора" - Модель)** доступен по адресу: ``v2/journals?journalId=working-calendar&viewMode=table&ws=admin$workspace`` .. image:: _static/calendar/calendar_1.png :width: 800 :align: center | .. image:: _static/calendar/calendar_2.png :width: 500 :align: center Атрибуты: .. list-table:: :widths: 10 10 10 :header-rows: 1 * - ID - Тип - Описание * - id - String - Идентификатор * - extensionFor - EntityRef - Ссылка на календарь, который мы расширяем своей конфигурацией * - from - LocalDate - Дата начала действия календаря * - until - LocalDate - Дата окончания действия календаря * - enabled - Boolean - Активен ли календарь * - dates - List - Список дней календаря **WorkingCalendarDay** содержит следующие поля: .. list-table:: :widths: 10 10 10 :header-rows: 1 * - ID - Тип - Описание * - date - LocalDate - Конкретная дата или дата начала диапазона если задано значение until * - until - LocalDate - Дата окончания диапазона (включительно) * - type - String - | Тип даты или всех дат в диапазоне | Допустимые типы: | WORKING — рабочий день. Имеет смысл указывать, когда выходной день становится рабочим | HOLIDAY — праздник | SHORTDAY — сокращенный на 1ч рабочий день | WEEKEND — выходной | NON_WORKING — не рабочий день * - description - MLText - Описание дня или диапазона Рабочее расписание ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Определяет обычный распорядок рабочих дней. Журнал **"Рабочее расписание" (Рабочее пространство "Раздел администратора" - Модель)** доступен по адресу: ``v2/journals?journalId=type$working-schedule&viewMode=table&ws=admin$workspace`` .. image:: _static/calendar/calendar_3.png :width: 800 :align: center | .. image:: _static/calendar/calendar_4.png :width: 500 :align: center Атрибуты: .. list-table:: :widths: 10 10 10 :header-rows: 1 :align: center * - ID - Тип - Описание * - id - String - Идентификатор * - name - MLText - Имя расписания * - type - String - Тип расписания. Сейчас поддерживается только weekly * - config - ObjectData - Конфигурация для типа расписания Конфигурация расписания для типа weekly: .. list-table:: :widths: 10 10 10 :header-rows: 1 :align: center * - ID - Тип - Описание * - workingDayStart - LocalTime - Начало рабочего дня * - workingDayEnd - LocalTime - Завершение рабочего дня * - workingDayTimeZone - ZoneId - Часовой пояс рабочего дня * - workingDays - List - Список рабочих дней * - workingCalendar - EntityRef - Ссылка на производственный календарь Использование сервиса WorkingScheduleService в java/kotlin коде ---------------------------------------------------------------- 1. Добавляем сервис ``ru.citeck.ecos.wkgsch.lib.schedule.WorkingScheduleService`` как spring бин. 2. Получаем рабочее расписание используя один из методов для поиска: .. code-block:: kotlin fun getScheduleById(id: String) fun getScheduleForGroup(groupId: String) fun getScheduleForUser(userName: String) fun querySchedule(query: WorkingScheduleQuery) 3. Используя методы интерфейса ``ru.citeck.ecos.wkgsch.lib.schedule.WorkingSchedule`` производим вычисления даты и/или времени в зависимости от рабочего расписания: .. code-block:: kotlin /** * This interface stands as a contract for defining working schedules. * It provides a range of functions that manipulate and interpret dates * with respect to a working calendar/week - which may vary depending on the locale * or the specific needs of a business. */ interface WorkingSchedule { /** * Adjusts a given date to its nearest following working day. * If the specified date is already a working day, no changes will be made. * Note: If the date has time and/or timeZone components, these will be preserved in the returned date. * * @param date any of date or datetime values Instant, LocalDate, LocalDateTime, OffsetDateTime, ZonedDateTime */ fun correctDate(date: T): T /** * Adjusts a given date to its nearest following working day and then adds specified working days to it. * Note: If the date has time and/or timeZone components, these will be preserved in the returned date. * * @param date any of date or datetime values Instant, LocalDate, LocalDateTime, OffsetDateTime, ZonedDateTime */ fun addWorkingDays(date: T, days: Int): T /** * Computes the number of working days between two dates. * * @param from the start date from which working days are counted. Accepted values: Instant, LocalDate, LocalDateTime, OffsetDateTime, ZonedDateTime * @param to the end date up to which working days are counted. Accepted values: Instant, LocalDate, LocalDateTime, OffsetDateTime, ZonedDateTime */ fun getWorkingDays(from: Temporal, to: Temporal): Int /** * Adds a specified working time to a certain date. * * @param date any of date or datetime values Instant, LocalDate, LocalDateTime, OffsetDateTime, ZonedDateTime */ fun addWorkingTime(date: T, time: Duration): T /** * Get working time between two dates. * * @param from the start time from which working time are counted. Accepted values: Instant, LocalDateTime, OffsetDateTime, ZonedDateTime * @param to the end time up to which working time are counted. Accepted values: Instant, LocalDateTime, OffsetDateTime, ZonedDateTime */ fun getWorkingTime(from: Temporal, to: Temporal): Duration } Records API в браузере и при использовании в BPMN процессе ------------------------------------------------------------ Добавить рабочее время ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tabs:: .. tab:: В браузере .. code-block:: javascript await Records.queryOne({ sourceId: 'emodel/working-schedule-action', query: { type: 'add-working-time', config: {date: '2023-03-05T14:00:00', time: '10h'}, query: {scheduleId: 'DEFAULT'} } }, "data") .. tab:: В BPMN процессе .. code-block:: javascript Records.query({ sourceId: 'emodel/working-schedule-action', query: { type: 'add-working-time', config: {date: dl.toISOString(), time: '32h'}, query: {scheduleId: 'DEFAULT'} } }, 'data').records[0].data Результат: .. code-block:: text '2023-03-07T11:00' Добавить рабочие дни ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tabs:: .. tab:: В браузере .. code-block:: javascript await Records.queryOne({ sourceId: 'emodel/working-schedule-action', query: { type: 'add-working-days', config: {date: '2023-03-05', days: 10}, query: {scheduleId: 'DEFAULT'} } }, "data") .. tab:: В BPMN процессе .. code-block:: javascript Records.query({ sourceId: 'emodel/working-schedule-action', query: { type: 'add-working-days', config: {date: '2023-03-05', days: 10}, query: {scheduleId: 'DEFAULT'} } }, 'data').records[0].data Результат: .. code-block:: text '2023-03-21' Рассчитать количество рабочих дней между двумя датами ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tabs:: .. tab:: В браузере .. code-block:: javascript await Records.queryOne({ sourceId: 'emodel/working-schedule-action', query: { type: 'get-working-days', config: {from: '2023-03-05', to: '2023-03-21'}, query: {scheduleId: 'DEFAULT'} } }, "data") .. tab:: В BPMN процессе .. code-block:: javascript Records.query({ sourceId: 'emodel/working-schedule-action', query: { type: 'get-working-days', config: {from: '2023-03-05', to: '2023-03-21'}, query: {scheduleId: 'DEFAULT'} } }, 'data').records[0].data Результат: .. code-block:: text '11' Рассчитать количество рабочих дней между двумя датами с временем ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. tabs:: .. tab:: В браузере .. code-block:: javascript await Records.queryOne({ sourceId: 'emodel/working-schedule-action', query: { type: 'get-working-time', config: {from: '2023-03-05', to: '2023-03-21'}, query: {} } }, "data") .. tab:: В BPMN процессе .. code-block:: javascript Records.query({ sourceId: 'emodel/working-schedule-action', query: { type: 'get-working-time', config: {from: '2023-03-05', to: '2023-03-21'}, query: {} } }, 'data').records[0].data Результат: .. code-block:: text 'PT80H' Во всех запросах есть поле ``query``, которое может иметь следующие поля: .. list-table:: :widths: 10 10 10 :header-rows: 1 :align: center * - ID - Тип - Описание * - user - String - | Пользователь, для которого нам нужно найти рабочее расписание. | Если расписание для пользователя не найдено, то берется DEFAULT. * - group - String - | Группа, для которой нам нужно найти рабочее расписание. | Если расписание для группы не найдено, то берется DEFAULT. * - scheduleId - String - | Идентификатор конкретного рабочего расписания. | Если задан, то user и group игнорируются. | Примеры идентификатора: 'DEFAULT', "some-id"