Почему в 1С:УТ 11 реальная форма списка документов отличается от конфигуратора и откуда берутся проценты оплаты?

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

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

Ярким примером этой архитектурной особенности является список документов Заказ поставщику. В конфигураторе основной формой списка назначена обычная ФормаСписка. Однако при запуске системы открывается сложная, многофункциональная ФормаСпискаДокументов с цветными индикаторами, текущими состояниями («Готов к поступлению», «Ожидается оплата») и загадочными расчетными колонками: % оплаты, % поступления и % долга. Давайте подробно разберем, как устроен этот механизм изнутри, почему происходит подмена форм и каким образом формируются эти расчетные данные.

1. Механизм переключения управляемых форм: событие «ОбработкаПолученияФормы»

Выясним причину, по которой платформа игнорирует форму списка, указанную в качестве основной в свойствах метаданных документа, и открывает другую. В платформе 1С:Предприятие 8.3 реализован мощный механизм динамического перенаправления вызовов форм. За это отвечает предопределенный обработчик событий, расположенный в модуле менеджера конкретного объекта.

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

В типовых конфигурациях этот обработчик выглядит следующим образом:


Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
    
    // Проверяем, запрашивается ли форма списка
    Если ВидФормы = "ФормаСписка" Тогда
        
        // Отменяем стандартное открытие формы, назначенной в конфигураторе
        СтандартнаяОбработка = Ложь;
        
        // Перенаправляем платформу на открытие специализированной общей формы списка
        ВыбраннаяФорма = "Документ.ЗаказПоставщику.Форма.ФормаСпискаДокументов";
        
    КонецЕсли;

КонецПроцедуры

Установка свойства СтандартнаяОбработка = Ложь дает платформе команду проигнорировать стандартные настройки метаданных. В переменную ВыбраннаяФорма записывается строковое имя альтернативной формы, которую и получит пользователь. Именно поэтому стандартная ФормаСписка остается неиспользованной, а на экране появляется ФормаСпискаДокументов.

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


ПараметрыФормы = Новый Структура;
ОткрытьФорму("Документ.ЗаказПоставщику.Форма.ФормаСпискаДокументов", ПараметрыФормы);

2. Откуда берутся колонки «% оплаты», «% поступления» и «% долга»?

Если мы детально изучим структуру реквизитов документа ЗаказПоставщику в дереве метаданных, мы не найдем там полей для хранения процентов оплаты, отгрузки или сумм задолженностей. Хранить такие оперативно меняющиеся расчетные данные непосредственно в табличной части или реквизитах шапки документа было бы грубой ошибкой проектирования: при каждом платеже или поступлении товара пришлось бы перезаписывать и перепроводить сам документ заказа.

Вместо этого разработчики фирмы «1С» применили классический паттерн проектирования с использованием регистров сведений. Рассмотрим подробнее эту схему:

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

Давайте посмотрим на пример упрощенного текста запроса динамического списка, который собирает эти данные воедино:


ВЫБРАТЬ
    ДокументЗаказ.Ссылка КАК Ссылка,
    ДокументЗаказ.Номер КАК Номер,
    ДокументЗаказ.Дата КАК Дата,
    ДокументЗаказ.Партнер КАК Партнер,
    ДокументЗаказ.СуммаДокумента КАК СуммаДокумента,
    
    // Соединяем расчетные данные из регистра сведений
    ЕСТЬNULL(СостоянияЗаказов.Состояние, ЗНАЧЕНИЕ(Перечисление.СостоянияЗаказовПоставщикам.ПустаяСсылка)) КАК Состояние,
    ЕСТЬNULL(СостоянияЗаказов.ПроцентОплаты, 0) КАК ПроцентОплаты,
    ЕСТЬNULL(СостоянияЗаказов.ПроцентПоступления, 0) КАК ПроцентПоступления,
    ЕСТЬNULL(СостоянияЗаказов.СуммаДолга, 0) КАК СуммаДолга
ИЗ
    Документ.ЗаказПоставщику КАК ДокументЗаказ
    
    // Реализуем левое соединение для получения информации о состоянии заказа
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СостоянияЗаказовПоставщикам КАК СостоянияЗаказов
        ПО ДокументЗаказ.Ссылка = СостоянияЗаказов.Заказ

Благодаря использованию конструкции ЛЕВОЕ СОЕДИНЕНИЕ, платформа на лету сопоставляет каждую строку списка документов с соответствующей записью из регистра сведений. Это обеспечивает мгновенный вывод актуальных расчетных показателей без снижения производительности СУБД.

3. Особенности визуализации и логика работы в Конфигураторе

Даже открыв правильную форму ФормаСпискаДокументов в конфигураторе, вы можете удивиться тому, что визуально она выглядит блекло и не содержит многих элементов, которые видны в режиме «1С:Предприятие». Разберем причины этого явления:

4. Как правильно доработать такую форму списка

Попытка добавить новые колонки стандартным пользовательским путем через меню «Еще — Изменить форму» не принесет результата, если нужного реквизита нет в выборке динамического запроса списка. Чтобы доработать этот список под индивидуальные требования бизнеса (например, вывести телефон менеджера или дополнительный реквизит контрагента), необходимо использовать механизм Расширений конфигурации.

Разберем этот процесс по шагам:

Шаг 1. Создаем новое расширение конфигурации в дереве метаданных и снимаем с него признаки «Безопасный режим» и «Защита от опасных действий» (если требуется полноценное выполнение серверного кода).

Шаг 2. Находим документ ЗаказПоставщику, нажимаем по нему правой кнопкой мыши и выбираем команду «Добавить в расширение». Затем аналогичным образом добавляем в расширение форму ФормаСпискаДокументов.

Шаг 3. Переходим в модуль добавленной формы в расширении и создаем перехватчик события ПриСозданииНаСервере с аннотацией &После:


&После("ПриСозданииНаСервере")
Процедура Расш_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // 1. Получаем исходный текст запроса динамического списка
    ТекстЗапросаСписок = Список.ТекстЗапроса;
    
    // 2. Модифицируем текст запроса, добавляя левое соединение или новое поле.
    // Например, выведем телефон основного менеджера заказа.
    НовоеПоле = "ДокументЗаказ.Менеджер.Телефон КАК ТелефонМенеджера,";
    
    // Внедряем наше поле в выборку запроса после ключевого слова ВЫБРАТЬ
    ТекстЗапросаСписок = СтрЗаменить(ТекстЗапросаСписок, "ВЫБРАТЬ", "ВЫБРАТЬ " + НовоеПоле);
    
    // Записываем измененный запрос обратно в динамический список
    Список.ТекстЗапроса = ТекстЗапросаСписок;
    
    // 3. Программно создаем элемент формы для вывода новой колонки на экран
    ИмяЭлемента = "СписокТелефонМенеджера";
    Если Элементы.Найти(ИмяЭлемента) = Неопределено Тогда
        
        // Создаем новое поле формы в таблице списка
        НоваяКолонка = Элементы.Добавить(ИмяЭлемента, Тип("ПолеФормы"), Элементы.Список);
        НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
        НоваяКолонка.ПутьКДанным = "Список.ТелефонМенеджера";
        НоваяКолонка.Заголовок = "Телефон менеджера";
        НоваяКолонка.ТолькоПросмотр = Истина;
        
    КонецЕсли;

КонецПроцедуры

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

← На главную