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