Что выбрать для учета состояний и очереди заявок в 1С: регистр накопления, регистр сведений или задачи?

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

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

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

Вариант 1. Регистр накопления остатков с фиксированным количеством 1

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

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

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

Недостатки и технические риски:

  1. Избыточная нагрузка на СУБД: Для регистров накопления остатков платформа 1С автоматически рассчитывает и поддерживают физические таблицы итогов. Использование математического пересчета итогов ради проверки простого флага наличия/отсутствия объекта создает неоправданную нагрузку при массовом проведении документов.
  2. Риск «зависших» остатков: При отмене проведения, изменении документов задним числом или некорректном ручном редактировании наборов записей возможна ситуация, когда в остатках появляются отрицательные значения или «зависшие» заявки.
  3. Эскалация блокировок: При одновременной работе десятков курьеров и диспетчеров записи в таблицы итогов регистра накопления могут провоцировать блокировки на уровне СУБД.

Вариант 2. Регистры сведений (периодический и непериодический)

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

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

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

Подход Б: Непериодический регистр сведений «Очередь обработки» (Паттерн «Очередь»)
Создается независимый непериодический регистр сведений, например, ЗаявкиКРаспределению, с единственным измерением Заявка. При создании или открытии заявки в регистр добавляется запись. При назначении заявки курьеру запись из регистра физически удаляется.

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

Вариант 3. Использование встроенного объекта метаданных «Задачи»

Проанализируем применение штатного механизма платформы — объекта метаданных Задача. Этот объект специально спроектирован для реализации бизнес-процессов и операционных очередей.

При создании заявки программно или через бизнес-процесс формируется объект Задача. У задач из коробки есть:

  1. Штатный реквизит Исполнена (булево).
  2. Механизм ролевой и предметной адресации (можно адресовать конкретной группе курьеров или диспетчеру).
  3. Автоматически индексируемые стандартные поля.
  4. Готовый интерфейс «Мои задачи» для пользователей.

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

Вариант 4. Индексированный реквизит в самом документе

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

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

Для получения списка нераспределенных заявок выполняем простой запрос к таблице документов:


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

Благодаря индексу СУБД мгновенно выбирает документы с нужным статусом без полного сканирования таблицы документов.

Обеспечение параллельной работы: управляемые блокировки

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

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


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ЗаявкиКРаспределению");
ЭлементБлокировки.УстановитьЗначение("Заявка", ВыбраннаяЗаявка);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();

Итоговые рекомендации по выбору архитектуры

  1. Регистр накопления с количеством 1 — наименее предпочтительный вариант из-за накладных расходов на расчет итогов и риска появления некорректных остатков при перепроведении.
  2. Индексированный реквизит документа — лучший выбор для небольших и средних систем благодаря простоте разработки и отсутствию риска рассинхронизации данных.
  3. Непериодический регистр сведений (Очередь) — оптимален для высоконагруженных систем, когда необходимо держать оперативную таблицу минимального размера.
  4. Задачи и Бизнес-процессы — лучшее решение для сложных сценариев с разделением ролей, контролем сроков и адресацией исполнителям.
← На главную