Как правильно организовать хранение состава изделия в регистре сведений, чтобы избежать ошибок в «Срезе последних»?

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

При разработке систем на платформе 1С:Предприятие одной из типовых задач является хранение спецификаций или составов изделий (например, рецептуры блюд, комплектация мебели или состав наборов). Часто начинающие разработчики используют для этого периодический регистр сведений, где в измерениях указывается «Изделие» и «Ингредиент». Однако здесь кроется серьезная ловушка: при исключении ингредиента из состава стандартный механизм СрезПоследних продолжает возвращать старую запись, так как она остается последней актуальной именно для этого сочетания измерений.

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

Проанализируем причину проблемы

Давайте разберем ситуацию на примере. У нас есть изделие «Хлеб». В версии №1 он состоял из муки, соли и сахара. Мы создали три записи в периодическом регистре сведений. Позже мы решили убрать сахар из рецепта. Мы создаем новую запись на текущую дату только для муки и соли. Но когда мы вызываем виртуальную таблицу СрезПоследних, система ищет последние записи по КАЖДОМУ уникальному набору измерений. Для муки и соли она найдет новые записи, а для сахара — старую, так как более новой записи по измерению «Сахар» просто не существует. В итоге сахар «зависает» в составе.

Решение №1: Использование справочника спецификаций (Золотой стандарт 1С)

Проанализируем наиболее правильный с точки зрения архитектуры подход, который используется в таких решениях, как 1С:ERP или 1С:УНФ. Вместо того чтобы хранить каждый ингредиент отдельной строкой регистра, мы выносим весь состав в табличную часть отдельного объекта.

Рассмотрим шаги реализации:

  1. Создадим справочник СпецификацииНоменклатуры.
  2. В этом справочнике создадим табличную часть Состав с реквизитами Номенклатура (ингредиент) и Доля (процент или количество).
  3. Создадим периодический регистр сведений ДействующиеСпецификации.
  4. В регистре сделаем одно измерение — Изделие и один ресурс — Спецификация (ссылка на наш справочник).

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

Решение №2: Метод «обнуления» или флаг активности

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

Для этого в регистр необходимо добавить ресурс ВходитВСостав (тип Булево) или просто проверять ресурс Количество. Если ингредиент удаляется из рецепта, мы должны явно записать в регистр строку по этому ингредиенту с нулевым количеством или флагом Ложь.

Посмотрим на пример кода при записи нового состава:


// Перед записью нового состава определим список исключаемых элементов
Запрос = Новый Запрос;
Запрос.Текст = 
"ВЫБРАТЬ
|	РецептыСрезПоследних.Ингредиент КАК Ингредиент
|ИЗ
|	РегистрСведений.СоставИзделий.СрезПоследних(&ДатаАктуальности, Изделие = &Изделие) КАК РецептыСрезПоследних";

Запрос.УстановитьПараметр("ДатаАктуальности", ТекущаяДата());
Запрос.УстановитьПараметр("Изделие", ВыбранноеИзделие);
// Далее сравниваем старый список с новым и для отсутствующих пишем Количество = 0

При извлечении данных через СрезПоследних в запросе обязательно нужно добавить условие фильтрации:


ГДЕ
    РецептыСрезПоследних.Количество > 0
    И РецептыСрезПоследних.ВходитВСостав = ИСТИНА

Решение №3: Ключ версии (Snapshot)

Разберем еще один продвинутый метод. Мы можем добавить в регистр сведений измерение КлючСостава (тип УникальныйИдентификатор или Число). Для каждой новой итерации состава мы генерируем новый ключ.

В этом случае алгоритм получения данных будет следующим:

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

Этот метод гарантирует, что вы получите «снимок» системы на определенный момент времени, и никакие записи из «прошлого» не подмешаются к результату, так как у них будут другие ключи.

Решение №4: Перенос ингредиентов в ресурсы

Если ваш состав изделия строго фиксирован и не предполагает бесконечного списка компонентов (например, только Мука, Соль, Сахар и Вода), мы можем отказаться от измерения Ингредиент вообще.

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

Подведем итоги

Выбор метода зависит от сложности вашей системы:

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

← На главную