В процессе работы с базами данных «1С:Предприятие» (особенно в крупных конфигурациях, таких как «Бухгалтерия предприятия 3.0», «ERP Управление предприятием» или «Комплексная автоматизация») пользователи часто сталкиваются с неприятной ситуацией. Стоит случайно открыть документ прошлых периодов, нажать кнопку «Записать» или «Провести» без фактического изменения данных, как вся последовательность проведения документов «слетает». Граница последовательности сдвигается назад, а система начинает требовать масштабного перепроведения документов за несколько месяцев, а то и лет.
Фактическое перепроведение документов «задним числом» — это всегда огромный риск. Во-первых, оно может исказить уже сданную отчетность и изменить копейки в расчетах из-за округлений. Во-вторых, этот процесс на больших базах данных может занимать часы или даже дни, парализуя работу пользователей. В этой статье мы подробно разберем, как исправить состояние проведения конкретного документа в последовательности программным путем, не прибегая к полному перепроведению.
Начинающие разработчики часто пытаются решить проблему «в лоб», используя стандартные методы работы с последовательностями. Рассмотрим, почему классические подходы могут не дать ожидаемого результата:
Последовательности.ДокументыОрганизаций.УстановитьГраницу() позволяет жестко сдвинуть общую границу последовательности на определенный момент времени. Однако в современных конфигурациях этот метод не изменяет статус «Проведен с нарушением последовательности» внутри формы самого документа, так как логика контроля стала более детализированной.Последовательности.ДокументыОрганизаций.Восстановить() запускает реальное проведение документов по цепочке, что возвращает нас к проблеме длительного ожидания и риска изменения проводок.Выясним причину такого поведения. В современных версиях платформы и конфигурациях на базе БСП (Библиотеки стандартных подсистем) учет последовательностей оптимизирован. Чтобы не блокировать базу данных при многопользовательской работе, система не просто хранит единую «точку» границы, а регистрирует состояние каждого конкретного документа в специальной таблице последовательности. Каждая запись имеет измерение СостояниеПроведения, которое может принимать значения из перечисления СостоянияПроведенияВПоследовательности (например, «Проведен в последовательности» или «Проведен с нарушением последовательности»).
Следовательно, для решения нашей задачи нам необходимо точечно перезаписать состояние конкретного документа в самой таблице последовательности.
Проанализируем ситуацию: нам нужно изменить запись в таблице последовательности, подчиненной конкретному регистратору (документу). Работа с последовательностью в данном случае очень похожа на работу с подчиненными регистрами сведений или накопления. В качестве основного отбора нам обязательно нужно использовать отбор по регистратору.
Ниже приведен готовый шаблон кода, который позволяет программно перевести статус документа в положение «Проведен в последовательности» без совершения проводок и изменения данных самого документа:
// Определим документ, статус которого необходимо исправить
ДокументРегистратор = СсылкаНаНашДокумент;
// Создаем набор записей для нужной последовательности
НаборЗаписей = Последовательности.ДокументыОрганизаций.СоздатьНаборЗаписей();
// Устанавливаем обязательный отбор по регистратору
НаборЗаписей.Отбор.Регистратор.Установить(ДокументРегистратор);
// Читаем текущие записи из базы данных
НаборЗаписей.Прочитать();
// Если запись уже существует, корректируем ее параметры
Если НаборЗаписей.Количество() > 0 Тогда
Для Каждого Запись Из НаборЗаписей Цикл
// Дополнительно можно проверить организацию или другие измерения
Если Запись.Организация = ДокументРегистратор.Организация Тогда
Запись.СостояниеПроведения = Перечисления.СостоянияПроведенияВПоследовательности.ПроведенВПоследовательности;
КонецЕсли;
КонецЦикла;
Иначе
// Если записи в последовательности не было, создаем новую
НоваяРегистрация = НаборЗаписей.Добавить();
НоваяРегистрация.Регистратор = ДокументРегистратор;
НоваяРегистрация.Период = ДокументРегистратор.Дата;
НоваяРегистрация.Организация = ДокументРегистратор.Организация;
НоваяРегистрация.СостояниеПроведения = Перечисления.СостоянияПроведенияВПоследовательности.ПроведенВПоследовательности;
КонецЕсли;
// Записываем набор записей с замещением существующих данных
НаборЗаписей.Записать(Истина);
Важное примечание: Если документ был полностью распроведен пользователем, и его необходимо вообще исключить из последовательности, мы можем просто очистить движения по нему в этой таблице. Для этого достаточно записать пустой набор с установленным отбором:
НаборЗаписей = Последовательности.ДокументыОрганизаций.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Registrator.Установить(ДокументРегистратор);
НаборЗаписей.Записать(Истина); // Запись пустого набора удалит движения
Часто после успешного выполнения кода из первого решения разработчики замечают, что обработка «Закрытие месяца» все равно продолжает гореть красным цветом и настойчиво требовать перепроведения документов. Почему так происходит?
В современных конфигурациях 1С состояние закрытия периода контролируется не только основной последовательностью, но и специальным вспомогательным регистром сведений. Он называется РегистрСведений.НеактуальныеРегламентныеОперации. Когда документ проводится «задним числом», система делает запись в этот регистр, помечая операции закрытия месяца как неактуальные.
Для того чтобы полностью восстановить статус закрытого периода без реального перепроведения, нам необходимо очистить записи по проблемной организации за затронутый период времени в этом регистре. Рассмотрим пример кода:
ОрганизацияДокумента = ДокументРегистратор.Организация;
ПериодДокумента = НачалоМесяца(ДокументРегистратор.Дата);
// Создаем набор записей регистра неактуальных операций
НаборРегламентных = РегистрыСведений.НеактуальныеРегламентныеОперации.СоздатьНаборЗаписей();
// Устанавливаем отборы по организации и периоду (месяцу)
НаборРегламентных.Отбор.Организация.Установить(ОрганизацияДокумента);
НаборРегламентных.Отбор.Период.Установить(ПериодДокумента);
// Записываем пустой набор записей, чтобы удалить признак неактуальности
НаборРегламентных.Записать(Истина);
После выполнения этой несложной процедуры обработка «Закрытие месяца» снова станет зеленой, а статус актуальности восстановится.
Рассмотрим альтернативный вариант. Фирма «1С» предусмотрела штатную возможность обхода этой проблемы прямо в пользовательском интерфейсе (доступно в «Бухгалтерии предприятия», начиная с релиза 3.0.62.17). Этот способ идеально подходит, если изменения в документе действительно были незначительными (например, вы просто изменили текстовый комментарий, договор для информации или номер входящего документа, что заведомо не влияет на проводки и взаиморасчеты).
Разберем этот алгоритм по шагам:
Обратите внимание: Данная команда доступна далеко не всем пользователям. Для ее выполнения необходимо обладать полными (административными) правами или иметь назначенную роль Право интерактивного переноса границы последовательности. Это сделано в целях безопасности, чтобы рядовые бухгалтеры не могли случайно нарушить логику партионного или налогового учета.
Мы подробно разобрали три эффективных метода корректировки последовательности документов. При выборе решения всегда оценивайте характер изменений в документе: