1C-CodeОсновы 1С → Регистры накопления: сколько и где

Регистры накопления: сколько и где

Остатки и обороты не хранятся в документах — их считают по движениям. Главный механизм учёта и главный источник вопросов на собеседовании.

Глава 19 из 36 · чтение примерно 30 минут

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

Первое, что приходит в голову, — держать поле «Остаток» в справочнике «Номенклатура» и менять его при каждом движении. Так делать нельзя, и понять почему — значит понять устройство всего учёта в 1С.

Почему поле «Остаток» — плохая идея

Нельзя посмотреть прошлое. «Сколько было на первое апреля» — ответа нет, поле хранит только «сейчас».

Нельзя разобраться, откуда взялось. Остаток разошёлся с фактом — и непонятно, какой документ виноват.

Нельзя перепровести. Исправили накладную задним числом — а поле уже дважды изменено.

Двое одновременно ломают его гарантированно. Прочитали оба по 10, оба записали 7 — вместо 4.

Движения вместо итога

1С хранит не остаток, а историю изменений. Каждое проведение документа пишет строки в регистр накопления: что, куда, сколько и в какую сторону.

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

Отсюда все свойства, за которые этот механизм и любят: видно прошлое на любую дату, видно, каким документом сделано каждое движение, и перепроведение просто переписывает строки этого документа.

Из чего состоит движение

ЧастьЧто этоПример
Периоддата движения05.01.2024
Регистратордокумент, который его сделалПоступление 1
ВидДвиженияприход или расходПриход
Измеренияразрезы: в каком сочетании считаемНоменклатура, Склад
Ресурсыто, что складываетсяКоличество, Сумма
Реквизитысправочно, в итоги не идутКомментарий

Измерение, ресурс, реквизит

Различие простое и его спрашивают почти всегда.

Ресурс складывается. Количество, сумма. Это то, что вы хотите видеть в итоге.

Измерение — разрез, по которому складывается. Остаток «по товару и складу» означает: измерения Номенклатура и Склад.

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

Ошибка «сделал измерением то, что должно быть реквизитом» дорогая: каждое лишнее измерение размножает строки итогов и замедляет всё.

Два вида регистров накопления

Остатки — когда нужен ответ «сколько сейчас». Товары на складах, деньги в кассе, долги контрагентов. У движений есть приход и расход.

Обороты — когда «сколько за период», а остаток бессмыслен. Продажи, выручка, количество звонков. Расхода у таких движений нет: только накопление.

Выбирают по вопросу, на который отвечает регистр. «Сколько продали в марте» — обороты. «Сколько лежит на складе» — остатки. Сделать остаточный регистр там, где нужны только обороты, значит заставить платформу считать и хранить итоги, которые никто не спросит.

Виртуальные таблицы

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

Остатки — сколько на дату. Обороты — сколько за период. ОстаткиИОбороты — начальный остаток, приход, расход, конечный остаток одной таблицей.

Главное правило: отбор передают параметром виртуальной таблицы, а не условием ГДЕ. Разница не в красоте — в количестве прочитанных строк. С параметром платформа возьмёт нужные итоги; с условием ГДЕ — сначала соберёт всё, потом выбросит лишнее.

На чём спотыкаются

Фильтруют через ГДЕ вместо параметров. Работает одинаково, отличается в десятки раз. Это первое, что смотрят, когда «отчёт тормозит».

Забывают, что остатка может не быть. Товара на складе не было — строки в виртуальной таблице тоже нет, а не ноль. Соединение обязано быть левым, а результат — обёрнут в ЕСТЬNULL.

Считают остаток на дату документа, а не на момент. Граница периода бывает включающей и исключающей; из-за этого документ то видит собственное движение, то нет.

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

Что умеет виртуальная таблица остатков

Регистр даёт не одну таблицу, а несколько. Обращаться к ним по-разному — и выбор между ними определяет, будет отчёт работать секунду или минуту.

Таблицы регистра накопления

ТаблицаЧто отдаётКогда берут
РегистрНакопления.Имясами движения, по одной строке на записькогда нужно «кто это сделал» — ссылка на регистратор
…​.Остатки(Период, Отбор)остаток на момент«сколько сейчас» и «сколько было на дату»
…​.Обороты(Начало, Конец, Период, Отбор)приход и расход за период«сколько продали за месяц»
…​.ОстаткиИОбороты(…)остаток на начало, обороты, остаток на конецоборотно-сальдовая ведомость — всё сразу
…​.Обороты у оборотного регистратолько оборотыу регистра оборотов остатков нет вовсе

Параметры виртуальной таблицы

