1С: Синхронизация статусов расписания – как устроен скрипт
Скрипт выбора данных — вторая половина обработки UnSpot Schedule Status Adapter: код на встроенном языке 1С, который выбирает из информационной базы сотрудников с email и определяет, какой рабочий статус у каждого из них на каждый день периода. В статье встроенный скрипт для конфигурации «ЗУП 3.1 (ПРОФ/КОРП)» разобран блок за блоком: что делает каждый блок, как определяются статусы и что можно менять в нестандартной конфигурации. Как подключить обработку — в статье 1С: Синхронизация статусов расписания – настройка интеграции, как она отправляет статусы — в статье 1С: Синхронизация статусов расписания – как устроен обработчик.
Содержание
Где находится скрипт и что он возвращает
Что скрипт получает от обработки
Сотрудники: переменная СотрудникиДляUnSpot
Статусы: переменная СтатусыСостоянийДляUnSpot
Сначала сотрудники: поля email и name
Общий порядок: как скрипт определяет статус дня
Один статус на день: что делает скрипт, если признаков несколько
Как результат превращается в статусы UnSpot
Кратко
Скрипт — часть обработки UnSpot Schedule Status Adapter. Для каждого сотрудника и каждого дня в периоде от 45 дней назад до 45 дней вперёд он смотрит, какой вид учёта времени поставила на этот день ЗУП, и превращает его в статус расписания UnSpot:
| Статус | Буквенные коды вида учёта времени | Что увидят в расписании UnSpot |
|---|---|---|
| Рабочее время | вид с признаком «рабочее время», код которого не входит в эту таблицу (например, явка Я) | Отметки нет: ранее поставленный статус снимается, а с ним и личные брони столов сотрудника на этот день |
| Больничный | Б, Т | Не работаю · «Больничный», код БЛ |
| Отпуск | О, ОТ, ОД, ОУ, ДБ, Р, УД, У, ОЗ, ДО, ОЖ | Не работаю · «Отпуск», код ОТ |
| Командировка | К, ПК, ПМ | Работаю удалённо · «Командировка», код К |
| Отсутствие | НН, НБ, НО, ПВ, П, Г, ЗБ, НЗ, ПР | Не работаю · «Отсутствие», код НН |
| Удалённая работа | Д, а также рабочий день в периоде дистанционной работы по договору | Работаю удалённо · «Удаленная работа», код Д |
| Остальные дни | выходные и виды без кода из таблицы | Ничего не меняется |
- Если на один день у сотрудника получилось два разных статуса, день для него пропускается.
- Сам скрипт ничего в UnSpot не отправляет: сравнивает с кэшем и отправляет обработка.
- Ниже сначала описаны данные, которые собирает скрипт, и как вычисляется каждый статус, затем — блоки скрипта (свёрнуты).
- Незнакомое слово — загляните в раздел Термины статьи-обзора.
Где находится скрипт и что он возвращает
Скрипт — это текст в поле «Код выбора данных для синхронизации» формы настроек обработки. Если в поле «Конфигурация 1С» выбрано «ЗУП 3.1 (ПРОФ/КОРП)», поле доступно только для просмотра, а текст скрипта обновляется вместе с обработкой. Если выбрана «Нестандартная конфигурация», поле редактируется, и ваш код выполняется вместо встроенного.
В начале каждого запуска обработка выполняет текст скрипта на сервере 1С: при «Сохранить и запустить» и по расписанию — в фоновом задании, при «Сохранить и проверить» — в серверном вызове формы. На выходе скрипт оставляет две переменные:
СотрудникиДляUnSpot— соответствие «идентификатор физлица → структура с полямиemailиname», то есть кого синхронизировать;СтатусыСостоянийДляUnSpot— соответствие «дата → идентификатор физлица → код статуса», то есть какой статус у кого и на какой день.
Остальное делает обработка: превращает коды в статусы UnSpot, сравнивает результат с кэшем и отправляет изменения. Если после выполнения хотя бы одна из двух переменных осталась не определена, запуск завершается ошибкой.
Что учитывать. Скрипт выполняется без ограничений безопасного режима и с правами пользователя, от имени которого идёт синхронизация. Относитесь к правке этого поля как к правке кода конфигурации и ограничьте доступ к форме настроек администраторами.
Что скрипт получает от обработки
| Переменная | Что это | Значения |
|---|---|---|
ТестовыйЗапуск | Признак проверочного запуска | Истина — запуск кнопкой «Сохранить и проверить», Ложь — обычный запуск |
НазваниеМодуля | Имя источника для записей журнала регистрации | Строка вида UnSpotScheduleStatus#дата; дата — день первого сохранения настроек |
От настроек формы скрипт больше ничего не зависит: у обработки нет режимов и флажков, меняющих выборку.
Схема работы скрипта
Скрипт состоит из восьми блоков, которые выполняются сверху вниз.
| № | Блок | Что делает |
|---|---|---|
| 0 | Период | Определяет даты начала и окончания выборки |
| 1 | Выбор сотрудников | Получает действующих сотрудников с заполненным email |
| 2 | Одно место работы | Из нескольких позиций одного физлица оставляет одну и формирует СотрудникиДляUnSpot |
| 3 | Проверка выборки | Останавливает запуск, если сотрудников с email нет |
| 4 | Данные учёта времени | Запрашивает у ЗУП виды учёта времени сотрудников по дням периода |
| 5 | Соответствие кодов | Задаёт, какому статусу UnSpot соответствует буквенный код вида времени |
| 6 | Статусы по дням | Для каждой строки учёта времени определяет статус и собирает статусы по датам и сотрудникам |
| 7 | Один статус на день | Сводит несколько статусов дня к одному, учитывает дистанционную работу по договору |
Какие данные собирает скрипт
Скрипт оставляет после себя две переменные. Сама обработка после работы скрипта в базу ничего не смотрит: она берёт эти две переменные, превращает их в запросы и отправляет в UnSpot. Переменные работают в паре: первая отвечает на вопрос «кого синхронизировать и как найти его в UnSpot», вторая — на вопрос «какой статус у кого и на какую дату».
Сотрудники: переменная СотрудникиДляUnSpot
СотрудникиДляUnSpot — соответствие. Ключ — идентификатор физлица в 1С (строка из 36 символов), значение — структура с данными сотрудника. Физлицо, работающее на нескольких позициях, попадает сюда один раз: лишние позиции отсеиваются в блоке 2. Уволенных сотрудников и сотрудников без email здесь нет.
| Поле | Что содержит | Зачем нужно |
|---|---|---|
email | Email сотрудника в нижнем регистре | По нему UnSpot понимает, чьё расписание менять: в запрос на установку статуса адрес уходит в поле userEmail |
name | Имя и фамилия через пробел | Только для сообщений в журнале регистрации и в проверочном запуске. В UnSpot не передаётся |
typePriority, rate, hiredAt | Приоритет вида занятости, количество ставок, дата приёма | Служебные: нужны для выбора одной позиции физлица (блок 2). Остаются в структуре, но обработка их не использует |
entity | Ссылка на элемент справочника «Сотрудники» | Служебное: по ссылкам собираются запросы данных учёта времени (блок 4) и периодов дистанционной работы (блок 7) |
Статусы: переменная СтатусыСостоянийДляUnSpot
СтатусыСостоянийДляUnSpot — двухуровневое соответствие: дата (строка вида гггг-ММ-дд) → идентификатор физлица → числовой код статуса. Идентификатор физлица здесь — тот же ключ, что в СотрудникиДляUnSpot: по нему обработка находит email сотрудника.
| Дата | Идентификатор физлица | Код статуса |
|---|---|---|
2026-10-21 | a1b2c3d4-0000-4000-8000-0123456789ab | 3 — «Отпуск» |
2026-10-21 | b2c3d4e5-0000-4000-8000-0123456789ab | 1 — «Рабочее время» |
2026-10-22 | a1b2c3d4-0000-4000-8000-0123456789ab | 3 — «Отпуск» |
Коды — это шесть статусов, которые различает скрипт. В переменной действуют три правила:
- на одну дату у сотрудника ровно один код: если вычислились два разных, дата для этого сотрудника в переменную не попадает;
- если для даты у сотрудника записи нет, обработка ничего не отправляет, и статус, который уже стоит в UnSpot на эту дату, не меняется;
- даты берутся из окна в 45 суток в обе стороны от текущего дня (при проверочном запуске — только текущий день).
| Код | Статус | Как определяется |
|---|---|---|
1 | Рабочее время | Вид учёта времени с признаком «рабочее время» — когда у него нет буквенного кода из таблицы соответствия |
2 | Больничный | Буквенный код вида учёта времени: Б или Т |
3 | Отпуск | Буквенный код вида учёта времени из списка отпускных кодов |
4 | Командировка | Буквенный код вида учёта времени: К, ПК или ПМ |
5 | Отсутствие | Буквенный код вида учёта времени из списка неявок |
6 | Удалённая работа | Буквенный код вида учёта времени Д или рабочий день внутри периода дистанционной работы по договору |
Подробно, по каждому статусу отдельно, — в разделе Как вычисляется каждый статус. Как коды превращаются в статусы UnSpot и что с ними делает обработка — в статье 1С: Синхронизация статусов расписания – как устроен обработчик.
Как вычисляется каждый статус
Статусы скрипт вычисляет не по документам, а по данным учёта рабочего времени ЗУП. Для каждого сотрудника и каждой даты окна ЗУП возвращает строку с видом учёта времени — тем, который он сам проставил на этот день с учётом графика, отпусков, больничных и командировок (блок 4). Дальше скрипт решает для каждой такой строки, какому статусу она соответствует. Листинги ниже — куски встроенного скрипта без комментариев; полные блоки — в разделе Разбор по блокам. Многоточие в листинге означает пропущенные строки.
Сначала сотрудники: поля email и name
Откуда. Кадровые данные сотрудников, действующих на текущую дату (блок 1). В выборку попадают только сотрудники с заполненным email — отбор EMailПредставление <> "". Ключ соответствия — идентификатор физлица: на нём же отсеиваются дубли по физлицу (блок 2).
Как вычисляется. Email приводится к нижнему регистру функцией НРег; имя для журнала собирается как «Имя Фамилия».
ИдФизЛица = Строка(СотрудникКД.ФизическоеЛицо.УникальныйИдентификатор());
...
ЭлементСотрудника.Вставить("email", НРег(СотрудникКД.EMailПредставление));
ЭлементСотрудника.Вставить("name", СотрудникКД.Имя + " " + СотрудникКД.Фамилия);1СОбщий порядок: как скрипт определяет статус дня
Статус определяется для каждой строки данных учёта времени — сотрудник, дата, вид учёта времени. Скрипт идёт по трём шагам в строгом порядке и останавливается на первом сработавшем:
- Шаг 1. Буквенный код. У вида учёта времени берётся буквенный код — реквизит
БуквенныйКодБюджетный; если он не заполнен, код берётся у основного вида времени. Если код есть в таблице соответствия, статус найден; - Шаг 2. Признак «рабочее время». Если по коду статус не найден, но у вида учёта времени установлен признак «рабочее время», день — «Рабочее время»;
- Шаг 3. Пропуск. Если не сработали ни код, ни признак, строка пропускается: статус на эту дату не вычисляется. Если при этом у вида есть буквенный код, но соответствия для него нет, скрипт пишет сообщение в журнал регистрации.
Порядок важен: код проверяется раньше признака. Вид учёта времени с кодом Д и с признаком «рабочее время» даст статус «Удалённая работа», а не «Рабочее время». И обратно: статуса не бывает у вида, который не работа и которого нет в таблице кодов, — например, у выходного дня.
Если
БуквенныйКодВидаУчетаВремени <> Неопределено
И СоответствиеВидаУчетаВремениСтатусу.Получить(БуквенныйКодВидаУчетаВремени) <> Неопределено
Тогда
Статус = СоответствиеВидаУчетаВремениСтатусу.Получить(БуквенныйКодВидаУчетаВремени);
ИначеЕсли СтрокаТЗ.ВидУчетаВремени.РабочееВремя Тогда
Статус = СоответствиеСтатусовUnSpot.РабочееВремя;
Иначе
Если БуквенныйКодВидаУчетаВремени <> Неопределено Тогда
ЗаписьЖурналаРегистрации(
НазваниеМодуля,
УровеньЖурналаРегистрации.Примечание,
ЭтотОбъект,
"вид учета времени пропускается - нет соответствия со статусом UnSpot",
Сотрудник["name"] + " " + ДатаФорматированная + " " + СтрокаТЗ.ВидУчетаВремени + ": " + БуквенныйКодВидаУчетаВремени
);
КонецЕсли;
Продолжить;
КонецЕсли;1СБуквенный код вида учёта времени получает функция обработки; она рекурсивно поднимается к основному виду времени, пока не найдёт заполненный код:
Функция ПолучитьБуквенныйКодВидаУчетаВремени(ВидУчетаВремени)
Если ЗначениеЗаполнено(ВидУчетаВремени.БуквенныйКодБюджетный) Тогда
БуквенныйКод = ВидУчетаВремени.БуквенныйКодБюджетный;
ИначеЕсли ЗначениеЗаполнено(ВидУчетаВремени.ОсновноеВремя)
И ВидУчетаВремени <> ВидУчетаВремени.ОсновноеВремя
Тогда
БуквенныйКод = ПолучитьБуквенныйКодВидаУчетаВремени(ВидУчетаВремени.ОсновноеВремя);
Иначе
БуквенныйКод = Неопределено;
КонецЕсли;
Возврат БуквенныйКод;
КонецФункции1ССами коды сгруппированы в таблицу соответствия СоответствиеВидаУчетаВремениСтатусу: ключ — буквенный код, значение — код статуса. Числовые коды статусов задаёт функция обработки ПолучитьСоответствиеСтатусовUnSpot.
Функция ПолучитьСоответствиеСтатусовUnSpot()
Если СоответствиеСтатусовUnSpot = Неопределено Тогда
СоответствиеСтатусовUnSpot = Новый Структура;
СоответствиеСтатусовUnSpot.Вставить("РабочееВремя", 1);
СоответствиеСтатусовUnSpot.Вставить("Больничный", 2);
СоответствиеСтатусовUnSpot.Вставить("Отпуск", 3);
СоответствиеСтатусовUnSpot.Вставить("Командировка", 4);
СоответствиеСтатусовUnSpot.Вставить("Отсутствие", 5);
СоответствиеСтатусовUnSpot.Вставить("УдаленнаяРабота", 6);
КонецЕсли;
Возврат СоответствиеСтатусовUnSpot;
КонецФункции1СЧто учитывать. Расшифровку кодов смотрите в справочнике «Виды учета времени» вашей ЗУП: в нестандартной конфигурации там могут быть свои виды с теми же или другими кодами. Вид с кодом, которого нет в таблице, статуса не получает.
Статус «Рабочее время»
Рабочее время — обычный рабочий день. Единственный статус, у которого нет собственных буквенных кодов: он определяется по признаку вида учёта времени.
| Что | Значение |
|---|---|
| Код в скрипте | 1 |
| Как определяется | У вида учёта времени дня установлен признак «рабочее время», а буквенного кода из таблицы соответствия нет |
| Что уходит в UnSpot | Статус не выставляется: тип, название и код передаются пустыми — это сброс статуса на эту дату. Побочный эффект на стороне UnSpot: сброс также снимает или останавливает собственные брони стола пользователя на эту дату |
| Зачем сброс | Если в 1С отпуск закончился или отменён, статус «Отпуск» должен исчезнуть из расписания UnSpot. Рабочий день — сигнал снять старый статус |
Признак проверяется на втором шаге общего порядка — в ветке ИначеЕсли … РабочееВремя. А сам сброс в обработке выглядит так: все три поля статуса пусты.
РабочееВремя = Новый Структура;
РабочееВремя.Вставить("statusType", Неопределено);
РабочееВремя.Вставить("statusName", Неопределено);
РабочееВремя.Вставить("statusCode", Неопределено);
СтатусыUnSpot.Вставить(СоответствиеСтатусов.РабочееВремя, РабочееВремя);1СОсобые случаи. Рабочий день внутри периода дистанционной работы по договору позже, в блоке 7, превращается в «Удалённая работа» (см. ниже). Дни, у которых вид учёта времени не рабочее время и не имеет кода из таблицы (например, выходные), статуса не получают: для них ничего не отправляется, и ранее выставленный статус на эти даты в UnSpot остаётся. О сбросе статуса и влиянии на брони — в статье 1С: Синхронизация статусов расписания – как устроен обработчик.
Статус «Больничный»
Больничный — день, которому ЗУП поставила вид учёта времени с кодом больничного. Скрипт не читает документы напрямую: он смотрит, какой вид учёта времени ЗУП поставила на день, и если у вида один из кодов Б или Т, считает день больничным.
| Что | Значение |
|---|---|
| Код в скрипте | 2 |
| Буквенные коды видов учёта времени | Б, Т |
| Что уходит в UnSpot | Тип NOT_WORKING, название «Больничный», код в расписании БЛ |
СоответствиеВидаУчетаВремениСтатусу.Вставить("Б", СоответствиеСтатусовUnSpot.Больничный);
СоответствиеВидаУчетаВремениСтатусу.Вставить("Т", СоответствиеСтатусовUnSpot.Больничный);1СОсобые случаи. Скрипт считает период от 45 суток назад до 45 суток вперёд, поэтому статус получают и будущие дни окна, на которые больничный уже оформлен. Если на один день у сотрудника вычислилось два разных статуса — дата пропускается (см. «Один статус на день»).
Статус «Отпуск»
Отпуск — день, которому ЗУП поставила вид учёта времени с одним из отпускных кодов. Определяется так же, как больничный, — по буквенному коду вида учёта времени, но кодов здесь одиннадцать.
| Что | Значение |
|---|---|
| Код в скрипте | 3 |
| Буквенные коды видов учёта времени | О, ОТ, ОД, ОУ, ДБ, Р, УД, У, ОЗ, ДО, ОЖ |
| Что уходит в UnSpot | Тип NOT_WORKING, название «Отпуск», код в расписании ОТ |
СоответствиеВидаУчетаВремениСтатусу.Вставить("О", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОТ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОД", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОУ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ДБ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("Р", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("УД", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("У", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОЗ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ДО", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОЖ", СоответствиеСтатусовUnSpot.Отпуск);1СОсобые случаи. Одиннадцать кодов дают один и тот же статус: в UnSpot они все видны как «Отпуск», различить их по статусу нельзя. Даты будущих отпусков получают статус заранее, как только отпуск оформлен в ЗУП.
Статус «Командировка»
Командировка — дни, на которые у вида учёта времени один из трёх кодов: К, ПК или ПМ. Что именно обозначают ПК и ПМ в вашей базе, видно в справочнике «Виды учета времени».
| Что | Значение |
|---|---|
| Код в скрипте | 4 |
| Буквенные коды видов учёта времени | К, ПК, ПМ |
| Что уходит в UnSpot | Тип REMOTE_WORK, название «Командировка», код в расписании К |
СоответствиеВидаУчетаВремениСтатусу.Вставить("К", СоответствиеСтатусовUnSpot.Командировка);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПК", СоответствиеСтатусовUnSpot.Командировка);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПМ", СоответствиеСтатусовUnSpot.Командировка);1СОсобые случаи. В отличие от отпуска и больничного, у командировки тип статуса REMOTE_WORK, а не NOT_WORKING: в UnSpot сотрудник в командировке считается работающим вне офиса, а не отсутствующим.
Статус «Отсутствие»
Отсутствие — день, которому ЗУП поставила вид учёта времени с кодом неявки, не относящийся ни к больничному, ни к отпуску, ни к командировке. Это не «всё остальное»: статус получают только виды учёта времени с кодами из списка ниже.
| Что | Значение |
|---|---|
| Код в скрипте | 5 |
| Буквенные коды видов учёта времени | НН, НБ, НО, ПВ, П, Г, ЗБ, НЗ, ПР |
| Что уходит в UnSpot | Тип NOT_WORKING, название «Отсутствие», код в расписании НН |
СоответствиеВидаУчетаВремениСтатусу.Вставить("НН", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НБ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НО", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПВ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("П", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("Г", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ЗБ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НЗ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПР", СоответствиеСтатусовUnSpot.Отсутствие);1СОсобые случаи. Вид учёта времени с кодом, которого нет ни в одной группе таблицы (и у которого нет признака «рабочее время»), статуса не получает: день пропускается, а в журнал регистрации пишется сообщение «вид учета времени пропускается – нет соответствия со статусом UnSpot». Если ваша конфигурация использует другие коды неявок, добавьте их в таблицу соответствия — это единственный способ получить для них статус.
Статус «Удалённая работа»
Удалённая работа — единственный статус, который определяется двумя независимыми способами. Результат у них одинаковый, а источники данных разные.
| Что | Значение |
|---|---|
| Код в скрипте | 6 |
| Способ 1: по виду учёта времени | Буквенный код вида учёта времени Д — определяется на общем шаге 1, как любой другой статус |
| Способ 2: по периоду в договоре | Рабочий день (статус «Рабочее время») внутри периода дистанционной работы по регистру сведений «Дистанционная работа сотрудников» — определяется в блоке 7 |
| Что уходит в UnSpot | Тип REMOTE_WORK, название «Удаленная работа», код в расписании Д |
Способ 1: вид учёта времени с кодом Д. Если у вида учёта времени дня — или у его основного вида — буквенный код Д, строка сразу получает статус «Удалённая работа». Это обычное соответствие кода и статуса:
СоответствиеВидаУчетаВремениСтатусу.Вставить("Д", СоответствиеСтатусовUnSpot.УдаленнаяРабота);1ССпособ 2: период дистанционной работы по договору. Второй способ работает только на днях, которые по общему порядку оказались обычными рабочими, — на отпуске, больничном, командировке и отсутствии он ничего не меняет. Он нужен тем сотрудникам, у кого дистанционная работа оформлена записью в этом регистре, а в графике ЗУП день остаётся обычным рабочим. Вычисление идёт в три шага.
Шаг 1. Проверка, используется ли дистанционная работа. Скрипт спрашивает у подсистемы дистанционной работы, включена ли она в конфигурации. Если общего модуля нет, он выключен или вызов закончился ошибкой, весь способ пропускается: данные по периодам не собираются, и статус «Рабочее время» остаётся как есть.
Шаг 2. Выборка периодов. Для выбранных сотрудников из регистра сведений «Дистанционная работа сотрудников» читаются записи, начавшиеся в окне, плюс срез последних записей на начало окна — то, что действовало ещё до него. У каждой записи три значения: когда начала действовать, работает ли сотрудник дистанционно (Истина или Ложь) и до какой даты действует. Записи упорядочены по сотруднику и дате начала.
Попытка
МодульДистанционнаяРабота = ОбщегоНазначения.ОбщийМодуль("ДистанционнаяРабота");
Если МодульДистанционнаяРабота <> Неопределено Тогда
ИспользуетcяДистанционнаяРабота = МодульДистанционнаяРабота.ИспользуетсяДистанционнаяРабота();
Иначе
ИспользуетcяДистанционнаяРабота = Ложь;
КонецЕсли;
Исключение
ИспользуетcяДистанционнаяРабота = Ложь;
КонецПопытки;
...
Запрос.Текст =
"ВЫБРАТЬ
| Дистанционка.Сотрудник КАК Сотрудник,
| Дистанционка.Период КАК Период,
| Дистанционка.РаботаетДистанционно КАК Статус,
| Дистанционка.ДействуетДо КАК ДатаОкончания
|ИЗ
| РегистрСведений.ДистанционнаяРаботаСотрудников КАК Дистанционка
|ГДЕ
| Дистанционка.Сотрудник В (&МассивСотрудников)
| И Дистанционка.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| СрезНаНачало.Сотрудник,
| &ДатаНачала,
| СрезНаНачало.РаботаетДистанционно,
| СрезНаНачало.ДействуетДо
|ИЗ
| РегистрСведений.ДистанционнаяРаботаСотрудников.СрезПоследних(&ДатаНачала, Сотрудник В (&МассивСотрудников)) КАК СрезНаНачало
|
|УПОРЯДОЧИТЬ ПО
| Сотрудник,
| Период";1СШаг 3. Проверка каждого дня. Для дня со статусом «Рабочее время» скрипт перебирает записи сотрудника по порядку. Как только встречается запись, которая начинается позже проверяемого дня, перебор прекращается. Запись «действует» в этот день, если у неё нет даты окончания или дата окончания позже дня; признак Истина или Ложь из последней такой записи и решает. Если итог Истина, день получает статус «Удалённая работа».
Если ДистанционнаяПоСотруднику <> Неопределено
И СтатусСотрудникаНаДату = СоответствиеСтатусовUnSpot.РабочееВремя
И ДистанционнаяПоСотруднику.Получить(ИдСотрудника) <> Неопределено
Тогда
СтатусДистанционнойРаботы = Ложь;
Для Каждого ДистанционныйПериод Из ДистанционнаяПоСотруднику.Получить(ИдСотрудника) Цикл
Если НачалоДня(ДистанционныйПериод.Период) > ДатаСтатусовСостояний.Значение Тогда
Прервать;
ИначеЕсли
Не ЗначениеЗаполнено(ДистанционныйПериод.ДатаОкончания)
Или НачалоДня(ДистанционныйПериод.ДатаОкончания) > ДатаСтатусовСостояний.Значение
Тогда
СтатусДистанционнойРаботы = ДистанционныйПериод.Статус;
КонецЕсли;
КонецЦикла;
Если СтатусДистанционнойРаботы Тогда
СтатусСотрудникаНаДату = СоответствиеСтатусовUnSpot.УдаленнаяРабота;
КонецЕсли;
КонецЕсли;1СОсобые случаи. Записи ищутся по выбранной позиции сотрудника (entity), а не по физлицу целиком. Дата окончания записи в период не входит: в день, указанный как «действует до», статус уже не меняется. Позднейшая запись с признаком Ложь отменяет предыдущую запись с Истина — так фиксируется возврат из дистанционной работы в офис.
Один статус на день: что делает скрипт, если признаков несколько
Строки данных учёта времени могут давать на один день сразу несколько статусов — например, полдня отпуска и полдня работы. Блок 6 складывает их в массив (одинаковые статусы считаются один раз), а блок 7 сводит массив к одному значению. UnSpot хранит на дату один статус, поэтому скрипт не пытается выбрать «главный»: при расхождении дата пропускается.
- статус один — он остаётся; если это «Рабочее время», дополнительно проверяется период дистанционной работы;
- статусов два и больше — дата для сотрудника пропускается, в журнал регистрации пишется сообщение «у сотрудника больше одного статуса на дату – эта дата для сотрудника пропускается».
КоличествоСтатусовСостоянийСотрудникаНаДату = СтатусыСостоянийСотрудникаНаДату.Значение.Количество();
Если КоличествоСтатусовСостоянийСотрудникаНаДату = 0 Тогда
СотрудникиДляУдаленияИзСтатусов.Добавить(ИдФизЛица);
ИначеЕсли КоличествоСтатусовСостоянийСотрудникаНаДату > 1 Тогда
ЗаписьЖурналаРегистрации(
НазваниеМодуля,
УровеньЖурналаРегистрации.Примечание,
ЭтотОбъект,
"у сотрудника больше одного статуса на дату - эта дата для сотрудника пропускается",
Сотрудник["name"] + " " + ДатаФорматированная
);
СотрудникиДляУдаленияИзСтатусов.Добавить(ИдФизЛица);
Иначе
СтатусСотрудникаНаДату = СтатусыСостоянийСотрудникаНаДату.Значение[0];
...
КонецЕсли;1СРазбор по блокам
Ниже каждый блок описан и показан так, как он выглядит в поле «Код выбора данных для синхронизации»; вспомогательные комментарии и запись в журнал в листингах опущены.
Блоки свёрнуты, чтобы не мешать чтению: нажмите на название блока, чтобы раскрыть его описание и листинг.
Блок 0. Период
Скрипт берёт окно в 45 суток в обе стороны от текущего дня: с начала дня на 45 суток раньше до конца дня на 45 суток позже. При проверочном запуске интервал равен нулю — выбирается только текущий день. Запись журнала фиксирует период выборки.
Сутки = 24 * 60 * 60;
// переменная ТестовыйЗапуск - это внешний параметр, Ложь при обычном запуске, Истина при проверке синхронизации
Если ТестовыйЗапуск Тогда
Интервал = 0;
Иначе
Интервал = 45 * Сутки;
КонецЕсли;
ДатаТекущая = НачалоДня(ТекущаяДатаСеанса());
ДатаНачала = НачалоДня(ТекущаяДатаСеанса()) - Интервал;
ДатаОкончания = КонецДня(ТекущаяДатаСеанса()) + Интервал;1СБлок 1. Выбор сотрудников
Метод КадровыйУчет.СотрудникиОрганизации возвращает только действующих (не уволенных) сотрудников на текущую дату. Из кадровых данных запрашиваются: сотрудник, физлицо, подразделение, должность, количество ставок, вид занятости, фамилия, имя, email, табельный номер и дата приёма. К выборке добавлен отбор по заполненному email: сотрудники без email не синхронизируются, потому что email — ключ, по которому UnSpot находит пользователя.
ПараметрыПолучения = КадровыйУчет.ПараметрыПолученияСотрудниковОрганизацийПоСпискуФизическихЛиц();
ПараметрыПолучения.КадровыеДанные = "Сотрудник,ФизическоеЛицо,Подразделение,Должность,КоличествоСтавок,ВидЗанятости,Фамилия,Имя,EMailПредставление,ТабельныйНомер,ДатаПриема";
ПараметрыПолучения.НачалоПериода = ТекущаяДата();
ПараметрыПолучения.ОкончаниеПериода = ТекущаяДата();
ЗарплатаКадрыОбщиеНаборыДанных.ДобавитьВКоллекциюОтбор(ПараметрыПолучения.Отборы, "EMailПредставление", "<>", """""", Ложь);
СотрудникиКД = КадровыйУчет.СотрудникиОрганизации(Истина, ПараметрыПолучения);1СБлок 2. Одно место работы на физлицо
Если физлицо работает сразу на нескольких позициях, статусы нужно отправить один раз. Каждому виду занятости присваивается приоритет: основное место работы — 4, внутреннее совместительство — 3, совместительство — 2, подработка — 1, любой другой вид — 0. Побеждает позиция с более высоким приоритетом, а при равном — с большим количеством ставок; если и приоритет, и количество ставок совпали, остаётся позиция, которая встретилась в выборке первой. Для оставшейся позиции создаётся запись с email, именем и служебными полями.
ПриоритетВидовЗанятости = Новый Соответствие;
ПриоритетВидовЗанятости.Вставить(Перечисления.ВидыЗанятости.Подработка, 1);
ПриоритетВидовЗанятости.Вставить(Перечисления.ВидыЗанятости.Совместительство, 2);
ПриоритетВидовЗанятости.Вставить(Перечисления.ВидыЗанятости.ВнутреннееСовместительство, 3);
ПриоритетВидовЗанятости.Вставить(Перечисления.ВидыЗанятости.ОсновноеМестоРаботы, 4);
// подготовка массива сотрудников (ключ - идентификатор физического лица)
// цикл обрабатывает каждого сотрудника, создаёт структуру, и сохраняет
// данные из переменной СотрудникиКД (из предыдущего запроса)
// метод УникальныйИдентификатор() справочника "ФизическоеЛицо"
// для дальнейшего сопоставления статусов и кэширования данных
СотрудникиДляUnSpot = Новый Соответствие;
Для Каждого СотрудникКД Из СотрудникиКД Цикл
ИдФизЛица = Строка(СотрудникКД.ФизическоеЛицо.УникальныйИдентификатор());
ПриоритетВидаЗанятости = 0;
Если ПриоритетВидовЗанятости[СотрудникКД.ВидЗанятости] <> Неопределено Тогда
ПриоритетВидаЗанятости = ПриоритетВидовЗанятости[СотрудникКД.ВидЗанятости];
КонецЕсли;
Если
СотрудникиДляUnSpot[ИдФизЛица] <> Неопределено
И (
СотрудникиДляUnSpot[ИдФизЛица]["typePriority"] > ПриоритетВидаЗанятости
ИЛИ СотрудникиДляUnSpot[ИдФизЛица]["typePriority"] = ПриоритетВидаЗанятости
И (
СотрудникиДляUnSpot[ИдФизЛица]["rate"] >= СотрудникКД.КоличествоСтавок
ИЛИ СотрудникиДляUnSpot[ИдФизЛица]["rate"] = СотрудникКД.КоличествоСтавок
И СотрудникиДляUnSpot[ИдФизЛица]["hiredAt"] >= СотрудникКД.ДатаПриема
)
)
Тогда
Продолжить;
КонецЕсли;
ЭлементСотрудника = Новый Структура;
ЭлементСотрудника.Вставить("email", НРег(СотрудникКД.EMailПредставление));
ЭлементСотрудника.Вставить("name", СотрудникКД.Имя + " " + СотрудникКД.Фамилия);
ЭлементСотрудника.Вставить("typePriority", ПриоритетВидаЗанятости);
ЭлементСотрудника.Вставить("rate", СотрудникКД.КоличествоСтавок);
ЭлементСотрудника.Вставить("hiredAt", СотрудникКД.ДатаПриема);
ЭлементСотрудника.Вставить("entity", СотрудникКД.Сотрудник);
СотрудникиДляUnSpot.Вставить(ИдФизЛица, ЭлементСотрудника);
КонецЦикла;1ССлужебные поля typePriority, rate, hiredAt нужны только для выбора позиции. Поле entity хранит ссылку на сотрудника и используется в блоках 4 и 7.
Блок 3. Проверка выборки
Скрипт собирает ссылки на выбранных сотрудников в массив, записывает в журнал их количество и, если сотрудников нет, прекращает работу с ошибкой «Не найдено сотрудников с заполненным email». Обычная причина — не заполнены email в карточках сотрудников.
МассивСотрудников = Новый Массив;
Для Каждого Сотрудник Из СотрудникиДляUnSpot Цикл
МассивСотрудников.Добавить(Сотрудник.Значение["entity"]);
КонецЦикла;
ЗаписьЖурналаРегистрации(
НазваниеМодуля,
УровеньЖурналаРегистрации.Примечание,
ЭтотОбъект,
"выбраны сотрудники с email для синхронизации статусов",
МассивСотрудников.Количество()
);
СтатусыСостоянийДляUnSpot = Новый Соответствие;
Если МассивСотрудников.Количество() = 0 Тогда
ВызватьИсключение "Не найдено сотрудников с заполненным email";
КонецЕсли;1СБлок 4. Данные учёта рабочего времени
Для выбранных сотрудников скрипт запрашивает у подсистемы учёта рабочего времени ЗУП (УчетРабочегоВремениРасширенный) вид учёта времени на каждый день периода. Расчёт включает плановое время, поэтому в данных есть и будущие дни: график, документы отклонений, отпуска, больничные и командировки учитываются так же, как в самом ЗУП. Результат — таблица значений ТЗ, где у каждой строки есть сотрудник, дата и вид учёта времени.
// формирование временной таблицы с сотрудниками, по которым надо получить статусы
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
СоздатьВТСотрудники(МенеджерВременныхТаблиц, МассивСотрудников, НачалоМесяца(ДатаНачала), ДатаТекущая, ДатаНачала, ДатаОкончания);
// получение статусов сотрудников с помощью функции УчетРабочегоВремениРасширенный.СоздатьВТДанныеУчетаВремениИСостоянийСотрудников
ПараметрыПолученияДанных = УчетРабочегоВремениРасширенный.ПараметрыДляЗапросВТДанныеУчетаВремениИСостоянийСотрудников();
ПараметрыПолученияДанных.ИмяВТСотрудники = "ВТСотрудники";;
ПараметрыПолученияДанных.РассчитыватьПлановоеВремя = Истина;
ПараметрыПолученияДанных.ДатаАктуальности = ДатаТекущая;
ПараметрыПолученияДанных.ДатаНачала = ДатаНачала;
ПараметрыПолученияДанных.ДатаОкончания = ДатаОкончания;
ПараметрыПолученияДанных.МесяцДатаНачала = НачалоМесяца(ДатаНачала);
ПараметрыПолученияДанных.МесяцДатаОкончания = КонецМесяца(ДатаОкончания);
УчетРабочегоВремениРасширенный.СоздатьВТДанныеУчетаВремениИСостоянийСотрудников(МенеджерВременныхТаблиц, Истина, ПараметрыПолученияДанных);
ТЗ = МенеджерВременныхТаблиц.Таблицы.Найти(ПараметрыПолученияДанных.ИмяВТРезультат).ПолучитьДанные().Выгрузить();1СБлок 5. Соответствие кодов и статусов
Вид учёта времени в ЗУП обозначается буквенным кодом. Если у самого вида кода нет, берётся код его основного вида времени. Скрипт задаёт, какому статусу соответствует каждый код: коды Б и Т — больничный, коды О, ОТ, ОД, ОУ, ДБ, Р, УД, У, ОЗ, ДО, ОЖ — отпуск, К, ПК, ПМ — командировка, НН, НБ, НО, ПВ, П, Г, ЗБ, НЗ, ПР — отсутствие, Д — удалённая работа. Статус «Рабочее время» определяется отдельно, по признаку вида времени. Внутри скрипта статусы хранятся числовыми кодами, которые задаёт функция обработки ПолучитьСоответствиеСтатусовUnSpot.
| Статус | Код в скрипте | Буквенные коды видов времени |
|---|---|---|
| Рабочее время | 1 | Любой вид с признаком «рабочее время» и без соответствия в таблице |
| Больничный | 2 | Б, Т |
| Отпуск | 3 | О, ОТ, ОД, ОУ, ДБ, Р, УД, У, ОЗ, ДО, ОЖ |
| Командировка | 4 | К, ПК, ПМ |
| Отсутствие | 5 | НН, НБ, НО, ПВ, П, Г, ЗБ, НЗ, ПР |
| Удалённая работа | 6 | Д |
// формирование соответствия СтатусыСостоянийДляUnSpot: дата -> идентификатор сотрудника -> массив статусов
ДатыСтатусовСостояний = Новый СписокЗначений;
СоответствиеСтатусовUnSpot = ПолучитьСоответствиеСтатусовUnSpot();
// СоответствиеВидаУчетаВремениСтатусу - соответствие буквы статуса справочника видов рабочего времени статусу UnSpot
СоответствиеВидаУчетаВремениСтатусу = Новый Соответствие();
СоответствиеВидаУчетаВремениСтатусу.Вставить("Б", СоответствиеСтатусовUnSpot.Больничный);
СоответствиеВидаУчетаВремениСтатусу.Вставить("Т", СоответствиеСтатусовUnSpot.Больничный);
СоответствиеВидаУчетаВремениСтатусу.Вставить("О", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОТ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОД", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОУ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ДБ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("Р", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("УД", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("У", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОЗ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ДО", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ОЖ", СоответствиеСтатусовUnSpot.Отпуск);
СоответствиеВидаУчетаВремениСтатусу.Вставить("К", СоответствиеСтатусовUnSpot.Командировка);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПК", СоответствиеСтатусовUnSpot.Командировка);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПМ", СоответствиеСтатусовUnSpot.Командировка);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НН", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НБ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НО", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПВ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("П", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НН", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("Г", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ЗБ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("НЗ", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("ПР", СоответствиеСтатусовUnSpot.Отсутствие);
СоответствиеВидаУчетаВремениСтатусу.Вставить("Д", СоответствиеСтатусовUnSpot.УдаленнаяРабота);1СБлок 6. Статусы по дням
Скрипт проходит по строкам таблицы ТЗ. Для каждой строки он определяет статус: сначала по буквенному коду, затем — по признаку «рабочее время». Если у вида есть буквенный код, но соответствия нет, и у вида нет признака «рабочее время», строка пропускается, а в журнал пишется сообщение «вид учета времени пропускается – нет соответствия со статусом UnSpot». Определённые статусы складываются в соответствие СтатусыСостоянийДляUnSpot: дата → физлицо → массив статусов, потому что на один день у сотрудника может быть несколько записей.
Для Каждого СтрокаТЗ Из ТЗ Цикл
Если Не ЗначениеЗаполнено(СтрокаТЗ.ВидУчетаВремени)
Или Не ЗначениеЗаполнено(СтрокаТЗ.Сотрудник)
Или Не ЗначениеЗаполнено(СтрокаТЗ.Сотрудник.ФизическоеЛицо)
Тогда
Продолжить;
КонецЕсли;
ИдФизЛица = Строка(СтрокаТЗ.Сотрудник.ФизическоеЛицо.УникальныйИдентификатор());
Если СотрудникиДляUnSpot[ИдФизЛица] = Неопределено Тогда
Продолжить;
КонецЕсли;
Сотрудник = СотрудникиДляUnSpot[ИдФизЛица];
ДатаФорматированная = ФорматироватьДату(СтрокаТЗ.Дата);
БуквенныйКодВидаУчетаВремени = ПолучитьБуквенныйКодВидаУчетаВремени(СтрокаТЗ.ВидУчетаВремени);
Если
БуквенныйКодВидаУчетаВремени <> Неопределено
И СоответствиеВидаУчетаВремениСтатусу.Получить(БуквенныйКодВидаУчетаВремени) <> Неопределено
Тогда
// если у вида учета времени (или его основного времени) если буквенный код, то подбираем по нему
Статус = СоответствиеВидаУчетаВремениСтатусу.Получить(БуквенныйКодВидаУчетаВремени);
ИначеЕсли СтрокаТЗ.ВидУчетаВремени.РабочееВремя Тогда
// если у вида учета времени установлен признак рабочего времени, то это рабочее время
Статус = СоответствиеСтатусовUnSpot.РабочееВремя;
Иначе
// если у вида учета времени есть буквенный код, но для него нет соответствия - сообщаем об этом в журнал регистрации
Если БуквенныйКодВидаУчетаВремени <> Неопределено Тогда
ЗаписьЖурналаРегистрации(
НазваниеМодуля,
УровеньЖурналаРегистрации.Примечание,
ЭтотОбъект,
"вид учета времени пропускается - нет соответствия со статусом UnSpot",
Сотрудник["name"] + " " + ДатаФорматированная + " " + СтрокаТЗ.ВидУчетаВремени + ": " + БуквенныйКодВидаУчетаВремени
);
КонецЕсли;
Продолжить;
КонецЕсли;
// инициализируем статусы состояний сотрудников на эту дату
СтатусыСостоянийНаДату = СтатусыСостоянийДляUnSpot.Получить(ДатаФорматированная);
Если СтатусыСостоянийНаДату = Неопределено Тогда
СтатусыСостоянийНаДату = Новый Соответствие;
СтатусыСостоянийДляUnSpot.Вставить(ДатаФорматированная, СтатусыСостоянийНаДату);
ДатыСтатусовСостояний.Добавить(СтрокаТЗ.Дата);
КонецЕсли;
// инициализируем статусы состояний сотрудника на эту дату - в общем случае их может быть несколько, поэтому массив
СтатусыСостоянийСотрудникаНаДату = СтатусыСостоянийНаДату.Получить(ИдФизЛица);
Если СтатусыСостоянийСотрудникаНаДату = Неопределено Тогда
СтатусыСостоянийСотрудникаНаДату = Новый Массив;
СтатусыСостоянийНаДату.Вставить(ИдФизЛица, СтатусыСостоянийСотрудникаНаДату);
КонецЕсли;
Если СтатусыСостоянийСотрудникаНаДату.Найти(Статус) <> Неопределено Тогда
Продолжить;
КонецЕсли;
СтатусыСостоянийСотрудникаНаДату.Добавить(Статус);
КонецЦикла;1СБлок 7. Один статус на день
В UnSpot у сотрудника может быть только один статус на дату, поэтому массив статусов дня нужно свести к одному значению:
- если у сотрудника на дату один статус, он остаётся;
- если статусов больше одного (например, полдня отпуска и полдня работы), эта дата для сотрудника пропускается, а в журнал пишется сообщение «у сотрудника больше одного статуса на дату — эта дата для сотрудника пропускается»;
- если статус — «Рабочее время», а на эту дату действует период дистанционной работы по трудовому договору (регистр «Дистанционная работа сотрудников»), статус меняется на «Удалённая работа».
Проверка дистанционной работы выполняется только если в конфигурации используется подсистема дистанционной работы; иначе статус «Рабочее время» остаётся без изменений.
// выбор статусов дистанционной работы сотрудников
ДистанционнаяПоСотруднику = ПолучитьСтатусыДистанционнойРаботыСотрудников(МассивСотрудников, ДатаНачала, ДатаОкончания);
// преобразование соответствия СтатусыСостоянийДляUnSpot: дата -> идентификатор сотрудника -> один статус
ДатыСтатусовСостояний.СортироватьПоЗначению(НаправлениеСортировки.Возр);
Для Каждого ДатаСтатусовСостояний Из ДатыСтатусовСостояний Цикл
ДатаФорматированная = ФорматироватьДату(ДатаСтатусовСостояний.Значение);
СтатусыСостоянийСотрудниковПоДатам = СтатусыСостоянийДляUnSpot.Получить(ДатаФорматированная);
СотрудникиДляУдаленияИзСтатусов = Новый Массив;
Для Каждого СтатусыСостоянийСотрудникаНаДату Из СтатусыСостоянийСотрудниковПоДатам Цикл
ИдФизЛица = СтатусыСостоянийСотрудникаНаДату.Ключ;
Если СотрудникиДляUnSpot[ИдФизЛица] = Неопределено Тогда
СотрудникиДляУдаленияИзСтатусов.Добавить(ИдФизЛица);
Продолжить;
КонецЕсли;
Сотрудник = СотрудникиДляUnSpot[ИдФизЛица];
ИдСотрудника = Строка(Сотрудник["entity"].УникальныйИдентификатор());
КоличествоСтатусовСостоянийСотрудникаНаДату = СтатусыСостоянийСотрудникаНаДату.Значение.Количество();
Если КоличествоСтатусовСостоянийСотрудникаНаДату = 0 Тогда
// пустой массив статусов - будет удалён из соответствия
СотрудникиДляУдаленияИзСтатусов.Добавить(ИдФизЛица);
ИначеЕсли КоличествоСтатусовСостоянийСотрудникаНаДату > 1 Тогда
// статусов у сотрудника на дату больше одного - будет удалён из соответствия
ЗаписьЖурналаРегистрации(
НазваниеМодуля,
УровеньЖурналаРегистрации.Примечание,
ЭтотОбъект,
"у сотрудника больше одного статуса на дату - эта дата для сотрудника пропускается",
Сотрудник["name"] + " " + ДатаФорматированная
);
СотрудникиДляУдаленияИзСтатусов.Добавить(ИдФизЛица);
Иначе
СтатусСотрудникаНаДату = СтатусыСостоянийСотрудникаНаДату.Значение[0];
// проверка дистанционной работы
Если ДистанционнаяПоСотруднику <> Неопределено
И СтатусСотрудникаНаДату = СоответствиеСтатусовUnSpot.РабочееВремя
И ДистанционнаяПоСотруднику.Получить(ИдСотрудника) <> Неопределено
Тогда
СтатусДистанционнойРаботы = Ложь;
Для Каждого ДистанционныйПериод Из ДистанционнаяПоСотруднику.Получить(ИдСотрудника) Цикл
Если НачалоДня(ДистанционныйПериод.Период) > ДатаСтатусовСостояний.Значение Тогда
Прервать;
ИначеЕсли
Не ЗначениеЗаполнено(ДистанционныйПериод.ДатаОкончания)
Или НачалоДня(ДистанционныйПериод.ДатаОкончания) > ДатаСтатусовСостояний.Значение
Тогда
СтатусДистанционнойРаботы = ДистанционныйПериод.Статус;
КонецЕсли;
КонецЦикла;
Если СтатусДистанционнойРаботы Тогда
СтатусСотрудникаНаДату = СоответствиеСтатусовUnSpot.УдаленнаяРабота;
КонецЕсли;
КонецЕсли;
СтатусыСостоянийСотрудниковПоДатам.Вставить(ИдФизЛица, СтатусСотрудникаНаДату);
КонецЕсли;
КонецЦикла;
Для Каждого ИдФизЛица Из СотрудникиДляУдаленияИзСтатусов Цикл
СтатусыСостоянийСотрудниковПоДатам.Удалить(ИдФизЛица);
КонецЦикла;
КонецЦикла;1СКак результат превращается в статусы UnSpot
Числовые коды из соответствия СтатусыСостоянийДляUnSpot обработка преобразует в данные запроса к UnSpot. Для статуса «Рабочее время» передаются пустые значения — это сброс статуса на эту дату: так статус «Отпуск» исчезает из расписания, когда отпуск в 1С закончился или был отменён.
| Код | Статус | Тип в UnSpot | Название | Код в расписании |
|---|---|---|---|---|
| 1 | Рабочее время | пусто | пусто | пусто |
| 2 | Больничный | NOT_WORKING | Больничный | БЛ |
| 3 | Отпуск | NOT_WORKING | Отпуск | ОТ |
| 4 | Командировка | REMOTE_WORK | Командировка | К |
| 5 | Отсутствие | NOT_WORKING | Отсутствие | НН |
| 6 | Удалённая работа | REMOTE_WORK | Удаленная работа | Д |
Подробности отправки — какие поля уходят в запросе, как работает кэш и что пишется в журнал — в статье 1С: Синхронизация статусов расписания – как устроен обработчик.
Что можно менять в нестандартной конфигурации
Для нестандартной конфигурации за основу можно взять копию встроенного скрипта (скопируйте его в режиме «ЗУП 3.1 (ПРОФ/КОРП)», затем переключитесь на «Нестандартная конфигурация» и вставьте): всё, что вы не меняли, продолжает работать как описано выше. Требования к собственному скрипту описаны в статье 1С: Собственный скрипт – настройка интеграции.
| Что менять | Где | На что обратить внимание |
|---|---|---|
| Ширину окна | Блок 0, значение 45 * Сутки | Окно задаёт, за какой период статусы в UnSpot приводятся в соответствие с 1С; чем оно шире, тем дольше первый запуск: статусы отправляются по одному в секунду |
| Список реквизитов сотрудника и отбор | Блок 1 | Названия реквизитов должны существовать в вашей конфигурации; email остаётся обязательным |
| Приоритеты видов занятости | Блок 2 | Добавьте новые виды занятости, иначе они получат приоритет 0 |
| Источник данных учёта времени | Блок 4 | Если в вашей конфигурации нет подсистемы УчетРабочегоВремениРасширенный, замените запрос на свой: результат должен содержать сотрудника, дату и вид учёта времени |
| Соответствие кодов и статусов | Блок 5 | Добавьте буквенные коды видов времени вашей конфигурации; коды без соответствия пропускаются и попадают в журнал |
| Правило дистанционной работы | Блок 7 | Нужно, если дистанционная работа в вашей конфигурации хранится не в регистре «Дистанционная работа сотрудников» |
После правки нажмите «Сохранить и проверить»: обработка выполнит пробный запуск за текущий день, покажет, сколько сотрудников выбрано и по скольким датам есть статусы (в проверочном запуске — 0 или 1), и отправит статус в UnSpot.
Чего скрипт не делает
- Не отправляет данные в UnSpot и не читает данные UnSpot — это делает код обработки.
- Не записывает ничего в информационную базу: он только читает данные. Кэш отправленных статусов ведёт обработка.
- Не передаёт в UnSpot ФИО, должность, подразделение и основание отсутствия: в запрос уходят только email, дата и обобщённый статус.
Связанные статьи
- 1С: Синхронизация статусов расписания – настройка интеграции — требования, подключение, поля формы, регулярный запуск и диагностика.
- 1С: Синхронизация статусов расписания – как устроен обработчик — протокол, отправляемые данные, кэш и журнал.
- 1С: Собственный скрипт – настройка интеграции — как написать скрипт для нестандартной конфигурации.
- 1С: Обзор интеграции — какие бывают интеграции с 1С и с чего начать.
- External API: обновление статуса в расписании — описание эндпоинта, в который отправляются статусы.
- Статусы в расписании: простановка и влияние на брони — как статусы выглядят в UnSpot и что происходит с бронями.
- Управление рабочими статусами в расписании — настройка статусов.