Можно ли использовать числовой тип для измерения регистра накопления и какие риски это влечет?

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

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

В чем главная опасность числового измерения в регистре остатков

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

  1. Зависание незакрытых остатков: чтобы регистр остатков сошелся в ноль, комбинация измерений в расходном движении должна строго совпадать с приходной записью. Если приход был зафиксирован по значению 333, а при списании из-за человеческого фактора или логики заполнения подставилось 334, по первому значению зависнет положительный остаток, а по второму образуется отрицательный. Проанализируем типичный сценарий: любое изменение порядка строк в табличной части документа-основания меняет числовые привязки, в результате чего движения перестают «схлопываться».
  2. Разрастание таблицы итогов: платформа автоматически формирует и обновляет физическую таблицу итогов СУБД. В ней хранятся свернутые остатки. Если измерение высокоселективное (каждое число уникально или редко повторяется), агрегации не происходит. Таблица итогов по количеству записей становится сопоставима с основной таблицей движений. Это многократно замедляет получение остатков через виртуальные таблицы, снижает скорость проведения документов и утяжеляет регламентную процедуру пересчета итогов.
  3. Искажение управляемых блокировок: контроль остатков при проведении в управляемом режиме требует блокировки пространства измерений. Если блокировка накладывается с учетом детализированного числового индекса, транзакция заблокирует только конкретную строку, а не общий остаток товара по заказу. При параллельной работе пользователей это приведет к пропуску превышения лимитов и появлению неоправданных минусов.

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

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

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

Архитектурные альтернативы: как решить задачу правильно

Если задача заключается в том, чтобы связать товарные позиции заказа с адресами доставки или операциями выполнения услуг, рассмотрим проверенные шаблоны проектирования, рекомендуемые стандартами разработки 1С.

1. Использование реквизита «КлючСвязи» на уровне документа

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

Рассмотрим пример связи строк при обработке проведения:


Для Каждого СтрТовары Из ТаблицаТовары Цикл
    Отбор = Новый Структура("КлючСвязи", СтрТовары.КлючСвязи);
    СтрокиАдресов = ТаблицаАдреса.НайтиСтроки(Отбор);
    
    Для Каждого СтрАдрес Из СтрокиАдресов Цикл
        // Формируем движения регистра или сопоставляем данные
    КонецЦикла;
КонецЦикла;

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

2. Шаблон «Ключ аналитики» (Справочник аналитики)

Когда требуется учитывать остатки в сложном разрезе нескольких сущностей (Заказ, Вид услуги, Адрес), добавление множества разнородных измерений в регистр неэффективно. Вместо этого создают служебный справочник КлючиАналитикиУслуг, реквизитами которого выступают все необходимые аналитики. В регистре накопления создается всего одно измерение ссылочного типа:


Функция ПолучитьКлючАналитики(Заказ, ВидУслуги, Адрес)
    Ключ = Справочники.КлючиАналитикиУслуг.НайтиПоРеквизитам(
        Новый Структура("Заказ, ВидУслуги, Адрес", Заказ, ВидУслуги, Адрес)
    );
    Если Не ЗначениеЗаполнено(Ключ) Тогда
        НовыйОбъект = Справочники.КлючиАналитикиУслуг.СоздатьЭлемент();
        НовыйОбъект.Заказ = Заказ;
        НовыйОбъект.ВидУслуги = ВидУслуги;
        НовыйОбъект.Адрес = Адрес;
        НовыйОбъект.Записать();
        Ключ = НовыйОбъект.Ссылка;
    КонецЕсли;
    Возврат Ключ;
КонецФункции

Такой подход сохраняет целостность ссылочных данных, обеспечивает быстродействие индексов СУБД и исключает появление несогласованных записей при ручном вводе.

3. Разделение регистра остатков и регистра сведений

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

← На главную