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

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

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

Зачем нужна группировка данных перед записью?

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

  1. Избыточность данных: Вместо одной итоговой записи в таблице движений регистра появляется множество мелких записей. Это раздувает размер базы данных и замедляет работу отчетов.
  2. Проблемы с контролем остатков: Представим, что в документе две строки по 10 единиц товара «Кирпич». На складе всего 15 единиц. При последовательной проверке первая строка (10 ед.) пройдет успешно, а на второй (еще 10 ед.) система выдаст ошибку, так как увидит остаток только в 5 ед. Если же мы заранее свернем строки в одну запись (20 ед.), система сразу поймет, что товара недостаточно в полном объеме.
  3. Блокировки базы данных: Каждая запись инициирует обновление индексов. Группировка данных минимизирует количество обращений к менеджеру блокировок, снижая вероятность возникновения Deadlocks (взаимных блокировок) при работе нескольких пользователей.

Метод 1: Использование метода Свернуть() для таблицы значений

Самый простой и интуитивно понятный способ, который часто используют начинающие разработчики, — это выгрузка табличной части в объект ТаблицаЗначений с последующим применением метода Свернуть. Рассмотрим этот процесс по шагам.

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


// В обработчике ОбработкаПроведения документа
ТаблицаДвижений = ТЧТовары.Выгрузить();

// Указываем измерения (через запятую) и ресурсы
// Все, что не указано в первом параметре и не является числом во втором, будет удалено
ТаблицаДвижений.Свернуть("Номенклатура, Склад, Характеристика", "Количество, Сумма");

Для Каждого СтрокаДвижения Из ТаблицаДвижений Цикл
    Движение = Движения.ОстаткиНоменклатуры.Добавить();
    Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
    Движение.Период = Дата;
    Движение.Номенклатура = СтрокаДвижения.Номенклатура;
    Движение.Склад = СтрокаДвижения.Склад;
    Движение.Количество = СтрокаДвижения.Количество;
КонецЦикла;

Важный нюанс: метод Свернуть чувствителен к типам данных. Если у вас в одной строке Склад заполнен, а в другой — нет (значение Неопределено или пустая ссылка), система воспримет их как разные измерения и не объединит строки. Поэтому перед сворачиванием убедитесь, что все ключевые аналитики заполнены корректно.

Метод 2: Профессиональный подход с использованием Запроса

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

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


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

// Передаем табличную часть как параметр запроса
Запрос.УстановитьПараметр("ТЧТовары", ЭтотОбъект.Товары.Выгрузить());

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    Движение = Движения.ОстаткиНоменклатуры.ДобавитьПриход();
    ЗаполнитьЗначенияСвойств(Движение, Выборка);
    Движение.Период = Дата;
КонецЦикла;

Использование оператора СГРУППИРОВАТЬ ПО гарантирует нам, что на выходе мы получим уникальный набор измерений с накопленным итогом по ресурсам. Это наиболее надежный способ подготовить данные для записи в регистры остатков.

Влияние на расчет себестоимости и учет по сериям

Проанализируем ситуацию, когда у номенклатуры есть дополнительные разрезы учета, такие как Серии или Характеристики. Это критически важный момент при группировке. Если в документе две строки с одинаковой номенклатурой, но разными сериями (например, разные сроки годности), их нельзя сворачивать в одну запись!

Рассмотрим правила корректной группировки:

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

Использование «Дополнительных свойств» для оптимизации

В типовых конфигурациях (УТ 11, ERP, КА) часто применяется архитектурный паттерн с использованием свойства ДополнительныеСвойства. Это позволяет сгруппировать данные один раз и использовать их во всех подписках на события или при записи в несколько разных регистров (например, в регистр остатков и регистр выручки одновременно). Для детального анализа последовательности выполнения транзакционных процедур и подписок можно использовать инструмент для отслеживания жизненного цикла событий платформы.

Рассмотрим, как это выглядит на практике:

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

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

Группировка одинаковой номенклатуры при записи в регистры накопления — это не просто прихоть постановщика ТЗ, а стандарт качественной разработки. Это обеспечивает целостность данных, корректную работу алгоритмов контроля остатков и высокую производительность базы данных. Мы рекомендуем использовать метод Запроса для группировки, так как он предоставляет больше инструментов для контроля данных и работает эффективнее в многопользовательской среде. Помните о важности совпадения всех аналитик (склад, серия, характеристика) и всегда тестируйте проведение документа с дублирующимися строками, чтобы убедиться в правильности суммирования итогов. Для проверки своих сил и закрепления навыков складского учета на реальном примере можно использовать практический кейс тестового задания с решением по учету товаров на складах.

← На главную