Как вызвать функцию формы документа на сервере и организовать программный пересчет данных

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 на управляемых формах разработчики нередко сталкиваются с необходимостью повторить интерактивные действия пользователя из фоновых процессов, подписок на события или регламентных заданий. Типичный пример — необходимость пересчитать строки документа ТабельУчетаРабочегоВремени при проведении или записи сопутствующих документов (например, регистраций переработок или сверхурочных часов).

Попытка обратиться к форме через серверный код приводит к ошибкам платформы. Разберем, почему возникает такое поведение, почему нельзя обращаться к контексту формы на сервере и как правильно реализовать программное заполнение данных объекта.

Почему возникает ошибка при попытке получить форму на сервере

Проанализируем типовую ошибочную конструкцию, с которой часто начинают разработку:


// Ошибочный подход в серверном контексте
сс = Документы.ТабельУчетаРабочегоВремени.НайтиПоНомеру("0А00-000015", Источник.Дата);
об = сс.ПолучитьОбъект();
ЭтаФорма = об.ПолучитьФорму(); // Вызовет исключение на сервере

Выясним причину такого поведения платформы 1С:

  1. Клиент-серверное разделение: Метод ПолучитьФорму() предназначен для клиентского контекста или работы в режиме обычного приложения. На стороне сервера без активного сеанса взаимодействия с пользователем формы физически не существует. Сервер выполняет чистую бизнес-логику и транзакции базы данных.
  2. Разделение модулей: Общие модули с постфиксом Формы (например, УчетРабочегоВремениРасширенныйФормы) оперируют исключительно визуальными структурами. Они ожидают на вход параметры типа УправляемаяФорма, ДанныеФормыКоллекция, ДанныеФормыСтруктура и обращаются к элементам интерфейса (например, Форма.Элементы.ДанныеОВремени.ТекущаяСтрока). У объекта ДокументОбъект таких свойств нет.

Способ 1. Использование экспортных методов модуля менеджера и модуля объекта

Рассмотрим правильный подход. Вся логика расчета, получения данных из регистров и заполнения табличных частей в типовых конфигурациях (включая «1С:Зарплата и управление персоналом 3») вынесена в серверные модули — модули менеджеров, модули объектов и общие серверные модули учета времени.

Разберем по шагам, как организовать программный пересчет и обновление данных без обращения к интерфейсу:

  1. Получение ссылки и объекта: Находим нужный документ и получаем экземпляр ДокументОбъект через метод ПолучитьОбъект().
  2. Обращение к серверным алгоритмам: Используем методы модуля менеджера документа ТабельУчетаРабочегоВремени (например, ТаблицаДанныхДляЗаполнения) или функции серверного общего модуля УчетРабочегоВремениРасширенный.
  3. Обновление строк табличной части: Напрямую модифицируем строки коллекции ДанныеОВремени объекта.
  4. Запись объекта: Вызываем метод Записать() в необходимом режиме.

Посмотрим на пример серверного кода обновления строк документа:


// Серверный алгоритм пересчета табеля
ТабельОбъект = СсылкаНаТабель.ПолучитьОбъект();

Если ТабельОбъект <> Неопределено Тогда
    Для Каждого СтрСотрудник Из Источник.Сотрудники Цикл
        Отбор = Новый Структура("Сотрудник", СтрСотрудник.Сотрудник);
        НайденныеСтроки = ТабельОбъект.ДанныеОВремени.НайтиСтроки(Отбор);
        
        // Модифицируем показатели времени в табличной части объекта
        Для Каждого СтрокаТабеля Из НайденныеСтроки Цикл
            // Вызываем серверный расчет показателей по регистрам учета времени
            // и обновляем реквизиты строки (Часы, ВидВремени и т.д.)
        КонецЦикла;
    КонецЦикла;
    
    // Записываем документ
    ТабельОбъект.Записать(РежимЗаписиДокумента.Запись);
КонецЕсли;

Способ 2. Вынос универсального алгоритма из формы в модуль

Если логика заполнения была изначально написана разработчиком внутри модуля формы и отсутствует в модуле менеджера, её необходимо отрефакторить. Перенесем расчетные процедуры из модуля формы в модуль объекта или менеджер документа.

Проанализируем разницу в типах данных при адаптации кода:

  1. Вместо ДанныеФормыКоллекция работаем с обычной ТабличнаяЧасть объекта или ТаблицаЗначений.
  2. Вместо поиска по Идентификатор через интерфейсную коллекцию используем поиск по реквизитам через Найти() или НайтиСтроки() у табличной части объекта.
  3. Исключаем любые обращения к свойствам Элементы, ТекущаяСтрока и ЭтаФорма, передавая конкретную строку или ссылку в качестве явного параметра процедуры.

Посмотрим на пример процедуры, адаптированной для работы на сервере:


// В модуле менеджера или модуле объекта
Процедура ЗаполнитьДанныеПоСотрудникуСервер(ТабельОбъект, СотрудникСсылка) Экспорт
    
    Отбор = Новый Структура("Сотрудник", СотрудникСсылка);
    СтрокиВремени = ТабельОбъект.ДанныеОВремени.НайтиСтроки(Отбор);
    
    Для Каждого Строка Из СтрокиВремени Цикл
        // Серверный алгоритм заполнения реквизитов строки времени
    КонецЦикла;
    
КонецПроцедуры

Важные архитектурные нюансы при работе с подписками на события

Если пересчет вызывается из подписки на события ПриЗаписи или ОбработкаПроведения другого документа, важно учитывать следующие особенности платформы:

  1. Транзакционные блокировки: Изменение и перезапись стороннего документа внутри транзакции проведения текущего документа может приводить к взаимным блокировкам таблиц СУБД (Deadlock) при одновременной работе нескольких пользователей.
  2. Методология учета: В типовых конфигурациях зарплатного учета регистрация сверхурочных часов и отклонений выполняется независимыми документами, формирующими собственные движения. Документ «Табель» используется как итоговый фиксирующий документ. Вместо мгновенной перезаписи табелей внутри подписок рекомендуется использовать регламентные механизмы перерасчета или выполнять обновление данных при открытии самого табеля.
← На главную