В процессе работы с конфигурацией 1С:Управление торговлей 11 часто возникает необходимость автоматизировать регистрацию цен после оформления закупки. Типовой процесс подразумевает ручное создание документа УстановкаЦенНоменклатуры на основании ПриобретениеТоваровУслуг, что может быть неэффективно при больших объемах документов. В этой статье мы разберем, как автоматизировать этот процесс, решим проблему низкой производительности в файловых базах и выберем оптимальную архитектуру решения.
Рассмотрим код, который часто используют начинающие разработчики. Основная идея заключается в перехвате события записи формы документа закупки и открытии формы установки цен. Однако такой подход имеет ряд критических недостатков:
КритерииОтбора.СвязанныеДокументы.Найти(Ссылка) в файловой базе данных работает крайне медленно (до 20 секунд), так как система сканирует множество таблиц для поиска связей.Прежде чем приступать к написанию кода, выясним причину, по которой типовые механизмы могут не подходить. В УТ 11 предусмотрена настройка в справочнике СоглашенияСПоставщиками. Если установить флаг «Регистрировать цены поставщика автоматически», то при проведении документа ПриобретениеТоваровУслуг система сама сделает записи в регистр сведений ЦеныНоменклатурыПоставщиков.
Если же вашей целью является не просто фиксация цен поставщика, а изменение собственных продажных цен (прайс-листа предприятия), то перейдем к реализации программных механизмов.
Разберем, как ускорить поиск существующего документа установки цен. Вместо медленных критериев отбора применим прямой запрос к базе данных. В 1С документы установки цен хранят ссылку на основание. Посмотрим на пример оптимизированной функции:
&НаСервере
Функция НайтиСвязаннуюУстановкуЦен(ДокументОснование)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Т.Ссылка КАК Ссылка
|ИЗ
| Документ.УстановкаЦенНоменклатуры КАК Т
|ГДЕ
| Т.ДокументОснование = &Основание
| И НЕ Т.ПометкаУдаления";
Запрос.УстановитьПараметр("Основание", ДокументОснование);
Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Ссылка;
КонецЕсли;
Возврат Неопределено;
КонецФункции
Такой запрос по индексированному полю ДокументОснование отработает мгновенно даже в крупной файловой базе, исключая задержки в 20 секунд.
Для того чтобы пользователь не ждал окончания процесса формирования цен, применим механизм фоновых заданий. Выясним причину, почему это важно: проведение первичного документа должно быть максимально быстрым. Вся «тяжелая» логика по расчету цен и созданию связанных объектов должна уходить в «тихий» режим.
Рассмотрим алгоритм реализации:
ПриобретениеТоваровУслуг в процедуре ПриЗаписи или через расширение добавляем запись в специально созданный вспомогательный Регистр Сведений (например, ОчередьОбновленияЦен).УстановкаЦенНоменклатуры.Посмотрим на пример кода для программного создания документа:
Процедура СоздатьОбновитьУстановкуЦен(ОснованиеСсылка)
// Поиск существующего документа
УстановкаСсылка = НайтиСвязаннуюУстановкуЦен(ОснованиеСсылка);
Если ЗначениеЗаполнено(УстановкаСсылка) Тогда
УстановкаОбъект = УстановкаСсылка.ПолучитьОбъект();
Иначе
УстановкаОбъект = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
УстановкаОбъект.Дата = ТекущаяДата();
УстановкаОбъект.ДокументОснование = ОснованиеСсылка;
// Заполнение других обязательных реквизитов
КонецЕсли;
// Заполнение табличной части на основании данных закупки
// Используем типовой механизм заполнения, если он предусмотрен в конфигурации
УстановкаОбъект.Заполнить(ОснованиеСсылка);
Попытка
УстановкаОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
ЗаписьЖурналаРегистрации("ОшибкаАвтоматическойУстановкиЦен", УровеньЖурналаРегистрации.Ошибка, , , КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
КонецПроцедуры
Чтобы не изменять типовую конфигурацию и упростить будущие обновления, крайне рекомендуется выносить эту логику в Расширение. Вместо правки модуля формы (как делал автор в исходном сообщении), используем перехват события в модуле объекта. Это гарантирует, что цены будут созданы, даже если документ закупки пришел через ЭДО или был создан обработкой ОбменДанными.
Проанализируем ситуацию с изменением цен «задним числом». Если пользователь решит исправить цену в документе месячной давности, ваше фоновое задание может создать новую установку цен текущей датой, что приведет к актуализации старой цены в сегодняшнем дне. Чтобы избежать этой логической ловушки, добавим проверку:
Если ОснованиеСсылка.Дата < НачалоДня(ТекущаяДата()) Тогда
// Если документ старый, возможно, стоит только уведомить ответственного,
// но не менять цены автоматически
Возврат;
КонецЕсли;
Мы рассмотрели несколько подходов к автоматизации данных. Подведем краткий итог нашим действиям:
КритерииОтбора в пользу прямых запросов.Использование этих методов позволит сделать работу системы стабильной, а интерфейс — отзывчивым даже в условиях файловой базы данных.