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