Как оптимально реализовать массовое сторнирование документов в 1С через «ОперациюБух»?

Программист 1C:Бухгалтерия Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При сопровождении учетных систем на платформе «1С:Предприятие» нередко возникает задача групповой корректировки или отмены движений за прошлые периоды. Типовой механизм сторнирования в конфигурациях, использующих документ ОперацияБух, обычно ориентирован на интерактивную работу с одним документом-основанием непосредственно в форме. Когда возникает необходимость автоматизировать ежемесячное сторнирование пачки из десятков или сотен документов, разработчик сталкивается с выбором архитектуры чтения и записи данных.

Типичная прикладная ситуация: в информационной базе присутствует нетиповой документ, формирующий записи только в два регистра — регистр бухгалтерии (например, Хозрасчетный) и один регистр накопления (например, по учету НДС). Методологическое требование состоит в создании отдельного документа ОперацияБух на каждый сторнируемый документ (соотношение строго 1:1) для сохранения прозрачности учета. Основная сложность заключается в определении наиболее эффективного способа считывания исходных движений и формирования реверсивных записей.

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

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

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

Разбор заблуждений об алгоритмической сложности

Распространенным заблуждением является стремление объединить обработку движений разнородных регистров в «один цикл» во избежание мнимой потери производительности. Если алгоритм выполняет последовательный обход выборки регистра бухгалтерии, а затем выборки регистра накопления по одному и тому же набору документов, суммарная алгоритмическая сложность остается строго линейной: O(N) + O(N) = O(N), где N — количество обрабатываемых строк.

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

Другое частое заблуждение — полный отказ от штатного метода РезультатЗапроса.Выгрузить() в пользу ручного создания пустой таблицы значений и построчного добавления строк в цикле. Метод Выгрузить() реализован на уровне платформы на компилируемом коде ядра и переносит данные в оперативную память значительно быстрее, чем интерпретируемый платформой цикл со строковыми вызовами Добавить() и заполнением свойств. Исключение составляют лишь сценарии обработки сверхбольших объемов данных (сотни тысяч строк), когда единовременная выгрузка всей таблицы может вызвать исчерпание оперативной памяти рабочего процесса (ошибку Out of Memory). Для пакетов в 50–100 документов этот фактор не актуален.

Варианты технической реализации сторнирования

Подход 1. Подокументная обработка через наборы записей

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

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

Ограничения:

Подход 2. Пакетный запрос с иерархической выборкой (рекомендуемый)

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

Далее обработка выполняется следующим образом:

Подход 3. Асинхронная очередь сторнирования

Если массовое сторнирование даже 50–100 документов начинает вызывать задержки в интерфейсе пользователей или конфликты блокировок с оперативной работой бухгалтерии, интерактивное выполнение обработки целесообразно заменить на отложенное фоновое выполнение.

Схема включает в себя:

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

Рекомендации по выбору решения

При выборе конкретного метода следует руководствоваться практическими условиями эксплуатации:

← На главную