Как программно создать и корректно отобразить документ Установка цен номенклатуры в УТ 11.4 без записи

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

При разработке в среде 1С:Управление торговлей 11.4 (а также в ERP 2 и КА 2) программисты часто сталкиваются с задачей программного формирования документа Установка цен номенклатуры. Особенность этой задачи заключается в требовании открыть форму нового документа с уже заполненными данными, но при этом не записывать сам документ в базу данных, чтобы пользователь мог проверить данные и нажать кнопку «Провести» самостоятельно.

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

В чем причина «пустой» формы

Проанализируем архитектуру формы документа УстановкаЦенНоменклатуры. В отличие от простых документов, здесь на форме отображаются не напрямую данные табличных частей объекта, а специальный реквизит формы — ДеревоЦен (тип ДанныеФормыДерево). Это дерево строится динамически при открытии формы или при изменении состава видов цен.

За построение этого дерева отвечает сложная логика в общем модуле УстановкаЦенСервер. Основная сложность заключается в том, что большинство процедур этого модуля требуют передачи контекста формы (параметр ЭтаФорма). Когда мы просто открываем форму программно, это дерево не заполняется автоматически на основании данных объекта, если не были задействованы штатные механизмы инициализации формы.

Шаг 1. Программное заполнение данных объекта

Прежде всего, нам необходимо создать объект документа и заполнить его основные реквизиты и табличные части. Обратите внимание на важный флаг ЦенаИзмененаВручную — без него система может пересчитать ваши цены в ноль при открытии, если они зависят от других цен.

Рассмотрим пример кода для серверной части обработки:


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

Шаг 2. Передача данных в форму и ее инициализация

Теперь перейдем к самому интересному — как заставить форму «увидеть» эти данные и построить дерево цен. Выясним причину, по которой обычный вызов Открыть() не помогает. Форме нужно дать команду на пересчет и заполнение внутренних реквизитов.

Экспериментальным путем было найдено решение: использование процедуры ЗаполнитьДокумент(), которая находится в модуле формы документа. Несмотря на то, что она может быть не объявлена как Экспортная, в определенных версиях платформы и режимах совместимости ее можно вызвать с клиента после открытия формы.

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


&НаКлиенте
Процедура СоздатьИОткрытьДокумент()
    
    // 1. Получаем форму нового документа
    лФорма = ПолучитьФорму("Документ.УстановкаЦенНоменклатуры.ФормаОбъекта");
    лДанныеФормы = лФорма.Объект;
    
    // 2. Заполняем объект данными на сервере
    ЗаполнитьДанныеДокументаНаСервере(лДанныеФормы);
    
    // 3. Устанавливаем флаги в форме, чтобы она поняла, что состав цен изменился
    лФорма.ВыбранныеЦеныИзменены = Истина;
    
    // 4. Отмечаем в служебной таблице формы, какие цены выбраны
    Для Каждого СтрокаВидЦены Из лДанныеФормы.ВидыЦен Цикл
        Отбор = Новый Структура("Ссылка", СтрокаВидЦены.ВидЦены);
        НайденныеСтроки = лФорма.ВыбранныеЦены.НайтиСтроки(Отбор);
        Для Каждого Стр Из НайденныеСтроки Цикл
            Стр.Выбрана = Истина;
        КонецЦикла;
    КонецЦикла;
    
    // 5. Копируем данные обратно в форму
    КопироватьДанныеФормы(лДанныеФормы, лФорма.Объект);
    
    // 6. Открываем форму
    лФорма.Открыть();
    
    // 7. Магия: вызываем серверный метод формы для принудительного построения дерева
    // Внимание: метод может быть не экспортным, но доступным для вызова!
    лФорма.ЗаполнитьДокумент();
    
КонецПроцедуры

Шаг 3. Анализ «хака» с вызовом неэкспортного метода

Проанализируем ситуацию: почему работает вызов лФорма.ЗаполнитьДокумент(), если в модуле формы отсутствует ключевое слово Экспорт?

Как показывают исследования разработчиков, это особенность (или баг) платформы 1С:Предприятие 8.3. В режимах совместимости до 8.3.12 включительно серверные процедуры модуля формы с директивами &НаСервере или &НаСервереБезКонтекста доступны для вызова извне, если у вас есть ссылка на открытую (или инициализированную) форму.

Важное предупреждение: начиная с режима совместимости 8.3.13, компания 1С ужесточила правила безопасности. В новых версиях такой вызов может привести к ошибке «Метод объекта не обнаружен». Если ваша конфигурация работает в режиме совместимости 8.3.13 и выше, вам придется использовать механизм Расширений.

Альтернативное решение через расширение

Если прямой вызов метода формы недоступен, мы рекомендуем воспользоваться расширением конфигурации:

  1. Добавьте документ УстановкаЦенНоменклатуры в расширение.
  2. В модуле формы документа найдите процедуру ЗаполнитьДокумент.
  3. Измените ее заголовок, добавив ключевое слово Экспорт, либо создайте свою экспортную процедуру-обертку.

Пример обертки в расширении:


&НаСервере
Процедура Расш1_ЗаполнитьДокументЭкспорт() Экспорт
    // Вызываем оригинальную процедуру модуля формы
    ЗаполнитьДокумент();
КонецПроцедуры

Дополнительные нюансы: НаборыЗначенийДоступа

Некоторые специалисты советуют также заполнять таблицу НаборыЗначенийДоступа. Проанализируем этот момент. Данная таблица отвечает за права доступа (RLS) на уровне записей. Для незаписанного документа ее заполнение не является обязательным для визуального отображения данных. Система автоматически сформирует эти записи при записи документа в базу. Таким образом, для решения задачи «просто показать данные пользователю» этот шаг можно пропустить.

Резюме

Для успешного программного открытия формы установки цен без записи необходимо:

  1. Заполнить объект через ДанныеФормы.
  2. Обязательно проставить ЦенаИзмененаВручную = Истина в строках ТЧ.
  3. Проставить признак Выбрана = Истина в коллекции формы ВыбранныеЦены.
  4. После открытия формы принудительно вызвать метод ЗаполнитьДокумент() для перерисовки дерева цен.

Используя этот подход, вы обеспечите корректную работу интерактивных механизмов типовой конфигурации и избавите пользователей от необходимости ручного ввода данных.

← На главную