В процессе сопровождения крупных информационных баз на платформе 1С:Предприятие 8 часто возникают ситуации, когда необходимо исправить ошибки в учете только по одному конкретному регистру накопления. Стандартное перепроведение документа (через метод Записать(РежимЗаписиДокумента.Проведение)) в таких случаях неэффективно: оно инициирует выполнение всего кода в процедуре ОбработкаПроведения, что затрагивает все связанные регистры, вызывает многочисленные проверки и требует колоссальных временных затрат. Разберем механизмы, которые позволяют обновить движения только по одному выбранному регистру, сохранив целостность остальных данных и значительно ускорив процесс.
В 1С документ является регистратором для наборов записей различных регистров. Чтобы изменить движения, нам не обязательно открывать сам документ как объект. Мы можем работать напрямую с объектом НаборЗаписей конкретного регистра. Проанализируем, почему этот метод является наиболее быстрым и безопасным.
Когда мы работаем через НаборЗаписей, система не выполняет код модуля документа. Она лишь открывает транзакцию на запись в конкретную таблицу базы данных. Это позволяет избежать блокировок по другим таблицам и исключить выполнение лишних вычислений. Для интерактивного изменения таких записей без написания кода можно использовать обработку для редактирования движений документа.
Рассмотрим по шагам, как реализовать программное обновление движений для конкретного документа и регистра.
Шаг 1. Создание набора записей и установка отбора.
Для начала необходимо создать объект набора записей регистра и ограничить его только данными нашего документа-регистратора. Рассмотрим пример кода:
// Создаем набор записей для нужного регистра
Набор = РегистрыНакопления.ИмяВашегоРегистра.СоздатьНаборЗаписей();
// Обязательно устанавливаем отбор по регистратору
Набор.Отбор.Регистратор.Установить(СсылкаНаДокумент);
Шаг 2. Формирование новых данных.
Здесь у нас есть два пути: либо полностью очистить движения (вызвав метод Записать() у пустого набора), либо заполнить его новыми данными. Для формирования новых записей проанализируем данные документа. Чтобы не тратить время на чтение всего объекта, рекомендуется использовать запрос к табличным частям документа.
// Пример заполнения набора новыми записями
Для Каждого СтрокаТЧ Из ТаблицаДанныхДокумента Цикл
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Период = ДатаДокумента;
НоваяЗапись.Регистратор = СсылкаНаДокумент;
НоваяЗапись.ВидДвижения = ВидДвиженияНакопления.Приход;
НоваяЗапись.Номенклатура = СтрокаТЧ.Номенклатура;
НоваяЗапись.Количество = СтрокаТЧ.Количество;
КонецЦикла;
Шаг 3. Запись набора с оптимизацией.
Для максимального ускорения процесса и обхода лишних проверок (например, подписок на события), используем свойство ОбменДанными.Загрузка.
Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать(Истина); // Параметр Истина означает замещение существующих записей
Если задача требует регулярного обновления движений (например, раз в месяц при корректировке источников происхождения), проанализируем архитектурный подход к организации кода. Постоянно дублировать логику формирования движений во внешних обработках — плохая практика. Разберем два более правильных способа:
СформироватьДвиженияПоРегиструХ() в модуле самого документа. Тогда из обработки нам достаточно будет получить объект и вызвать эту процедуру, после чего записать только конкретную коллекцию из свойства Движения.Посмотрим на пример вызова через объект документа:
ОбъектДок = СсылкаНаДокумент.ПолучитьОбъект();
// Вызываем процедуру, которая заполняет Движения.ИмяРегистра, но не записывает их
ОбъектДок.СформироватьДвиженияПоНужномуРегистру();
// Записываем только этот регистр
ОбъектДок.Движения.ИмяРегистра.Записать(Истина);
Выясним, как ускорить процесс, если нам нужно перепровести тысячи документов по одному регистру. Основная нагрузка при записи наборов идет на транзакции СУБД. Чтобы минимизировать издержки, воспользуемся следующими правилами:
НачатьТранзакцию() и ЗафиксироватьТранзакцию(). Это сократит количество обращений к диску.Ссылка.ПолучитьОбъект() — тяжелая операция. Если структура движений позволяет, соберите данные по всем нужным документам одним большим запросом, а затем в цикле создавайте и записывайте наборы записей.Несмотря на высокую скорость, "фрагментарное" проведение несет в себе риски нарушения логической целостности базы. Проанализируем критические моменты:
Риск 1: Рассинхронизация данных.
В типовых конфигурациях многие регистры взаимосвязаны. Например, "Продажи" и "НДС Продажи". Если вы обновите один и не тронете другой, отчеты могут начать показывать противоречивые данные. Всегда проверяйте, не является ли исправляемый регистр базой для расчетов в других подсистемах.
Риск 2: Флаги актуальности.
В конфигурациях на обычных формах (УТ 10.3) часто используются реквизиты вроде Проведен или специфические флаги в дополнительных свойствах. Программная запись набора записей не меняет статус документа. Если пользователь позже вручную перепроведет документ из формы, ваши программно внесенные правки будут затерты стандартным алгоритмом проведения.
Риск 3: Блокировки.
Даже при записи одного регистра 1С накладывает блокировки. Если во время вашей обработки пользователи будут пытаться проводить те же документы штатными средствами, могут возникнуть конфликты блокировок (Deadlock). Рекомендуется выполнять такие операции в периоды минимальной активности пользователей.
Подведем итог: использование объекта НаборЗаписей с установленным отбором по регистратору — это мощный инструмент для "хирургического" вмешательства в данные учета. Он обеспечивает максимальную скорость за счет исключения лишнего кода и минимизации работы с объектами метаданных, однако требует от разработчика четкого понимания структуры связей в конкретной конфигурации. При необходимости массовой правки данных без создания собственных процедур можно использовать редактор записей регистров накопления с помощником групповых изменений.