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