Как получить остаток материала из регистра накопления при выборе в документе 1С

Программист 1С v8.3 (Обычные формы) Управленческий учет
← На главную

При разработке документов списания или реализации материалов часто возникает необходимость показывать пользователю текущий остаток позиций на складе прямо в момент заполнения табличной части. Разберем, как правильно извлечь данные из регистра накопления и отобразить их в документе, а также проанализируем ошибки, которые допускают начинающие разработчики.

Типичные ошибки при запросе остатков

Рассмотрим распространенный подход: получение остатка при изменении колонки с материалом с помощью запроса. В исходном варианте кода обработчик события ПриИзменении может выглядеть следующим образом:


Процедура МатериалНаименованиеПриИзменении(Элемент)
    СтрокаТабличнойЧасти = ЭлементыФормы.Материал.ТекущиеДанные;
    
    Запрос = Новый Запрос;
    Запрос.Текст = "ВЫБРАТЬ
                   |    МатериалыОстаткиИОбороты.Наименование,
                   |    МатериалыОстаткиИОбороты.КоличествоКонечныйОстаток
                   |ИЗ
                   |    РегистрНакопления.Материалы.ОстаткиИОбороты КАК МатериалыОстаткиИОбороты";
    
    ВыборкаРезультатаЗапроса = Запрос.Выполнить().Выбрать();
    Пока ВыборкаРезультатаЗапроса.Следующий() Цикл    
        // Обработка выборки
    КонецЦикла;
КонецПроцедуры

В приведенном коде содержится сразу несколько существенных проблем, которые приводят к неверным данным и низкой производительности системы:

  1. Использование неверной виртуальной таблицы: Виртуальная таблица ОстаткиИОбороты предназначена для получения оборотов за период. Для расчета текущих остатков следует обращаться к таблице Остатки.
  2. Отсутствие параметров отбора: Запрос выбирает данные по всем материалам сразу без фильтрации по конкретной номенклатуре и складу. В результате выборка считывает всю таблицу остатков из базы данных.
  3. Использование цикла: Если передать отбор по конкретному материалу прямо в параметры виртуальной таблицы, запрос вернет ровно одну строку, и обходить результат циклом не потребуется.

Корректировка запроса к регистру остатков

Исправим запрос и сделаем выборку точечной. В параметры виртуальной таблицы Остатки передадим условия отбора по номенклатуре, а результат сразу запишем в реквизит текущей строки табличной части.

Разберем правильную реализацию процедуры на стороне формы:


Процедура МатериалНаименованиеПриИзменении(Элемент)
    СтрокаТабличнойЧасти = ЭлементыФормы.Материал.ТекущиеДанные;
    Если Не ЗначениеЗаполнено(СтрокаТабличнойЧасти.Номенклатура) Тогда
        Возврат;
    КонецЕсли;

    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    МатериалыОстатки.КоличествоОстаток КАК КоличествоОстаток
        |ИЗ
        |    РегистрНакопления.Материалы.Остатки(&Период, Номенклатура = &Номенклатура) КАК МатериалыОстатки";

    Запрос.УстановитьПараметр("Период", Дата);
    Запрос.УстановитьПараметр("Номенклатура", СтрокаТабличнойЧасти.Номенклатура);

    РезультатЗапроса = Запрос.Выполнить();
    Если Не РезультатЗапроса.Пустой() Тогда
        Выборка = РезультатЗапроса.Выбрать();
        Выборка.Следующий();
        СтрокаТабличнойЧасти.КоличествоНаСкладе = Выборка.КоличествоОстаток;
    Иначе
        СтрокаТабличнойЧасти.КоличествоНаСкладе = 0;
    КонецЕсли;
КонецПроцедуры

В этом примере мы задействовали параметризацию виртуальной таблицы РегистрНакопления.Материалы.Остатки. Благодаря этому СУБД считывает минимально необходимый объем данных, а заполнение колонки КоличествоНаСкладе происходит мгновенно.

Архитектурные рекомендации по хранению остатков

Проанализируем вопрос проектирования данных. Хранить ли значение остатка в табличной части самого документа в базе данных?

Важно: Записывать остаток склада в физическую таблицу документа не рекомендуется. Остаток — это динамический показатель, который меняется с каждым проведенным документом. Если сохранить числовое значение остатка в базе данных, оно устареет при изменении данных задним числом или при оформлении параллельных документов другими пользователями.

Рекомендуется использовать один из двух архитектурных подходов:

  1. Реквизит формы (не связанный с объектом): Колонка остатка добавляется только на форму документа и вычисляется динамически при открытии или при изменении строки. В самом объекте ДокументОбъект данная колонка не сохраняется.
  2. Форма подбора товаров: Для удобного выбора номенклатуры создается отдельная форма подбора. На ней размещается список номенклатуры с актуальными остатками, где пользователь видит всю информацию до перетаскивания строк в документ.
← На главную