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

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

При разработке и сопровождении учетных систем на платформе 1С разработчики нередко сталкиваются с ситуацией, когда в табличной части документа присутствуют две или более строки с одинаковой номенклатурой и одинаковыми характеристиками. Типичный пример: в заказе покупателя одна и та же позиция заведена двумя строками, так как выпуск продукции на производстве запланирован на разные даты. При проведении документа в регистр накопления остатков записываются две отдельные записи. Однако при попытке прочитать данные через виртуальную таблицу Остатки запрос возвращает одну свёрнутую запись с общей суммой и количеством.

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

Почему виртуальная таблица остатков всегда группирует данные

Для понимания происходящего проанализируем внутреннее устройство регистров накопления с видом «Остатки» в платформе 1С:Предприятие:

  1. Физическая таблица итогов: На уровне СУБД для регистра остатков создается специальная таблица итогов. В ней хранятся рассчитанные агрегированные остатки в разрезе только заданных измерений регистра. Таблица итогов принципиально не содержит информации о номерах строк, регистраторах или периодах движений.
  2. Схлопывание по набору измерений: Первичный ключ таблицы итогов формируется исключительно из измерений регистра. Если две строки документа имеют одинаковые значения всех измерений (например, Номенклатура, ХарактеристикаНоменклатуры, ЗаказПокупателя), для платформы это одна и та же итоговая точка остатка.
  3. Ограничения виртуальной таблицы: Виртуальная таблица Остатки предназначена для быстрого извлечения мгновенного среза данных именно из таблицы итогов. Поэтому получить из неё остаток с детализацией до исходной строки движения технически невозможно.

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

Способ 1. Использование дополнительной аналитики: серии номенклатуры

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

Разберем по шагам, как это работает:

  1. Включаем учет по сериям для соответствующего вида номенклатуры, если он был выключен.
  2. Поскольку разные строки отражают разные партии выпуска продукции, каждой строке сопоставляется своя серия (или плановая дата выпуска в свойствах серии).
  3. Так как измерение СерияНоменклатуры входит в состав измерений регистра остатков, комбинация измерений для двух строк становится различной.
  4. При обращении к виртуальной таблице Остатки запрос возвращает две независимые строки, каждая со своим количеством и остатком.

Способ 2. Добавление технического измерения «Ключ строки»

Если серии использовать нецелесообразно или методология предприятия не предполагает серийного учета, рассмотрим современный платформенный паттерн, применяемый в типовых конфигурациях линейки ERP и УТ 11: внедрение уникального ключа строки.

Для реализации этого подхода выполним следующие действия:

  1. В табличную часть документа добавляем реквизит КлючСтроки (тип Число). При заполнении документа ему присваивается уникальный номер (например, номер строки).
  2. В регистр накопления добавляем измерение КлючСтроки с аналогичным типом.
  3. При проведении документа переносим значение ключа из табличной части в движения регистра.

В результате комбинация «Номенклатура + Характеристика + Заказ + КлючСтроки» становится уникальной для каждой позиции табличной части, и виртуальная таблица Остатки перестает сворачивать строки:


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

Способ 3. Программное распределение общего остатка по строкам документа

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

Рассмотрим пример запроса с вычислением накопительного итога:


ВЫБРАТЬ
    ТЧ.НомерСтроки КАК НомерСтроки,
    ТЧ.Номенклатура КАК Номенклатура,
    ТЧ.Количество КАК КоличествоПлан,
    СУММА(ТЧ_Предыдущие.Количество) КАК НакопленныйИтогПлан,
    ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК ВсегоОстаток
ПОМЕСТИТЬ ВТ_СтрокиСИтогами
ИЗ
    Документ.ЗаказПокупателя.Товары КАК ТЧ
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ЗаказПокупателя.Товары КАК ТЧ_Предыдущие
        ПО ТЧ.Ссылка = ТЧ_Предыдущие.Ссылка
        И ТЧ.Номенклатура = ТЧ_Предыдущие.Номенклатура
        И ТЧ.НомерСтроки >= ТЧ_Предыдущие.НомерСтроки
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ЗаказыПокупателей.Остатки(
        &Период,
        ЗаказПокупателя = &ТекущийЗаказ) КАК Остатки
        ПО ТЧ.Ссылка = Остатки.ЗаказПокупателя
        И ТЧ.Номенклатура = Остатки.Номенклатура
ГДЕ
    ТЧ.Ссылка = &ТекущийЗаказ
СГРУППИРОВАТЬ ПО
    ТЧ.НомерСтроки,
    ТЧ.Номенклатура,
    ТЧ.Количество,
    Остатки.КоличествоОстаток
;

ВЫБРАТЬ
    ВТ.НомерСтроки КАК НомерСтроки,
    ВТ.Номенклатура КАК Номенклатура,
    ВТ.КоличествоПлан КАК КоличествоПлан,
    ВЫБОР
        КОГДА ВТ.ВсегоОстаток >= ВТ.НакопленныйИтогПлан
            ТОГДА ВТ.КоличествоПлан
        КОГДА ВТ.ВсегоОстаток > ВТ.НакопленныйИтогПлан - ВТ.КоличествоПлан
            ТОГДА ВТ.ВсегоОстаток - (ВТ.НакопленныйИтогПлан - ВТ.КоличествоПлан)
        ИНАЧЕ 0
    КОНЕЦ КАК ОстатокПоСтроке
ИЗ
    ВТ_СтрокиСИтогами КАК ВТ
УПОРЯДОЧИТЬ ПО
    ВТ.НомерСтроки

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

Способ 4. Организационно-методологическое разделение

В типовых решениях (включая УПП) основным разрезом контроля исполнения заказа покупателя является сам документ заказа. Если две партии одинаковой продукции имеют разные даты готовности и отгрузки, штатным подходом является создание двух отдельных документов «Заказ покупателя» под каждую дату выполнения. Это исключает коллизии в регистрах и снимает необходимость доработки конфигурации.

← На главную