Top.Mail.Ru
Центр помощи / Для администратора / 4. Интеграции / Синхронизация пользователей / 1С: Синхронизация статусов расписания – как устроен скрипт

1С: Синхронизация статусов расписания – как устроен скрипт

Скрипт выбора данных — вторая половина обработки UnSpot Schedule Status Adapter: код на встроенном языке 1С, который выбирает из информационной базы сотрудников с email и определяет, какой рабочий статус у каждого из них на каждый день периода. В статье встроенный скрипт для конфигурации «ЗУП 3.1 (ПРОФ/КОРП)» разобран блок за блоком: что делает каждый блок, как определяются статусы и что можно менять в нестандартной конфигурации. Как подключить обработку — в статье 1С: Синхронизация статусов расписания – настройка интеграции, как она отправляет статусы — в статье 1С: Синхронизация статусов расписания – как устроен обработчик.

Кратко

Скрипт — часть обработки 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 здесь нет.

ПолеЧто содержитЗачем нужно
emailEmail сотрудника в нижнем регистреПо нему UnSpot понимает, чьё расписание менять: в запрос на установку статуса адрес уходит в поле userEmail
nameИмя и фамилия через пробелТолько для сообщений в журнале регистрации и в проверочном запуске. В UnSpot не передаётся
typePriority, rate, hiredAtПриоритет вида занятости, количество ставок, дата приёмаСлужебные: нужны для выбора одной позиции физлица (блок 2). Остаются в структуре, но обработка их не использует
entityСсылка на элемент справочника «Сотрудники»Служебное: по ссылкам собираются запросы данных учёта времени (блок 4) и периодов дистанционной работы (блок 7)

Статусы: переменная СтатусыСостоянийДляUnSpot

СтатусыСостоянийДляUnSpot — двухуровневое соответствие: дата (строка вида гггг-ММ-дд) → идентификатор физлица → числовой код статуса. Идентификатор физлица здесь — тот же ключ, что в СотрудникиДляUnSpot: по нему обработка находит email сотрудника.

ДатаИдентификатор физлицаКод статуса
2026-10-21a1b2c3d4-0000-4000-8000-0123456789ab3 — «Отпуск»
2026-10-21b2c3d4e5-0000-4000-8000-0123456789ab1 — «Рабочее время»
2026-10-22a1b2c3d4-0000-4000-8000-0123456789ab3 — «Отпуск»

Коды — это шесть статусов, которые различает скрипт. В переменной действуют три правила:

  • на одну дату у сотрудника ровно один код: если вычислились два разных, дата для этого сотрудника в переменную не попадает;
  • если для даты у сотрудника записи нет, обработка ничего не отправляет, и статус, который уже стоит в UnSpot на эту дату, не меняется;
  • даты берутся из окна в 45 суток в обе стороны от текущего дня (при проверочном запуске — только текущий день).
КодСтатусКак определяется
1Рабочее времяВид учёта времени с признаком «рабочее время» — когда у него нет буквенного кода из таблицы соответствия
2БольничныйБуквенный код вида учёта времени: Б или Т
3ОтпускБуквенный код вида учёта времени из списка отпускных кодов
4КомандировкаБуквенный код вида учёта времени: К, ПК или ПМ
5ОтсутствиеБуквенный код вида учёта времени из списка неявок
6Удалённая работаБуквенный код вида учёта времени Д или рабочий день внутри периода дистанционной работы по договору

Подробно, по каждому статусу отдельно, — в разделе Как вычисляется каждый статус. Как коды превращаются в статусы UnSpot и что с ними делает обработка — в статье 1С: Синхронизация статусов расписания – как устроен обработчик.

Как вычисляется каждый статус

Статусы скрипт вычисляет не по документам, а по данным учёта рабочего времени ЗУП. Для каждого сотрудника и каждой даты окна ЗУП возвращает строку с видом учёта времени — тем, который он сам проставил на этот день с учётом графика, отпусков, больничных и командировок (блок 4). Дальше скрипт решает для каждой такой строки, какому статусу она соответствует. Листинги ниже — куски встроенного скрипта без комментариев; полные блоки — в разделе Разбор по блокам. Многоточие в листинге означает пропущенные строки.

Сначала сотрудники: поля email и name

Откуда. Кадровые данные сотрудников, действующих на текущую дату (блок 1). В выборку попадают только сотрудники с заполненным email — отбор EMailПредставление <> "". Ключ соответствия — идентификатор физлица: на нём же отсеиваются дубли по физлицу (блок 2).

Как вычисляется. Email приводится к нижнему регистру функцией НРег; имя для журнала собирается как «Имя Фамилия».

ИдФизЛица = Строка(СотрудникКД.ФизическоеЛицо.УникальныйИдентификатор());
...
ЭлементСотрудника.Вставить("email", НРег(СотрудникКД.EMailПредставление));
ЭлементСотрудника.Вставить("name", СотрудникКД.Имя + " " + СотрудникКД.Фамилия);
1С

Общий порядок: как скрипт определяет статус дня

Статус определяется для каждой строки данных учёта времени — сотрудник, дата, вид учёта времени. Скрипт идёт по трём шагам в строгом порядке и останавливается на первом сработавшем:

  1. Шаг 1. Буквенный код. У вида учёта времени берётся буквенный код — реквизит БуквенныйКодБюджетный; если он не заполнен, код берётся у основного вида времени. Если код есть в таблице соответствия, статус найден;
  2. Шаг 2. Признак «рабочее время». Если по коду статус не найден, но у вида учёта времени установлен признак «рабочее время», день — «Рабочее время»;
  3. Шаг 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, дата и обобщённый статус.

Связанные статьи

Оставьте заявку, и мы свяжемся с вами в течение 30 минут.

Loading

Как улучшить работу офиса?

Оставьте контакт - покажем на демо как уйти от таблиц, двойных бронирований и путаницы с рабочими местами.

Loading