ВЫБРАТЬ
	Номенклатура,
	КоличествоОстаток
ИЗ
	РегистрНакопления.ОстаткиТоваров.Остатки(
		&НаДату,
		Склад = &Склад И Номенклатура В (&СписокТоваров))
ЧастьЧто означает
&НаДатупервый параметр — момент; пусто означает «на сейчас»
второй параметротбор ВНУТРИ виртуальной таблицы — не путать с ГДЕ
КоличествоОстатокимя ресурса плюс «Остаток»: так платформа называет колонки итогов
без соединенияостаток уже посчитан — складывать движения руками не надо

Отбор в параметрах, а не в ГДЕ

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

ГДЕ Склад = &Склад после виртуальной таблицы работает так: платформа считает остатки по всем складам и всей номенклатуре, а потом выбрасывает лишнее. Отбор в параметрах — считает только по нужному.

Разница на демо-базе незаметна. На базе с миллионом движений это разница между «секунда» и «полторы минуты», и находят её обычно замером, когда отчётом уже пользуются.

Упражнение 2. Остаток товара на складе

Напишите Остаток(Товар, Склад): количество на складе через виртуальную таблицу .Остатки, отбор — в параметрах, а не в ГДЕ. Проверка спрашивает про Гвозди 100мм на Основном складе. Если ничего не нашлось, вернуть 0, а не NULL.

Решается в тренажёре: код запускается и проверяется сразу.

Остаток ушёл в минус

Регистр накопления не запрещает отрицательный остаток. Он честно складывает движения: пришло 100, ушло 300 — останется минус 200.

Запрет — это не свойство регистра, а ваш код в проведении. Нет проверки — будет минус, и никто не заметит, пока кладовщик не придёт с вопросом.

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

Упражнение 3. Найти минус на складе

Напишите ВМинусе(): верните наименование первого товара, у которого остаток отрицательный. Если таких нет — пустую строку.

Решается в тренажёре: код запускается и проверяется сразу.

Итоги: почему остатки считаются быстро

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

У регистра есть служебные таблицы итогов: остаток на конец каждого месяца и «текущие итоги» на последний момент. Запрос к виртуальной таблице берёт ближайший готовый итог и досчитывает по движениям только остаток пути.

Из этого следуют две практические вещи, про которые спрашивают:

Запрос на середину месяца медленнее, чем на границу: досчитывать приходится больше.

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

Регистратор и набор записей

У каждой записи регистра есть регистратор — ссылка на документ, который её сделал. Движения без регистратора в регистре накопления невозможны.

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

Это и ответ на вопрос «как удалить движения»: записать пустой набор с тем же отбором.

Период движения — дата документа, а не «сейчас»

В движении есть поле Период, и заполнять его надо датой документа. Написали ТекущаяДата() — и документ от первого марта лёг в остатки сегодняшним числом.

Проявляется это не сразу: «сейчас» отчёты покажут верно. Сломается отчёт на дату — и разбираться с ним будут через полгода, когда автора уже не спросить.

Сколько регистров заводить

Начинающий пытается сделать один регистр «на всё»: и количество, и сумма, и партии, и резерв.

Правило простое: один регистр отвечает на один вопрос. Остатки товаров, взаиморасчёты с контрагентами, товары в резерве — три разных регистра, потому что это три разных вопроса с разными измерениями.

Признак, что регистров надо два: часть измерений у половины движений пустая. Если «Договор» заполняется только для взаиморасчётов, а для товарных движений пуст — значит, в один регистр свели две сущности.

Почему нельзя просто добавить измерение

Соблазн есть: добавить в существующий регистр ещё одно измерение — «и заказ тоже». Цена этого решения не видна сразу.

Каждое измерение дробит остатки. Был остаток «товар × склад», стал «товар × склад × заказ» — и строк в итогах стало в сто раз больше, а «сколько всего на складе» теперь требует группировки.

Поэтому измерения добавляют, только когда по ним действительно нужен ОСТАТОК. Если нужна просто справка «из какого заказа» — это реквизит, а не измерение.

Упражнение 1. Остаток по движениям

Функция ОстатокТовара(Товар, Склад) должна пройти по движениям регистра ОстаткиТоваров и вернуть остаток: приходы плюс, расходы минус. Считайте только строки с нужным товаром и складом.

Решается в тренажёре: код запускается и проверяется сразу.

Короткий свод

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

Как закрепить

Читать про код и писать код — разные умения. В тренажёре к этой главе идут упражнения: вы пишете решение, оно запускается на настоящем интерпретаторе 1С и проверяется сразу, без установки платформы.

Открыть эту главу в тренажёре

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