Регистр накопления 1С хранит числа, которые приходят и уходят: товар на складе, долги контрагентов, продажи за месяц. Документ при проведении пишет в него движения, а отчёты получают готовые остатки и обороты, не перебирая документы. Ниже — виды регистров, контроль остатков при проведении, устройство итогов и причины тормозов. Платформа 8.3, конфигурация любая.
Регистр накопления — объект конфигурации, каждая запись которого (движение) увеличивает или уменьшает показатель в разрезе измерений. Записи всегда принадлежат документу-регистратору: независимого режима, как у регистра сведений, здесь нет. Перепровели документ — старые движения заменились новыми, отменили проведение — движения удалились. У каждой цифры есть документ, который её объясняет.
Где в 1С регистры накопления:
Вид задаётся свойством «Вид регистра»; от него зависят поля, виртуальные таблицы и хранение итогов.
| Признак | Регистр остатков | Оборотный регистр |
|---|---|---|
| Что даёт | Остаток на любую дату и движения за период | Только обороты за период |
Поле ВидДвижения | Есть: Приход или Расход | Нет |
| Виртуальные таблицы | Остатки, Обороты, ОстаткиИОбороты | Обороты |
| Агрегаты | Нет | Можно использовать |
| Типичные примеры | Товары на складах, взаиморасчёты, денежные средства | Продажи, закупки, затраты |
Правило выбора простое: если про показатель осмысленно спросить «сколько сейчас», нужен регистр остатков. Если вопрос только «сколько за период» — оборотный. Продажи в регистре остатков — частая ошибка: «остаток продаж» не нужен, а итоги по нему обновляются при каждой записи.
Каждое новое измерение умножает число строк в таблице итогов. Если в измерение попадает поле с почти уникальными значениями — документ-основание, номер строки, серия, — итоги разрастаются до размеров таблицы движений и перестают экономить время. Такие поля кладите в реквизиты. Если по ним действительно нужен остаток, как в партионном учёте, следите, чтобы остатки по закрытым партиям обнулялись.
Порядок измерений влияет на индекс таблицы итогов: первым ставьте измерение, по которому чаще всего отбирают данные. После создания регистра отметьте регистраторы и дайте права в ролях — см. статью про роли 1С.
Пример — документ «Расход товара» списывает товар из регистра остатков ОстаткиТоваров и не даёт уйти в минус. Схема: сначала записать движения под блокировкой, потом проверить остатки. Нужен управляемый режим блокировок и платформа 8.3.6+ (СтрШаблон).
// Модуль объекта документа РасходТовара.
// Регистр накопления ОстаткиТоваров, вид «Остатки».
// Измерения: Склад (СправочникСсылка.Склады), Номенклатура (СправочникСсылка.Номенклатура).
// Ресурс: Количество (Число 15.3).
// Режим управления блокировкой данных в конфигурации: «Управляемый». Платформа 8.3.6+ (СтрШаблон).
Процедура ОбработкаПроведения(Отказ, Режим)
// 1. Формируем движения. При записи набор с отбором по регистратору
// заменяет прежние движения документа.
НаборДвижений = Движения.ОстаткиТоваров;
НаборДвижений.Записывать = Истина;
НаборДвижений.БлокироватьДляИзменения = Истина;
Для Каждого СтрокаТоваров Из Товары Цикл
Движение = НаборДвижений.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Склад = Склад;
Движение.Номенклатура = СтрокаТоваров.Номенклатура;
Движение.Количество = СтрокаТоваров.Количество;
КонецЦикла;
// 2. Записываем сразу: остаток проверяем уже с учётом этого документа.
// Запись самого набора не сбрасывает флаг Записывать. Сбрасываем вручную,
// иначе после ОбработкаПроведения платформа запишет набор ещё раз.
НаборДвижений.Записать();
НаборДвижений.Записывать = Ложь;
// 3. Контроль: не ушёл ли остаток в минус по позициям документа.
Нехватка = НехваткаТоваров();
Если Нехватка.Количество() = 0 Тогда
Возврат;
КонецЕсли;
Для Каждого СтрокаНехватки Из Нехватка Цикл
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = СтрШаблон(НСтр("ru = 'Не хватает товара «%1» на складе «%2»: %3'"),
СтрокаНехватки.Номенклатура, Склад, СтрокаНехватки.Нехватка);
Сообщение.Сообщить();
КонецЦикла;
Отказ = Истина; // транзакция откатится вместе с записанными движениями
КонецПроцедуры
Функция НехваткаТоваров()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| -Остатки.КоличествоОстаток КАК Нехватка
|ИЗ
| РегистрНакопления.ОстаткиТоваров.Остатки(
| &Граница,
| (Склад, Номенклатура) В
| (ВЫБРАТЬ
| ДвиженияДокумента.Склад,
| ДвиженияДокумента.Номенклатура
| ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ДвиженияДокумента
| ГДЕ
| ДвиженияДокумента.Регистратор = &Регистратор)) КАК Остатки
|ГДЕ
| Остатки.КоличествоОстаток < 0";
Запрос.УстановитьПараметр("Граница", Новый Граница(МоментВремени(), ВидГраницы.Включая));
Запрос.УстановитьПараметр("Регистратор", Ссылка);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
Разбор ключевых строк:
БлокироватьДляИзменения = Истина — исключительную блокировку итогов по значениям измерений платформа ставит при записи набора всегда. Но при разделении итогов (у нового регистра оно разрешено по умолчанию) в блокировку входит и разделитель, и два документа по одному товару друг друга не ждут. Свойство убирает разделитель: второй документ по тому же товару и складу ждёт конца первой транзакции.ВидДвижения = ВидДвиженияНакопления.Расход — без этой строки движение запишется приходом.НаборДвижений.Записать() — явная запись до проверки; набор с отбором по регистратору заменяет прежние движения. Метод набора флаг Записывать не сбрасывает: без следующей строки (Записывать = Ложь) платформа запишет движения и итоги второй раз после выхода из обработчика. Альтернатива — Движения.Записать(), он сбрасывает флаг сам.&Граница с ВидГраницы.Включая — остаток на момент документа с учётом его собственных движений.(Склад, Номенклатура) В (…) стоит в параметрах виртуальной таблицы: остатки считаются только по позициям документа, а не по всему складу.Отказ = Истина откатывает транзакцию вместе с записанными движениями.Проверка идёт на момент документа. При проведении задним числом остаток может уйти в минус позже — тогда дополнительно проверяйте текущие остатки: ту же таблицу без параметра периода.
Физическая таблица РегистрНакопления.ОстаткиТоваров — это сами движения: Период, Регистратор, НомерСтроки, Активность, ВидДвижения, измерения, ресурсы и реквизиты. Виртуальные таблицы платформа собирает на лету из итогов и движений.
| Виртуальная таблица | У какого регистра | Параметры | Поля ресурса Количество |
|---|---|---|---|
| Остатки | остатков | Период, Условие | КоличествоОстаток |
| Обороты | остатков и оборотного | НачалоПериода, КонецПериода, Периодичность, Условие | КоличествоПриход, КоличествоРасход, КоличествоОборот; у оборотного — только КоличествоОборот |
| ОстаткиИОбороты | остатков | НачалоПериода, КонецПериода, Периодичность, МетодДополнения, Условие | КоличествоНачальныйОстаток, КоличествоПриход, КоличествоРасход, КоличествоОборот, КоличествоКонечныйОстаток |
Ведомость по складу за период — один запрос к таблице ОстаткиИОбороты:
// Ведомость по складу за период: остаток на начало, приход, расход, остаток на конец.
// Параметры: НачалоПериода = НачалоДня(Дата1), КонецПериода = КонецДня(Дата2).
ВЫБРАТЬ
ОО.Номенклатура КАК Номенклатура,
ОО.КоличествоНачальныйОстаток КАК НаНачало,
ОО.КоличествоПриход КАК Приход,
ОО.КоличествоРасход КАК Расход,
ОО.КоличествоКонечныйОстаток КАК НаКонец
ИЗ
РегистрНакопления.ОстаткиТоваров.ОстаткиИОбороты(
&НачалоПериода,
&КонецПериода,
,
,
Склад = &Склад) КАК ОО
УПОРЯДОЧИТЬ ПО
ОО.Номенклатура.Наименование
Для оборотного регистра Продажи обороты по месяцам и контрагентам получаются так:
// Оборотный регистр Продажи: измерения Контрагент, Номенклатура; ресурсы Количество, Сумма.
ВЫБРАТЬ
Продажи.Период КАК Месяц,
Продажи.Контрагент КАК Контрагент,
Продажи.СуммаОборот КАК Сумма
ИЗ
РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Месяц) КАК Продажи
УПОРЯДОЧИТЬ ПО
Месяц,
Сумма УБЫВ
Таблицы регистра в СУБД показывает функция ПолучитьСтруктуруХраненияБазыДанных (листинг ниже). Обычно это таблица движений _AccumRg<N> и таблица итогов: _AccumRgT<N> у регистра остатков, _AccumRgTn<N> у оборотного. Настройки итогов лежат в служебной таблице _AccumRgOpt, у агрегатов и регистрации изменений — свои таблицы. Писать в них напрямую SQL-запросами нельзя: итоги разойдутся с движениями.
Ради итогов регистр накопления и существует. У регистра остатков платформа хранит остатки помесячно до периода рассчитанных итогов и отдельно — текущие итоги. Остаток на произвольную дату считается так: платформа берёт ближайшую более позднюю или совпадающую точку с сохранёнными итогами — границу месяца до периода рассчитанных итогов или текущие итоги — и откатывает движения между нужной датой и этой точкой. У оборотного регистра итоги — обороты по месяцам.
ПересчитатьИтоги(), ПересчитатьИтогиЗаПериод(), ПересчитатьТекущиеИтоги() или обработка «Управление итогами». Нужен после сбоев или когда остаток не сходится с суммой активных движений (сверка — ниже). После загрузки с выключенными итогами отдельный пересчёт не нужен: УстановитьИспользованиеИтогов(Истина) пересчитывает их сам и тоже идёт долго. Требует права «Управление итогами», на большом регистре — вне рабочего времени.УстановитьРазделениеИтогов(). Параллельные транзакции пишут приращения в разные строки таблицы итогов и не ждут друг друга на уровне СУБД. Плата — итогов больше и читаются они чуть медленнее. Для регистра с контролем остатков обязательно БлокироватьДляИзменения = Истина (см. разбор примера): без него проверка после записи не защищает от ухода в минус.ОбновитьАгрегаты()) и перестраивать под реальные запросы. Имеют смысл на больших регистрах.Сверка итогов с движениями — одним запросом. Учитывайте только активные записи: неактивные в итоги не попадают и дадут ложное расхождение.
// Сверка итогов с движениями регистра ОстаткиТоваров.
// Параметры: Дата = КонецДня(ДатаСверки);
// Граница = Новый Граница(КонецДня(ДатаСверки), ВидГраницы.Включая).
ВЫБРАТЬ
ДвиженияРегистра.Склад КАК Склад,
ДвиженияРегистра.Номенклатура КАК Номенклатура,
СУММА(ВЫБОР
КОГДА ДвиженияРегистра.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
ТОГДА ДвиженияРегистра.Количество
ИНАЧЕ -ДвиженияРегистра.Количество
КОНЕЦ) КАК Количество
ПОМЕСТИТЬ ПоДвижениям
ИЗ
РегистрНакопления.ОстаткиТоваров КАК ДвиженияРегистра
ГДЕ
ДвиженияРегистра.Активность
И ДвиженияРегистра.Период <= &Дата
СГРУППИРОВАТЬ ПО
ДвиженияРегистра.Склад,
ДвиженияРегистра.Номенклатура
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЕСТЬNULL(ПоИтогам.Склад, ПоДвижениям.Склад) КАК Склад,
ЕСТЬNULL(ПоИтогам.Номенклатура, ПоДвижениям.Номенклатура) КАК Номенклатура,
ЕСТЬNULL(ПоИтогам.КоличествоОстаток, 0) КАК ОстатокПоИтогам,
ЕСТЬNULL(ПоДвижениям.Количество, 0) КАК ОстатокПоДвижениям
ИЗ
РегистрНакопления.ОстаткиТоваров.Остатки(&Граница) КАК ПоИтогам
ПОЛНОЕ СОЕДИНЕНИЕ ПоДвижениям КАК ПоДвижениям
ПО ПоИтогам.Склад = ПоДвижениям.Склад
И ПоИтогам.Номенклатура = ПоДвижениям.Номенклатура
ГДЕ
ЕСТЬNULL(ПоИтогам.КоличествоОстаток, 0) <> ЕСТЬNULL(ПоДвижениям.Количество, 0)
Состояние итогов удобно смотреть из внешней обработки. Код для модуля её формы:
// Модуль формы внешней обработки. Все обращения к регистру — на сервере.
&НаСервереБезКонтекста
Функция СостояниеРегистраНаСервере(ИмяРегистра)
МетаРегистр = Метаданные.РегистрыНакопления[ИмяРегистра];
Менеджер = РегистрыНакопления[ИмяРегистра];
Состояние = Новый Структура;
Состояние.Вставить("ИтогиИспользуются", Менеджер.ПолучитьИспользованиеИтогов());
Состояние.Вставить("РазделениеИтогов", Менеджер.ПолучитьРазделениеИтогов());
// Текущие итоги и период рассчитанных итогов есть только у регистра остатков.
Если МетаРегистр.ВидРегистра = Метаданные.СвойстваОбъектов.ВидРегистраНакопления.Остатки Тогда
Состояние.Вставить("ТекущиеИтогиИспользуются", Менеджер.ПолучитьИспользованиеТекущихИтогов());
Состояние.Вставить("ИтогиРассчитаныПо", Менеджер.ПолучитьПериодРассчитанныхИтогов());
КонецЕсли;
// Таблицы регистра в СУБД: назначение и имя таблицы хранения.
ОбъектыМетаданных = Новый Массив;
ОбъектыМетаданных.Добавить(МетаРегистр);
Таблицы = Новый Массив;
Для Каждого ОписаниеТаблицы Из ПолучитьСтруктуруХраненияБазыДанных(ОбъектыМетаданных) Цикл
Таблицы.Добавить(ОписаниеТаблицы.Назначение + ": " + ОписаниеТаблицы.ИмяТаблицыХранения);
КонецЦикла;
Состояние.Вставить("Таблицы", Таблицы);
Возврат Состояние;
КонецФункции
&НаСервереБезКонтекста
Процедура ПересчитатьИтогиНаСервере(ИмяРегистра)
Если Не ПравоДоступа("УправлениеИтогами", Метаданные) Тогда
ВызватьИсключение НСтр("ru = 'Недостаточно прав: нужно право «Управление итогами».'");
КонецЕсли;
// На большом регистре выполняется долго: запускайте вне рабочего времени.
РегистрыНакопления[ИмяРегистра].ПересчитатьИтоги();
КонецПроцедуры
УстановитьИспользованиеИтогов(Истина), и каждый запрос считает остатки по движениям.Если база уже медленная, а причина не очевидна, начинайте с замеров — см. услугу «1С тормозит».
&КонецПериода, равный 31.03.2026 00:00:00, отрезает весь последний день. Передавайте КонецДня(Дата) или Новый Граница(КонецДня(Дата), ВидГраницы.Включая).БлокироватьДляИзменения или ставьте управляемую блокировку до чтения.Регистр накопления складывает числа и отдаёт остатки и обороты, а записи в него делают только документы. Регистр сведений хранит одно значение на сочетание ключей — цену, курс, настройку — и может обходиться без регистратора. Подробнее — в статье про регистр сведений 1С.
Нет. Набор можно создать кодом через РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей(), но в отборе всё равно указывается документ-регистратор. Ручные исправления оформляют документом корректировки — так видно, кто и когда поправил остаток.
Командами перехода к регистрам на панели навигации формы документа (нужны права на регистр) или отчётом БСП «Движения документа». Программисту быстрее запрос к физической таблице с отбором по Регистратор.
Сравните остаток из виртуальной таблицы Остатки с суммой активных движений физической таблицы на ту же дату — запрос приведён в разделе про итоги. Расхождение — повод пересчитать итоги. Если цифры совпадают, но остаток неверный, ошибка в самих движениях: пересчёт не поможет, нужно исправлять проведение.
Спроектировать регистр заранее дешевле, чем переделывать его на живых данных с переносом истории и перепроведением документов. Если нужно добавить учёт в новых разрезах, настроить контроль остатков или выяснить, почему проведение и отчёты стали медленными, посмотрите услуги по доработке 1С или разместите задачу на площадке: оценка бесплатная, ответ — в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.