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