Как установить флажок в обработке «Состояние обеспечения заказа» при выставлении счета поставщиком в 1С:Управление торговлей 11

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

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

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

Шаг 1. Создание реквизита и настройка элемента формы (Поле флажка)

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

  1. Откроем форму обработки СостояниеОбеспеченияЗаказов в конфигураторе.
  2. В окне «Реквизиты» найдем дерево значений с именем Товары. Это основной реквизит формы, в котором выводятся заказы и их потребности.
  3. Добавим новый реквизит в структуру дерева Товары. Назовем его, например, СчетВыставленПоставщиком с типом данных Булево. По умолчанию значение будет установлено в Ложь.
  4. Перетащим созданный реквизит СчетВыставленПоставщиком в элементы формы — внутрь таблицы Товары.
  5. Выделим созданный элемент на форме и откроем его палитру свойств. Найдем свойство «Вид» и установим для него значение «Поле флажка». Это позволит отображать данные в виде интерактивной галочки вместо текстовых значений «Да/Нет».
  6. Поскольку это поле должно носить исключительно информационный характер, установим свойство «ТолькоПросмотр» в значение Истина. Это защитит данные от случайного изменения пользователем вручную.

Шаг 2. Анализ структуры данных формы

Разберем важную техническую особенность работы с коллекцией Товары на форме. Данный реквизит имеет тип ДанныеФормыДерево. Это иерархическая структура:

Поскольку наша задача — установить флажок напротив всего заказа в целом, нам необходимо работать со строками верхнего уровня. Для этого мы будем использовать метод ПолучитьЭлементы() главного реквизита.

Обратим внимание на то, как получить ссылку на документ. В отличие от стандартных табличных частей, где ссылка хранится в реквизите Ссылка, в этой обработке ссылка на документ-заказ хранится в реквизите с именем Заказ. Таким образом, правильное обращение к ссылке выглядит так:

СсылкаНаЗаказ = СтрокаЗаказа.Заказ;

Шаг 3. Разработка оптимизированного алгоритма заполнения

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

Мы применим классический оптимизированный паттерн:

  1. Выполним обход коллекции дерева и соберем все уникальные ссылки на заказы в массив.
  2. Одним запросом выберем из базы данных информацию о наличии выставленных счетов для этих заказов.
  3. Поместим результаты запроса во временную коллекцию Соответствие (Map) для мгновенного доступа по ключу-ссылке.
  4. Повторно обойдем строки дерева на форме и установим флажки, получая признак счета из соответствия за доли секунды.

Шаг 4. Написание программного кода

Внедрим нашу логику в процедуру обновления состояния на сервере. В модуле формы найдем процедуру ОбновитьСостояниеНаСервере(). Проанализируем ее код и найдем место, где данные уже подготовлены и выведены в дерево (обычно это происходит после вызова функций заполнения дат обеспечения и рекомендации). Именно там мы разместим наш алгоритм.

Ниже представлен готовый пример кода, который решает поставленную задачу:


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

// Шаг 4.2. Пакетный запрос к базе данных
СоответствиеЗаказовИСчетов = Новый Соответствие;

Если МассивЗаказов.Количество() > 0 Тогда
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗРЕШЕННЫЕ
        |	ЗаказПоставщику.ДокументОснование КАК ЗаказКлиента,
        |	ИСТИНА КАК СчетВыставлен
        |ИЗ
        |	Документ.ЗаказПоставщику КАК ЗаказПоставщику
        |ГДЕ
        |	ЗаказПоставщику.ДокументОснование В(&МассивЗаказов)
        |	И ЗаказПоставщику.НомерВходящегоДокумента <> """"
        |	И НЕ ЗаказПоставщику.ПометкаУдаления
        |
        |СГРУППИРОВАТЬ ПО
        |	ЗаказПоставщику.ДокументОснование";
        
    // Примечание: В качестве признака полученного счета мы анализируем 
    // заполненность реквизита "НомерВходящегоДокумента" в связанном Заказе поставщику.
    // Если в вашей базе используется отдельный документ "Счет на оплату поставщика",
    // запрос следует переписать к таблице этого документа.

    Запрос.УстановитьПараметр("МассивЗаказов", МассивЗаказов);
    
    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Пока Выборка.Следующий() Цикл
            СоответствиеЗаказовИСчетов.Вставить(Выборка.ЗаказКлиента, Выборка.СчетВыставлен);
        КонецЦикла;
    КонецЕсли;
КонецЕсли;

// Шаг 4.3. Заполнение нашей булевой колонки на форме
Для Каждого СтрокаВерхнегоУровня Из Товары.ПолучитьЭлементы() Цикл
    СсылкаНаЗаказ = СтрокаВерхнегоУровня.Заказ;
    
    // Проверяем наличие информации в соответствии
    ФлагСчета = СоответствиеЗаказовИСчетов[СсылкаНаЗаказ];
    Если ФлагСчета <> Неопределено Тогда
        СтрокаВерхнегоУровня.СчетВыставленПоставщиком = ФлагСчета;
    Иначе
        СтрокаВерхнегоУровня.СчетВыставленПоставщиком = Ложь;
    КонецЕсли;
КонецЦикла;

Дополнительные рекомендации по адаптации логики

Рассмотрим ситуации, когда связь между заказом покупателя и заказом поставщика осуществляется не напрямую через реквизит ДокументОснование, а по другим правилам складского учета:

Благодаря использованию механизма Соответствие и предварительного пакетного сбора данных, разработанное решение будет работать максимально быстро даже на базах данных с большим объемом ежедневных заказов.

← На главную