Как автоматически изменять данные или создавать документ «Установка цен номенклатуры» на основании «Приобретения товаров и услуг»?

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

В процессе работы с конфигурацией 1С:Управление торговлей 11 часто возникает необходимость автоматизировать регистрацию цен после оформления закупки. Типовой процесс подразумевает ручное создание документа УстановкаЦенНоменклатуры на основании ПриобретениеТоваровУслуг, что может быть неэффективно при больших объемах документов. В этой статье мы разберем, как автоматизировать этот процесс, решим проблему низкой производительности в файловых базах и выберем оптимальную архитектуру решения.

Проанализируем исходную ситуацию и проблемы кода

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

  1. Использование критериев отбора: Вызов метода КритерииОтбора.СвязанныеДокументы.Найти(Ссылка) в файловой базе данных работает крайне медленно (до 20 секунд), так как система сканирует множество таблиц для поиска связей.
  2. Клиентский контекст: Попытка управлять данными через форму (`ОткрытьФорму`) блокирует работу пользователя и не срабатывает при программном создании документов (например, через ЭДО или загрузку из Excel).
  3. Отсутствие контроля актуальности: Если документ проводится «задним числом», автоматическое создание новых цен может нарушить хронологию прайс-листа.

Решение 1: Использование типового функционала соглашений

Прежде чем приступать к написанию кода, выясним причину, по которой типовые механизмы могут не подходить. В УТ 11 предусмотрена настройка в справочнике СоглашенияСПоставщиками. Если установить флаг «Регистрировать цены поставщика автоматически», то при проведении документа ПриобретениеТоваровУслуг система сама сделает записи в регистр сведений ЦеныНоменклатурыПоставщиков.

Если же вашей целью является не просто фиксация цен поставщика, а изменение собственных продажных цен (прайс-листа предприятия), то перейдем к реализации программных механизмов.

Решение 2: Оптимизация поиска связанных документов через запрос

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


&НаСервере
Функция НайтиСвязаннуюУстановкуЦен(ДокументОснование)
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ ПЕРВЫЕ 1
        |    Т.Ссылка КАК Ссылка
        |ИЗ
        |    Документ.УстановкаЦенНоменклатуры КАК Т
        |ГДЕ
        |    Т.ДокументОснование = &Основание
        |    И НЕ Т.ПометкаУдаления";
    
    Запрос.УстановитьПараметр("Основание", ДокументОснование);
    Результат = Запрос.Выполнить();
    
    Если НЕ Результат.Пустой() Тогда
        Выборка = Результат.Выбрать();
        Выборка.Следующий();
        Возврат Выборка.Ссылка;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Такой запрос по индексированному полю ДокументОснование отработает мгновенно даже в крупной файловой базе, исключая задержки в 20 секунд.

Решение 3: Реализация через фоновые задания (наилучшая практика)

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

Рассмотрим алгоритм реализации:

  1. В модуле объекта документа ПриобретениеТоваровУслуг в процедуре ПриЗаписи или через расширение добавляем запись в специально созданный вспомогательный Регистр Сведений (например, ОчередьОбновленияЦен).
  2. Создаем Регламентное задание, которое раз в несколько минут анализирует этот регистр.
  3. Регламентное задание запускает процедуру, которая программно создает или обновляет УстановкаЦенНоменклатуры.

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


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

    // Заполнение табличной части на основании данных закупки
    // Используем типовой механизм заполнения, если он предусмотрен в конфигурации
    УстановкаОбъект.Заполнить(ОснованиеСсылка);
    
    Попытка
        УстановкаОбъект.Записать(РежимЗаписиДокумента.Проведение);
    Исключение
        ЗаписьЖурналаРегистрации("ОшибкаАвтоматическойУстановкиЦен", УровеньЖурналаРегистрации.Ошибка, , , КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
КонецПроцедуры

Решение 4: Использование расширений для чистоты кода

Чтобы не изменять типовую конфигурацию и упростить будущие обновления, крайне рекомендуется выносить эту логику в Расширение. Вместо правки модуля формы (как делал автор в исходном сообщении), используем перехват события в модуле объекта. Это гарантирует, что цены будут созданы, даже если документ закупки пришел через ЭДО или был создан обработкой ОбменДанными.

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


Если ОснованиеСсылка.Дата < НачалоДня(ТекущаяДата()) Тогда
    // Если документ старый, возможно, стоит только уведомить ответственного, 
    // но не менять цены автоматически
    Возврат; 
КонецЕсли;

Подведем итоги

Мы рассмотрели несколько подходов к автоматизации данных. Подведем краткий итог нашим действиям:

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

← На главную