Как правильно реализовать ведение статусов документов по нескольким типам объектов в 1С?

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

В процессе разработки корпоративных информационных систем на платформе «1С:Предприятие» перед архитектором часто встает задача проектирования подсистемы жизненного цикла документов. Нам требуется вести учет различных состояний (например, «Заказ: создан, оплачен, собран, отгружен» или «Реализация: подготовлена, оригиналы получены»). При этом система должна работать быстро, не перегружать СУБД, позволять строить аналитические отчеты по истории изменений и корректно работать в условиях закрытых периодов.

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

Реквизит объекта или Регистр сведений: Анализ подходов

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

Подход 1: Хранение статуса в реквизите самого документа

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

Преимущества:

Недостатки:

Подход 2: Хранение статусов в регистре сведений

Этот подход предполагает создание независимого (или подчиненного регистратору) регистра сведений (например, РегистрСведений.СтатусыДокументов), где ключевым измерением является ссылка на документ, а ресурсом — его статус.

Преимущества:

Недостатки:

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

Выбор типа измерения регистра: Составной тип, ПВХ или Определяемый тип?

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

1. Почему нельзя использовать План видов характеристик (ПВХ)?

Некоторые начинающие разработчики путают назначение объектов метаданных и предлагают использовать ПВХ в качестве типа измерения. Это грубая архитектурная ошибка. План видов характеристик предназначен для хранения метаданных о свойствах (например, «Цвет», «Размер», «Диагональ»), а не для хранения ссылок на физические документы информационной базы. Для идентификации документов ПВХ неприменим.

2. Проблема составного типа данных «в лоб»

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

3. Лучшее решение: Использование Определяемых типов

Для централизации и оптимизации работы с составными типами в платформе 1С предусмотрен специальный объект метаданных — ОпределяемыйТип. Создадим определяемый тип (например, ОпределяемыйТип.ДокументСоСтатусом) и настроим его состав:

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

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

Для эффективного ведения статусов создадим независимый периодический регистр сведений СтатусыДокументов со следующей структурой:

Проблема производительности динамических списков и гибридный подход

Если мы будем выводить статус документа в форму списка (например, в список заказов покупателей), получая текущее состояние через левое соединение таблицы документов с виртуальной таблицей СрезПоследних нашего регистра сведений, интерфейс начнет «тормозить» при скроллинге, поиске и отборах. Виртуальные таблицы срезов последних в соединениях — крайне тяжелая операция для СУБД на больших объемах данных.

Чтобы обойти это ограничение, применим гибридный архитектурный подход:

  1. Создаем реквизит: В самом документе все же создаем реквизит Статус (без признака проведения, чтобы его изменение не влияло на движения документа). Он будет использоваться исключительно для быстрого вывода в динамические списки и простых отборов.
  2. Разделяем запись:
    • При изменении бизнес-состояния документа (например, при фиксации оплаты или сборки) мы делаем запись новой строки в периодический регистр сведений СтатусыДокументов. Это сохраняет историю изменений.
    • Одновременно с этим мы программно обновляем реквизит Статус в самом документе. Чтобы обойти проблему закрытых периодов и не вызывать блокировки, мы записываем документ с установленным признаком ОбменДанными.Загрузка = Истина.

Рассмотрим пример кода, реализующий этот гибридный механизм при изменении статуса заказа:


Процедура УстановитьНовыйСтатусДокумента(СсылкаНаДокумент, НовыйСтатус, Автор, Комментарий = "") Экспорт
    
    // Шаг 1. Запись истории в периодический регистр сведений
    НаборЗаписей = РегистрыСведений.СтатусыДокументов.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Документ.Установить(СсылкаНаДокумент);
    
    // Поскольку регистр периодический, мы не перезаписываем старые, а добавляем новую запись
    НоваяЗапись = НаборЗаписей.Добавить();
    НоваяЗапись.Период = ТекущаяДатаСеанса();
    НоваяЗапись.Документ = СсылкаНаДокумент;
    НоваяЗапись.Статус = НовыйСтатус;
    НоваяЗапись.АвторИзменения = Автор;
    НоваяЗапись.Примечание = Комментарий;
    
    Попытка
        НаборЗаписей.Записать(Ложь); // Параметр Ложь указывает на добавление записей, а не перезапись всего набора по отбору
    Исключение
        ЗаписьЖурналаРегистрации("Установка статуса", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
        ВызватьИсключение "Не удалось записать историю изменения статуса!";
    КонецПопытки;
    
    // Шаг 2. Обновление реквизита в самом документе для оптимизации динамических списков
    // Обходим блокировки закрытого периода и оптимизируем скорость записи
    ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
    Если ДокументОбъект.Статус <> НовыйСтатус Тогда
        ДокументОбъект.Статус = НовыйСтатус;
        
        // Включаем режим загрузки, чтобы отключить проверки проведения и подписки на события,
        // которые могут заблокировать запись в закрытом периоде
        ДокументОбъект.ОбменДанными.Загрузка = Истина;
        
        Попытка
            ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);
        Исключение
            ЗаписьЖурналаРегистрации("Установка статуса в документе", УровеньЖурналаРегистрации.Предупреждение,,, ОписаниеОшибки());
            // Даже если объект заблокирован намертво СУБД, у нас осталась запись в регистре сведений
        КонецПопытки;
    КонецЕсли;
    
КонецПроцедуры

Оптимизация работы с регистрами в платформе версии 8.3.25 и выше

Если ваша база данных развернута на современных версиях платформы (8.3.25+), обязательно воспользуйтесь новыми системными механизмами оптимизации записи больших таблиц.

Режим замещения при записи (Merge)

Для независимых регистров сведений в новых версиях платформы оптимизирован механизм записи наборов данных. При использовании метода Записать() платформа использует СУБД-специфичные инструкции слияния (например, MERGE в MS SQL Server или INSERT ... ON CONFLICT в PostgreSQL). Это позволяет не очищать предварительно всю таблицу по отбору перед вставкой новых данных, а обновлять существующие и дозаписывать новые записи в один проход, что кардинально экономит транзакционные ресурсы сервера баз данных.

Режим сокращения типов при реструктуризации

Если со временем список документов, для которых ведется учет статусов, сокращается, платформа позволяет эффективно управлять освобождением места. В свойствах метаданных при изменении состава ОпределяемогоТипа используйте свойство «Режим сокращения типа» в значение «Удаление данных». Платформа при реструктуризации базы данных автоматически очистит устаревшие записи физических таблиц СУБД, предотвращая накопление «мусорных» данных и уменьшая размер индексов регистра.

Резюме

Мы проанализировали подходы к реализации контроля состояний бизнес-объектов в системе «1С:Предприятие». Подводя итоги, выделим ключевые правила построения подсистемы:

  1. Не используйте План видов характеристик для хранения ссылок на экземпляры документов.
  2. Для минимизации неявных левых соединений на уровне SQL-запросов объединяйте целевые документы в Определяемый тип.
  3. Для ведения полноценной аналитики по времени прохождения этапов используйте периодический независимый регистр сведений.
  4. Для быстрой отрисовки списков документов используйте гибридный метод: дублируйте актуальный статус в реквизит документа без запуска тяжелых транзакций проведения при помощи флага ОбменДанными.Загрузка = Истина.
  5. </ol
← На главную