При автоматизации кадрового учета в конфигурации 1С:Зарплата и управление персоналом 3.1 (ЗУП) разработчики часто сталкиваются со сложной задачей: необходимо программно создавать документы Прием на работу и автоматически заполнять их данными из штатного расписания. Основная трудность заключается в том, что в типовом решении интерактивное заполнение кадровых документов прочно привязано к событиям формы. При попытке вызвать процедуры заполнения из внешнего кода или фонового задания разработчик натыкается на функции, требующие передачи контекста формы в качестве параметра.
В этой статье мы подробно разберем, как обойти жесткую привязку к форме, какие механизмы программного интерфейса (API) предоставляет сама система ЗУП 3.1 для работы со штатным расписанием, и как правильно заполнить документ «Прием на работу» без рисков сломать логику при очередном обновлении конфигурации.
Разработчики типовых конфигураций 1С ориентируют большинство механизмов заполнения на интерактивную работу пользователя (оператора). Когда в форме документа Прием на работу выбирается позиция штатного расписания, на клиенте срабатывает обработчик изменения, который вызывает серверные общие модули. Эти модули напрямую читают данные элементов формы, модифицируют видимость колонок и рассчитывают показатели.
Если попытаться использовать эти функции напрямую в коде (например, при импорте данных из внешней CRM или ERP-системы), система выдаст ошибку отсутствия контекста формы. Чтобы решить эту проблему красиво и надежно, нам нужно обойти «клиентскую» обертку и обратиться напрямую к бизнес-логике конфигурации.
---
Вместо написания собственных тяжелых запросов к регистрам сведений штатного расписания, мы можем использовать стабильный программный интерфейс, который разработчики 1С заложили в систему. Для получения всех параметров позиции штатного расписания на определенную дату (включая начисления и графики работы) предназначен общий модуль УправлениеШтатнымРасписанием.
Основная функция, которая нам понадобится: УправлениеШтатнымРасписанием.ДанныеПозицииШтатногоРасписания().
Рассмотрим ее параметры подробнее:
ШтатноеРасписание.Истина, функция вернет таблицу плановых начислений и показателей, привязанных к этой позиции.Давайте проанализируем пример кода, который получает эти данные:
// Определяем параметры
ПозицияШР = Справочники.ШтатноеРасписание.НайтиПоРеквизиту("Код", "00000001");
ДатаПриема = ТекущаяДата();
// Получаем структуру данных позиции
ДанныеПозиции = УправлениеШтатнымРасписанием.ДанныеПозицииШтатногоРасписания(ПозицияШР, ДатаПриема, Истина);
Если ДанныеПозиции = Неопределено Тогда
ВызватьИсключение "Не удалось получить данные по выбранной позиции штатного расписания!"; КонецЕсли;
Возвращаемое значение представляет собой структуру (или таблицу значений в зависимости от релиза), содержащую готовые для подстановки в документ реквизиты: подразделение, должность, график работы, разряд или категорию, тарифную ставку, а также вложенную таблицу плановых начислений.
---
Просто перенести строки из структуры штатного расписания в документ Прием на работу недостаточно. Наиболее частая ошибка начинающих разработчиков в ЗУП 3.1 — это некорректное заполнение плановых начислений сотрудника. При ручном добавлении строк на форме они выглядят пустыми, хотя расчет ФОТ (фонда оплаты труда) при этом может отрабатывать.
Выясним причину этого поведения. В документе Прием на работу табличная часть Начисления и табличная часть Показатели жестко связаны между собой через служебный реквизит ИдентификаторСтрокиВидаРасчета.
При программном заполнении нам необходимо строго соблюдать следующий алгоритм:
Начисления, указав этот идентификатор.Показатели, указав тот же самый идентификатор связи.Разберем детальный пример программного создания документа и заполнения его табличных частей:
Функция СоздатьПриемНаРаботуПоШтатномуРасписанию(Сотрудник, ПозицияШР, ДатаПриема, Организация) Экспорт
// 1. Создаем новый документ
ДокОбъект = Документы.ПриемНаРаботу.СоздатьДокумент();
ДокОбъект.Дата = ТекущаяДата();
ДокОбъект.Организация = Организация;
ДокОбъект.Сотрудник = Сотрудник;
ДокОбъект.ФизическоеЛицо = Сотрудник.ФизическоеЛицо;
ДокОбъект.ДатаПриема = ДатаПриема;
// 2. Получаем данные позиции штатного расписания через API
ДанныеПозиции = УправлениеШтатнымРасписанием.ДанныеПозицииШтатногоРасписания(ПозицияШР, ДатаПриема, Истина);
Если ДанныеПозиции <> Неопределено Тогда
// Заполняем основные кадровые реквизиты
ДокОбъект.Подразделение = ДанныеПозиции.Подразделение;
ДокОбъект.Должность = ДанныеПозиции.Должность;
ДокОбъект.ДолжностьПоШтатномуРасписанию = ПозицияШР;
ДокОбъект.ГрафикРаботы = ДанныеПозиции.ГрафикРаботы;
ДокОбъект.КоличествоСтавок = 1; // Указываем количество ставок по умолчанию
КонецЕсли;
// Очищаем ТЧ перед заполнением
ДокОбъект.Начисления.Очистить();
ДокОбъект.Показатели.Очистить();
// Инициализируем счетчик связи табличных частей
ИндексСвязи = 1;
// 3. Заполняем плановые начисления и показатели
Если ДанныеПозиции.Свойство("Начисления") И ТипЗнч(ДанныеПозиции.Начисления) = Тип("ТаблицаЗначений") Тогда
Для Каждого СтрокаНачисленияИзШР Из ДанныеПозиции.Начисления Цикл
// Добавляем строку в ТЧ Начисления
НоваяСтрокаНачисления = ДокОбъект.Начисления.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрокаНачисления, СтрокаНачисленияИзШР);
НоваяСтрокаНачисления.ИдентификаторСтрокиВидаРасчета = ИндексСвязи;
// Ищем показатели, связанные с этим начислением в ШР
Если ДанныеПозиции.Свойство("Показатели") И ТипЗнч(ДанныеПозиции.Показатели) = Тип("ТаблицаЗначений") Тогда
// Фильтруем показатели по текущему начислению
Отбор = Новый Структура("ИдентификаторСтрокиВидаРасчета", СтрокаНачисленияИзШР.ИдентификаторСтрокиВидаРасчета);
НайденныеПоказатели = ДанныеПозиции.Показатели.НайтиСтроки(Отбор);
Для Каждого СтрокаПоказателяИзШР Из НайденныеПоказатели Цикл
// Добавляем строку в ТЧ Показатели документа
НоваяСтрокаПоказателя = ДокОбъект.Показатели.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрокаПоказателя, СтрокаПоказателяИзШР);
// Связываем строку показателя со строкой начисления
НоваяСтрокаПоказателя.ИдентификаторСтрокиВидаРасчета = ИндексСвязи;
КонецЦикла;
КонецЕсли;
// Увеличиваем индекс для следующего начисления
ИндексСвязи = ИндексСвязи + 1;
КонецЦикла;
КонецЕсли;
// Перед записью обязательно рассчитываем ФОТ по заполненным показателям
// Используем стандартный метод для пересчета ФОТ документа
КадровыйУчет.РассчитатьФОТДокумента(ДокОбъект);
// Записываем документ
Попытка
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
Возврат ДокОбъект.Ссылка;
Исключение
ЗаписьЖурналаРегистрации("ПрограммныйПриемНаРаботу", УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
Возврат Неопределено;
КонецПопытки;
КонецФункции
Использование метода КадровыйУчет.РассчитатьФОТДокумента() гарантирует, что фонд оплаты труда по документу будет рассчитан строго по правилам конфигурации, и у расчетчиков зарплаты не возникнет расхождений при последующем начислении.
---
При программном создании кадровых документов важно исключить человеческий фактор или логические ошибки переноса данных, когда сотрудника принимают на позицию, где физически нет свободных ставок. В интерфейсе программы за это отвечает предупреждение системы, но при фоновом создании документ может просто записаться или провестись вопреки лимитам (если в настройках программы не стоит жесткий запрет).
Для программной проверки свободных ставок мы можем использовать функцию:
УправлениеШтатнымРасписанием.ЗанятостьПозицийШтатногоРасписания(ПозицияШР, ДатаПриема)
Проанализируем пример функции проверки вакантных мест перед созданием приема:
Функция ЕстьСвободнаяСтавка(ПозицияШР, ДатаПриема) Экспорт
ТаблицаЗанятости = УправлениеШтатнымРасписанием.ЗанятостьПозицийШтатногоРасписания(ПозицияШР, ДатаПриема);
Если ТаблицаЗанятости.Количество() > 0 Тогда
ТекущаяСтрока = ТаблицаЗанятости[0];
// Вычисляем количество свободных ставок
СвободноСтавок = ТекущаяСтрока.КоличествоСтавок - ТекущаяСтрока.КоличествоЗанятыхСтавок;
Возврат (СвободноСтавок >= 1);
КонецЕсли;
Возврат Ложь;
КонецФункции
Такой превентивный контроль убережет базу данных от рассогласованности кадрового учета и штатного расписания.
---
Если ваша задача — предоставить пользователю удобную кнопку заполнения прямо в форме нового документа (но при этом вы не хотите модифицировать типовую конфигурацию и снимать ее с поддержки), используйте механизм дополнительных отчетов и обработок БСП.
При регистрации внешней обработки заполнения табличных частей укажите тип команды ЗаполнениеФормы вместо стандартного ВызовКлиентскогоМетода или ВызовСерверногоМетода.
Преимущества этого подхода:
Пример секции регистрации внешней обработки:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработкеКопированием();
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиЗаполнениеОбъекта();
ПараметрыРегистрации.Назначение.Добавить("Документ.ПриемНаРаботу");
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Заполнить по штатному расписанию (Умное заполнение)";
НоваяКоманда.Идентификатор = "ЗаполнитьПоШР";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыЗаполнениеФормы();
Возврат ПараметрыРегистрации;
КонецФункции
---
При создании механизмов автоматизации в 1С:ЗУП 3.1 важно следовать правилу минимального вмешательства в регистры напрямую. Всегда отдавайте предпочтение штатным программным методам конфигурации. Резюмируем основные шаги для красивого и надежного заполнения кадровых документов:
УправлениеШтатнымРасписанием.ДанныеПозицииШтатногоРасписания().Начисления и ТЧ Показатели через генерацию сквозного уникального значения ИдентификаторСтрокиВидаРасчета.КадровыйУчет.РассчитатьФОТДокумента() перед его записью.Соблюдение этих простых архитектурных принципов позволит вашему коду работать быстро, корректно и безболезненно переносить любые технологические обновления конфигурации со стороны фирмы "1С".