При разработке в системе 1С:Предприятие 8 часто возникает задача программного создания и заполнения документов, минуя интерактивные действия пользователя. Одной из таких типовых ситуаций является программное заполнение табличных частей документа, например, табличной части "Оплата труда" в документе "Кадровый перевод", особенно когда этот процесс должен выполняться на стороне сервера. Рассмотрим подробно, почему привычные методы, используемые при работе с формой, оказываются недоступными на сервере, и как реализовать требуемую логику.
Прежде всего, давайте выясним причину, по которой мы не можем просто вызвать экспортные процедуры формы документа "Кадровый перевод", такие как ФормаСтрокиДокументаКадровыйПереводСписком, или использовать свойства ЭтаФорма и Объект формы на стороне сервера.
Отсутствие контекста формы: При программном создании документа на сервере, в отличие от интерактивного создания пользователем, нет вызова формы. Серверный модуль работает напрямую с объектами базы данных. Это означает, что для сервера не существует понятия "формы", "элементов формы" или "контекста формы". Соответственно, такие объекты, как ЭтаФорма (ссылка на текущую форму) или Объект (ссылка на данные формы), которые активно используются в клиентских и форменных процедурах для доступа к реквизитам и табличным частям, попросту недоступны.
Особенности клиент-серверного взаимодействия: Платформа 1С:Предприятие 8 использует клиент-серверную архитектуру. Клиент отвечает за пользовательский интерфейс, а сервер — за хранение и обработку данных. Формы и все, что с ними связано (элементы управления, интерактивные действия, события) — это область ответственности клиента. Серверные процедуры (помеченные как &НаСервере или &НаСервереБезКонтекста) имеют доступ только к данным информационной базы и параметрам, явно переданным с клиента, но не к объектам интерфейса.
Сложная логика форменных процедур: Как правило, форменные процедуры в типовых конфигурациях (особенно тех, что используют БСП – Библиотеку стандартных подсистем) могут содержать довольно "матрешечную" структуру вызовов. Они часто работают с реквизитами, которые присутствуют на форме, но могут отсутствовать непосредственно в объекте документа в базе данных (это могут быть вспомогательные реквизиты формы). Помимо этого, логика формы может включать в себя интерактивные запросы к пользователю, динамическое изменение видимости элементов и другие действия, которые невозможно воспроизвести на сервере.
Таким образом, попытка вызова форменных экспортных процедур или использования свойств формы на сервере приведет к ошибкам, связанным с отсутствием объекта или контекста.
Поскольку мы не можем использовать логику формы на сервере, нам необходимо организовать аналогичный алгоритм непосредственно в нашем серверном модуле. Это означает, что мы будем работать напрямую с объектом документа "Кадровый перевод", его реквизитами и табличными частями, имитируя логику, которую обычно выполняет форма.
Первым делом нам нужно получить ссылку на документ "Кадровый перевод" или создать новый его экземпляр. Если мы создаем новый документ, то используем метод СоздатьДокумент(). Если же нам нужно изменить уже существующий документ, то используем метод ПолучитьОбъект() по его ссылке.
// Пример создания нового документа "Кадровый перевод"
ДокументОбъект = Документы.КадровыйПеревод.СоздатьДокумент();
// Если требуется изменить существующий документ, можно получить его объект по ссылке:
// ДокументОбъект = Документы.КадровыйПеревод.ПолучитьОбъект(СсылкаНаСуществующийДокумент);
После получения объекта документа, заполняем его основные реквизиты, которые находятся в шапке (не в табличных частях). Это могут быть поля типа "Сотрудник", "Дата", "Организация", "Подразделение", "Должность", "Вид перевода" и так далее.
// Пример заполнения основных реквизитов шапки документа
ДокументОбъект.Дата = ТекущаяДата();
ДокументОбъект.Организация = СсылкаНаНашуОрганизацию;
ДокументОбъект.Сотрудник = СсылкаНаСотрудника;
ДокументОбъект.Подразделение = СсылкаНаНовоеПодразделение; // Например, при переводе
ДокументОбъект.Должность = СсылкаНаНовуюДолжность; // Например, при переводе
ДокументОбъект.ВидПеревода = Перечисления.ВидыКадровогоПеревода.ИзменениеДолжности; // В ЗУП могут быть свои перечисления
ДокументОбъект.ДатаНачала = ДатаНачалаНовыхУсловий;
ДокументОбъект.ДатаОкончания = ДатаОкончанияНовыхУсловий; // Если перевод временный
// ... другие реквизиты, необходимые для документа
Наиболее важная часть задачи — это заполнение данных, относящихся к оплате труда. Важно понимать, что "Оплата труда" — это страница (закладка) формы документа. В самом объекте документа ей соответствуют одна или несколько табличных частей. В типовых конфигурациях, таких как 1С:Зарплата и Управление Персоналом (ЗУП), это чаще всего табличные части Начисления и Показатели, а также могут быть Удержания.
Мы должны программно добавлять строки в эти табличные части и заполнять их реквизиты, исходя из нашей логики:
Табличная часть "Начисления": Здесь хранятся сведения о видах начислений (оклад, премия, надбавки) и их размерах.
// Пример заполнения табличной части "Начисления"
// Перед добавлением новых строк, если документ уже существует и требуется обновить,
// возможно, потребуется очистить существующие строки или изменить их
// ДокументОбъект.Начисления.Очистить();
НоваяСтрокаНачисления = ДокументОбъект.Начисления.Добавить();
НоваяСтрокаНачисления.ВидРасчета = ПланыВидовРасчета.Начисления.ОкладПоДням; // Пример вида расчета
НоваяСтрокаНачисления.Размер = 60000; // Размер оклада или другого начисления
НоваяСтрокаНачисления.ДействуетС = ДокументОбъект.ДатаНачала; // Дата, с которой действует начисление
НоваяСтрокаНачисления.ДействуетПо = ДокументОбъект.ДатаОкончания; // Если начисление временно
НоваяСтрокаНачисления.Сторно = Ложь; // По умолчанию не сторно
НоваяСтрокаНачисления.ГрафикРаботы = Справочники.ГрафикиРаботы.ОсновнойГрафик; // Если применимо
// ... другие реквизиты строки начисления, специфичные для вашей конфигурации
Табличная часть "Показатели": В ЗУП часто используются показатели, которые влияют на расчет зарплаты (например, количество ставок, процент надбавки). Эти показатели хранятся в отдельной табличной части.
// Пример заполнения табличной части "Показатели"
// ДокументОбъект.Показатели.Очистить(); // Если требуется обновить
НоваяСтрокаПоказатель = ДокументОбъект.Показатели.Добавить();
НоваяСтрокаПоказатель.Показатель = Справочники.ПоказателиРасчетаЗарплаты.КоличествоСтавок; // Пример показателя
НоваяСтрокаПоказатель.Значение = 1; // Значение показателя (например, 1 ставка)
НоваяСтрокаПоказатель.ДатаНачала = ДокументОбъект.ДатаНачала;
НоваяСтрокаПоказатель.ДатаОкончания = ДокументОбъект.ДатаОкончания;
// ... другие реквизиты строки показателя
Табличная часть "Удержания" (если применимо): В некоторых случаях могут потребоваться и удержания.
// Пример заполнения табличной части "Удержания"
// ДокументОбъект.Удержания.Очистить(); // Если требуется обновить
// НоваяСтрокаУдержание = ДокументОбъект.Удержания.Добавить();
// НоваяСтрокаУдержание.ВидРасчета = ПланыВидовРасчета.Удержания.ПрофсоюзныеВзносы;
// НоваяСтрокаУдержание.Размер = 0.01; // 1%
// ...
Если интерактивное заполнение формы вызывало сложную логику (например, расчеты, подбор данных из справочников или регистров сведений, проверки), эту логику необходимо полностью воспроизвести в вашем серверном модуле. Это может включать:
Получение актуальных данных: Используйте запросы к информационной базе для получения текущих окладов, графиков работы, категорий должностей и других сведений, необходимых для заполнения табличных частей. Это наиболее эффективный способ работы с данными на сервере.
// Пример использования запроса для получения данных о текущем окладе сотрудника
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДанныеКадровогоУчетаСрезПоследних.ВидРасчета,
| ДанныеКадровогоУчетаСрезПоследних.Размер
|ИЗ
| РегистрСведений.ДанныеКадровогоУчетаСотрудников.СрезПоследних(
| &Дата,
| Сотрудник = &Сотрудник
| ) КАК ДанныеКадровогоУчетаСрезПоследних
|ГДЕ
| ДанныеКадровогоУчетаСрезПоследних.ВидРасчета В (&ВидыРасчетаДляОплатыТруда)";
Запрос.УстановитьПараметр("Дата", ДокументОбъект.Дата);
Запрос.УстановитьПараметр("Сотрудник", ДокументОбъект.Сотрудник);
Запрос.УстановитьПараметр("ВидыРасчетаДляОплатыТруда",
Новый Массив(ПланыВидовРасчета.Начисления.ОкладПоДням, ПланыВидовРасчета.Начисления.НадбавкаЗаСтаж)); // Пример
РезультатЗапроса = Запрос.Выполнить().Выбрать();
Пока РезультатЗапроса.Следующий() Цикл
НоваяСтрокаНачисления = ДокументОбъект.Начисления.Добавить();
НоваяСтрокаНачисления.ВидРасчета = РезультатЗапроса.ВидРасчета;
НоваяСтрокаНачисления.Размер = РезультатЗапроса.Размер;
НоваяСтрокаНачисления.ДействуетС = ДокументОбъект.ДатаНачала;
// ... и другие реквизиты
КонецЦикла;
Расчеты и валидация: Если форма выполняла какие-либо расчеты (например, процентные надбавки, зависимости от стажа) или валидацию вводимых данных, эти расчеты и проверки должны быть реализованы в вашем серверном коде.
Заполнение по умолчанию: Если некоторые поля заполняются по умолчанию из справочников или настроек, используйте соответствующие справочники и регистры сведений для получения этих значений.
После того как все необходимые реквизиты шапки и табличные части заполнены, документ необходимо записать. Если документ должен быть проведен (то есть создать движения по регистрам), используйте режим записи РежимЗаписиДокумента.Проведение. В противном случае — РежимЗаписиДокумента.Запись.
Попытка
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение); // Запись и проведение документа
// или ДокументОбъект.Записать(РежимЗаписиДокумента.Запись); // Просто запись без проведения
Сообщить("Документ 'Кадровый перевод' успешно создан и " + ?(ДокументОбъект.Проведен, "проведен", "записан") + ".");
Исключение Э
Сообщить("Ошибка при записи/проведении документа: " + Э.Описание);
Возврат Неопределено;
КонецПопытки;
Возврат ДокументОбъект.Ссылка; // Возвращаем ссылку на созданный/измененный документ
При реализации серверной логики важно помнить о различиях между контекстными (&НаСервере) и внеконтекстными (&НаСервереБезКонтекста) вызовами. Если для заполнения табличной части не требуется передавать весь контекст формы (что является нашим случаем, так как форма не открыта), то использование внеконтекстных вызовов может значительно повысить производительность. При &НаСервереБезКонтекста на сервер передаются только явно указанные параметры, а не все данные формы, что уменьшает объем сетевого трафика и нагрузку на сервер.
В конфигурациях 1С:Зарплата и Управление Персоналом (ЗУП) документ "Кадровый перевод" является центральным для изменения условий труда сотрудника. Вкладка "Оплата труда" на его форме агрегирует данные из нескольких табличных частей объекта: Начисления, Удержания и Показатели. При программном заполнении необходимо уделять особое внимание корректному заполнению всех необходимых реквизитов в этих табличных частях, учитывая специфику видов расчетов, их назначение и параметры использования в системе ЗУП. Это включает в себя не только размеры, но и даты действия, графики работы, показатели, влияющие на расчет, и другие параметры, которые определяют логику расчета зарплаты.
Программное заполнение табличной части "Оплата труда" документа "Кадровый перевод" на сервере требует глубокого понимания структуры объекта документа и логики его обработки. Мы не можем напрямую использовать форменные процедуры из-за отсутствия контекста формы на сервере. Вместо этого, нам необходимо самостоятельно воспроизвести всю необходимую логику, работая напрямую с реквизитами и табличными частями объекта документа, используя запросы для получения данных и обеспечивая корректное заполнение всех полей перед записью и проведением документа.