При работе в крупных информационных базах на платформе «1С:Предприятие 8» (особенно в конфигурациях «Управление производственным предприятием 1.3», «Комплексная автоматизация 1.1» или «Управление торговлей 10.3») администраторы и разработчики часто сталкиваются с необходимостью восстановить или сдвинуть границу последовательности партионного учета. Стандартное восстановление через проведение документов может занимать часы, а иногда и дни, что парализует работу пользователей. В таких случаях возникает задача: перенести границу последовательности программно вперед, зафиксировав текущее состояние учета как корректное и избежав физического перепроведения тысяч документов.
Однако при попытке сдвинуть границу стандартным методом УстановитьГраницу() разработчики часто сталкиваются с тем, что код выполняется без ошибок, но сама граница в форме «Проведение документов» остается на прежнем месте. В этой статье мы подробно разберем, почему так происходит, как устроена логика измерений последовательностей партионного учета и какими способами можно гарантированно решить эту задачу.
В отличие от простых последовательностей взаиморасчетов, последовательности ПартионныйУчет и ПартионныйУчетБУ имеют дополнительное измерение, которое усложняет механику их работы — ПроведенВХронологическойПоследовательности (тип Булево). Рассмотрим подробнее, зачем оно нужно системе:
Истина.Ложь.В результате в базе данных образуется так называемая «интервальная» граница. Система видит, что на определенный момент времени существуют документы, которые были проведены с нарушением хронологии. Пытаясь сдвинуть границу простым указанием момента времени без учета этого флага, мы терпим неудачу, так как платформа продолжает видеть незакрытые записи со значением Ложь по конкретной организации.
Для успешного сдвига границы нам необходимо явно передать структуре отбора значение Истина для флага хронологии. Проанализируем правильный вариант формирования отбора:
МоментВремениДокумента = Новый МоментВремени(ВыбДата, ВыбСсылка);
Отбор = Новый Структура;
Отбор.Вставить("Организация", ВыбраннаяОрганизация);
Отбор.Вставить("ПроведенВХронологическойПоследовательности", Истина);
Последовательности.ПартионныйУчет.УстановитьГраницу(МоментВремениДокумента, Отбор);
Последовательности.ПартионныйУчетБУ.УстановитьГраницу(МоментВремениДокумента, Отбор);
Если мы укажем в отборе значение Ложь или вообще опустим это измерение при наличии нескольких организаций в базе данных, платформа не сможет корректно «схлопнуть» интервалы, и визуальная граница в интерфейсе не сдвинется.
Даже при использовании правильного отбора граница может оставаться на месте. Это происходит из-за существования в базе данных устаревших, поврежденных или «фантомных» записей границ последовательности (например, записей с пустой организацией или незаполненными ключевыми реквизитами). Метод УстановитьГраницу() работает строго точечно по переданному набору измерений. Если в таблице границ остаются другие наборы, общая визуальная граница последовательности будет определяться по самому раннему документу среди всех наборов измерений.
Разберем по шагам алгоритм, который позволяет гарантированно очистить все лишние ветки и установить актуальную границу:
ПолучитьГраницы().Посмотрим на пример программной реализации этого подхода:
// Выберем целевой момент времени (например, конец дня нужной даты)
ЦелевойМомент = Новый МоментВремени(КонецДня(РабочаяДата));
// Получаем все зарегистрированные границы для управленческого партионного учета
ТаблицаГраниц = Последовательности.ПартионныйУчет.ПолучитьГраницы();
Для Каждого СтрокаГраницы Из ТаблицаГраниц Цикл
// Формируем структуру отбора на основании реальных данных из таблицы границ
СтруктураОтбора = Новый Структура;
// Динамически заполняем измерения последовательности
Для Каждого Колонка Из ТаблицаГраниц.Колонки Цикл
Если Колонка.Имя <> "МоментВремени" Тогда
СтруктураОтбора.Вставить(Колонка.Имя, СтрокаГраницы[Колонка.Имя]);
КонецЕсли;
КонецЦикла;
// Если в базе есть записи с флагом Ложь, принудительно меняем его на Истина для закрытия интервала
Если СтруктураОтбора.Свойство("ПроведенВХронологическойПоследовательности") Тогда
СтруктураОтбора.ПроведенВХронологическойПоследовательности = Истина;
КонецЕсли;
// Устанавливаем границу для текущего набора измерений
Последовательности.ПартионныйУчет.УстановитьГраницу(ЦелевойМомент, СтруктураОтбора);
КонецЦикла;
Этот способ является наиболее надежным, так как он гарантирует, что ни одно «забытое» измерение (например, по давно удаленной или помеченной на удаление организации) не потянет общую границу назад в прошлое.
Если вам необходимо решить эту задачу разово и вы не хотите писать внешнюю обработку, обратите внимание на штатные возможности конфигураций:
УстановкаГраницыПоследовательностиПартионногоУчета. Она позволяет сдвинуть границу без запуска непосредственного перепроведения документов.Право интерактивного переноса границы последовательности.При работе с границами последовательностей важно помнить об архитектурных особенностях платформы «1С:Предприятие». Таблица границ последовательности — это высоконагруженный разделяемый ресурс.
Ни в коем случае не выполняйте программную установку границ внутри транзакции проведения документов (например, в обработчиках событий ОбработкаПроведения или в подписках на события, выполняющихся в транзакции записи). Если несколько пользователей будут одновременно проводить документы и ваш код попытается программно сдвинуть границу для одной и той же организации, это гарантированно приведет к ошибкам взаимной блокировки данных (Deadlocks) и аварийному завершению сеансов пользователей.
Рекомендуется выполнять любые операции по ручному или программному сдвигу границ последовательностей монопольно, либо в периоды минимальной активности пользователей (ночью) с использованием регламентных заданий.