В практике разработки на платформе 1С:Предприятие часто возникает ситуация, когда механизмы последовательностей ведут себя не так, как ожидается от стандартных настроек метаданных. Казалось бы, если документ не указан в составе последовательности, он не должен на нее влиять. Однако на практике граница последовательности (ГП) может «улетать» вперед или сдвигаться назад при проведении совершенно сторонних документов. В этой статье мы подробно разберем, почему это происходит, и как найти «виновника» в программном коде.
Первое, что нам необходимо осознать: платформа 1С предоставляет разработчику возможность управлять границей последовательности вручную. Если в метаданных документа не стоит галочка о вхождении в последовательность, это лишь означает, что платформа автоматически не будет регистрировать этот документ в таблице регистрации последовательности. Но это не запрещает программному коду принудительно изменить состояние границы.
Разберем основной метод, который используется для этих целей: Последовательности[ИмяПоследовательности].УстановитьГраницу(). Рассмотрим пример кода, который может скрываться в недрах конфигурации:
// Пример программной установки границы
Граница = Новый Граница(ДокументСсылка.МоментВремени(), ГраницаТип.Включая);
Последовательности.МояПоследовательность.УстановитьГраницу(Граница, Новый Структура("Организация", ДокументОбъект.Организация));
Если такой код вызывается в модуле документа, который формально не входит в последовательность, граница все равно будет перемещена. Проанализируем ситуацию: зачем это может быть нужно? Часто это делается в самописных решениях для того, чтобы «подтянуть» последовательность при вводе исторических данных или при выполнении регламентных операций, которые должны считаться «финальной точкой» актуальности данных.
Проанализируем структуру конфигурации. В современных решениях (особенно использующих БСП) логика проведения часто выносится из модулей документов в Подписки на события. Посмотрим на объект ОбщаяПодпискаНаСобытие. Если существует подписка на событие ОбработкаПроведения, в качестве источника которой указан тип ДокументОбъект (или большой список документов), то код внутри обработчика этой подписки будет выполняться для каждого документа в системе.
Выясним причину влияния через подписку. Внутри обработчика может стоять универсальный вызов:
Процедура ПриПроведенииДокументаДляПоследовательности(Источник, Отказ, РежимПроведения) Экспорт
// Логика может проверять наличие определенных движений по регистрам
// и, если они есть, двигать границу конкретной последовательности
Если Источник.Движения.Хозрасчетный.Количество() > 0 Тогда
Последовательности.ПартионныйУчет.УстановитьГраницу(Источник.МоментВремени());
КонецЕсли;
КонецПроцедуры
В этом случае документ может даже не «знать» о существовании последовательности, но глобальный механизм контроля будет двигать ГП при каждом его проведении.
Последовательность в 1С тесно связана с регистрами. Если документ (даже не входящий в последовательность) делает записи в регистр накопления или сведений, который является «контрольным» для этой последовательности, это может инициировать пересчет. Хотя сама платформа редко двигает ГП для «чужих» документов без команды, в типовых или сложных самописных решениях часто реализуется механизм автоматической актуализации.
Рассмотрим подробнее: если ваша последовательность имеет измерения (например, Организация), то граница хранится в разрезе каждого значения этого измерения. Если сторонний документ меняет данные по этой организации в связанных регистрах, программный код может быть настроен так, чтобы сбрасывать границу назад или, наоборот, считать данные актуальными на момент этого документа.
Чтобы разобраться, какой именно механизм двигает вашу последовательность, пройдем по следующим шагам:
Ctrl+Shift+F и введите имя вашей последовательности. Ищите все вхождения, особенно те, где используются методы УстановитьГраницу или Записать..Границы (обращение к таблице границ последовательности).ОбработкаПроведения и ПередЗаписью. Проверьте программный код их обработчиков.Последовательности.Нужно учитывать, что если у последовательности заданы измерения, то вызов метода УстановитьГраницу без указания отбора по измерениям может привести к непредсказуемому поведению (сбросу границ по всем организациям сразу или, наоборот, к ошибке). Проанализируем пример правильной установки границы с учетом измерений:
Отбор = Новый Структура;
Отбор.Вставить("Организация", СсылкаНаОрганизацию);
Отбор.Вставить("Склад", СсылкаНаСклад);
Момент = Новый МоментВремени(ДатаДокумента, СсылкаНаДокумент);
Последовательности.УчетТоваров.УстановитьГраницу(Момент, Отбор);
Резюмируем: Если документ, не входящий в последовательность, двигает ее границу — ищите программный вызов УстановитьГраницу в модулях этого документа, в подписках на события или в общих модулях, отвечающих за проведение. Платформа сама по себе (на уровне ядра) не добавляет «чужие» документы в механизм автоматического перемещения ГП, это всегда результат работы кода разработчика.