Вопрос восстановления последовательности документов — одна из классических задач в 1С:Предприятии, особенно когда речь идет о складском учете или расчетах с контрагентами в конфигурациях вроде «Бухгалтерия предприятия» или «ERP». Часто начинающие разработчики пытаются реализовать этот механизм через обычный перебор документов в цикле, что приводит к ошибкам или неоптимальной работе системы. В этой статье мы подробно разберем, как правильно подойти к этой задаче, проанализируем типичные ошибки и рассмотрим программные методы управления последовательностями.
Прежде чем переходить к коду, давайте выясним причину, по которой ручное перепроведение документов в произвольном порядке не является «восстановлением последовательности». Суть последовательности заключается в строгом хронологическом порядке. Если мы сначала проведем Реализацию от 14:00, а затем Поступление от 10:00 того же дня, остатки могут рассчитаться некорректно, и граница последовательности (точка, до которой учет считается верным) не сдвинется вперед.
Рассмотрим распространенную ошибку, которую часто совершают разработчики. Попытка вызвать метод Восстановить() внутри цикла по выборке документов является методологически неверной:
// ОШИБОЧНЫЙ ПОДХОД
Пока Выборка.Следующий() Цикл
Момент = Новый МоментВремени(Выборка.Дата, Выборка.Ссылка);
Последовательности.ДокументыОрганизаций.Восстановить(Момент);
ДокументОбъект = Выборка.Ссылка.ПолучитьОбъект();
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецЦикла;
В чем здесь ошибка? Метод Восстановить() сам по себе является итератором. При его вызове платформа автоматически находит самый старый документ, нарушивший последовательность, перепроводит его и сдвигает «Границу». Если мы вызываем его в своем цикле, мы фактически заставляем систему выполнять двойную работу и нарушаем логику работы встроенных механизмов 1С.
Самый простой и правильный способ программного восстановления — позволить платформе самой управлять процессом. Рассмотрим, как это сделать. Для этого нам не нужно делать запрос к документам, нам нужно лишь указать «конечную точку», до которой мы хотим актуализировать данные.
Проанализируем пример кода для восстановления последовательности до текущего момента времени:
Процедура ВосстановитьПоследовательностьПрограммно(ОрганизацияСсылка)
// Создаем отбор, если последовательность разделена по измерениям (например, по Организации)
СтруктураОтбора = Новый Структура;
СтруктураОтбора.Вставить("Организация", ОрганизацияСсылка);
// Получаем текущую границу, чтобы понимать масштаб проблемы (необязательно)
ТекущаяГраница = Последовательности.ДокументыОрганизаций.ПолучитьГраницу(СтруктураОтбора);
// Восстанавливаем до текущего момента.
// Если передать Неопределено, будет восстановлено всё до самого последнего документа.
Последовательности.ДокументыОрганизаций.Восстановить(Неопределено, СтруктураОтбора);
Сообщить("Восстановление завершено");
КонецПроцедуры
При таком подходе платформа сама найдет все документы, входящие в последовательность ДокументыОрганизаций, и будет проводить их по одному, пока граница не достигнет актуального состояния. Это гарантирует, что каждый последующий документ «видит» корректные движения предыдущего.
Иногда требуется более тонкий контроль (например, если нужно перепроводить только определенные типы документов или добавлять специфическую логику). В этом случае мы пишем запрос вручную. Разберем по шагам, на что обратить внимание.
Важнейшее правило: Сортировка в запросе должна быть строго по Дата и Ссылка. В 1С МоментВремени — это комбинация времени и уникального идентификатора. Если несколько документов созданы в одну и ту же секунду, только сортировка по ссылке обеспечит стабильный и правильный порядок проведения.
ТекстЗапроса =
"ВЫБРАТЬ
| Док.Ссылка КАК Ссылка,
| Док.Дата КАК Дата
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док
|ГДЕ
| Док.Проведен И Док.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Док.Ссылка,
| Док.Дата
|ИЗ
| Документ.ПоступлениеТоваровУслуг КАК Док
|ГДЕ
| Док.Проведен И Док.Дата МЕЖДУ &ДатаНачала И &ДатаКонца
|
|УПОРЯДОЧИТЬ ПО
| Дата,
| Ссылка"; // Критически важная сортировка
После получения такой выборки мы проводим документы в цикле. Однако помните: при ручном проведении платформа может автоматически НЕ двигать границу последовательности, если в свойствах документа отключено «Заполнение последовательностей» или стоит режим «Не заполнять автоматически».
Выясним, как управлять «флажком» актуальности без перепроведения самих документов. Для этого используются методы ПолучитьГраницу и УстановитьГраницу.
МоментВремени, указывающий на первый документ, после которого последовательность нарушена.Рассмотрим пример «перепрыгивания» периода:
// Установим границу на начало текущего года, считая, что прошлый год закрыт верно
НужныйМомент = Новый МоментВремени(НачалоГода(ТекущаяДата()));
Отбор = Новый Структура("Организация", ВыбраннаяОрганизация);
Последовательности.ДокументыОрганизаций.УстановитьГраницу(НужныйМомент, Отбор);
Проанализируем ситуацию, упомянутую в обсуждении: почему в «Бухгалтерии предприятия 3.0» у последовательности часто не указаны регистры в метаданных?
В современных конфигурациях используется механизм «входящих документов». Это означает, что последовательность контролирует сам факт записи документа, входящего в её состав, независимо от того, по каким регистрам он делает движения. Кроме того, в БП 3.0 часто используются программные интерфейсы (общие модули), которые управляют состоянием учета через задания закрытия месяца. Если вы работаете с БП 3.0, рекомендуется изучить возможности общего модуля ОбщегоНазначенияБП, который содержит процедуры для проверки актуальности учета.
Восстановление последовательности — тяжелая операция. Проанализируем основные риски:
Восстановить() система блокирует таблицу последовательности. Другие пользователи не смогут проводить документы, входящие в эту же последовательность.ОбменДанными.Загрузка = Истина, но помните, что это отключает и программные проверки в модуле документа.В завершение отметим, что для глубокого понимания работы этого механизма полезно изучить видеоуроки (например, курсы Павла Чистова), где наглядно показывается, как перемещение границы влияет на итоги в регистрах накопления. Правильное использование МоментВремени и штатных методов Последовательности избавит вас от множества проблем с актуальностью данных в 1С.