Как сохранить историю изменений в периодическом регистре сведений при проведении документа в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие программисты часто сталкиваются с задачей ведения истории изменения каких-либо состояний объектов. Классический пример — история изменения статусов документов (например, договоров, заявок или дел по просроченной задолженности). Естественным желанием начинающего разработчика является создание периодического регистра сведений, подчиненного документу-регистратору, с записью движений непосредственно при проведении этого документа.

Однако при попытке реализовать это «в лоб» разработчик сталкивается с неприятным поведением платформы: при каждом повторном проведении документа старые записи по этому регистратору бесследно исчезают, а в регистре остается только одна, самая последняя строка. Изменение свойств проведения документа (например, отключение автоматического удаления движений) не приносит желаемого результата.

В этой статье мы подробно разберем, почему платформа 1С ведет себя именно так, выясним причину такого поведения и рассмотрим три архитектурно верных способа решения этой задачи, которые применяются в профессиональной разработке.

---

Почему платформа перезаписывает движения? Разбор механики 1С

Для того чтобы понять суть проблемы, нам необходимо проанализировать логику работы платформы 1С с подчиненными регистрами. Когда регистр сведений имеет режим записи «Подчинение регистратору», его жизненный цикл становится жестко связанным с транзакционным циклом документа-регистратора.

Каждый раз, когда пользователь проводит или перезаписывает документ с формированием движений, платформа выполняет следующие действия:

  1. В рамках транзакции проведения полностью очищается таблица движений данного конкретного документа (регистратора) в этом регистре сведений.
  2. Вызывается процедура-обработчик ОбработкаПроведения в модуле объекта документа.
  3. В этой процедуре формируются новые движения (набор записей).
  4. Новый сформированный набор записей записывается в базу данных с замещением старого.

Даже если вы зайдете в свойства документа на вкладку «Движения» и установите свойство «Удаление движений» в значение «Не удалять автоматически», это не решит проблему накопления истории. При вызове метода Движения.Записать() (или при автоматической записи движений платформой по окончании проведения) коллекция движений этого документа по регистру будет перезаписана целиком. Платформа 1С проектировалась исходя из концепции, что документ — это однократное событие в физическом времени, а не процесс, растянутый во времени. Документ должен фиксировать хозяйственную операцию в определенный момент времени, и его движения обязаны строго соответствовать реквизитам документа на этот момент.

Попытка использовать один и тот же документ в качестве регистратора для накопления истории его собственного жизненного цикла противоречит логике платформы. Если вам необходимо хранить историю изменения статусов одного объекта, следует использовать другие подходы. Ниже мы разберем три лучших решения.

---

Решение 1. Использование независимого регистра сведений (Рекомендуемый способ)

Если вам нужно просто и быстро организовать хранение истории изменения статусов без создания дополнительных документов, использование независимого регистра сведений — это лучший выбор.

Проанализируем этот подход по шагам:

  1. Настройка регистра сведений:
    • Установите режим записи регистра в значение Независимый.
    • Сделайте регистр периодическим (например, с периодичностью В пределах секунды).
    • Создайте измерение Дело (или любой другой ваш объект) с типом ссылки на ваш документ.
    • Критически важно: установите для измерения Дело свойство Ведущее. Это гарантирует, что при удалении документа из базы данных платформа автоматически очистит все связанные записи в регистре сведений, предотвращая появление «битых» ссылок и сохраняя ссылочную целостность СУБД.
    • Создайте ресурс СтатусДела (например, тип — перечисление или справочник).
  2. Реализация записи данных:

    Запись в независимый регистр сведений должна выполняться вне транзакции проведения. Писать в независимые регистры из процедуры ОбработкаПроведения крайне не рекомендуется, так как это может приводить к избыточным блокировкам базы данных и нарушению логики проведения. Лучшим местом для этого является обработчик события ПриЗаписи в модуле объекта документа.

Рассмотрим пример кода, который необходимо разместить в модуле объекта вашего документа:


Процедура ПриЗаписи(Отказ)
    
    // Предотвращаем выполнение кода при обмене данными или если запись отменена
    Если ОбменДанными.Загрузка Или Отказ Тогда
        Возврат;
    КонецЕсли;
    
    // Нам нужно записывать статус только в том случае, если он действительно изменился.
    // Для этого можно сравнить текущее значение реквизита со значением в базе данных.
    СсылкаНаБазу = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Ссылка, "СтатусДела");
    
    Если СсылкаНаБазу.СтатусДела <> СтатусДела Тогда
        
        // Создаем менеджер записи для работы с одной строкой независимого регистра
        МенеджерЗаписи = РегистрыСведений.СтатусыДелОПросроченнойЗадолженности.СоздатьМенеджерЗаписи();
        
        // Заполняем ключевые поля (период и измерения)
        МенеджерЗаписи.Период = ТекущаяДата();
        МенеджерЗаписи.Дело = Ссылка;
        
        // Заполняем ресурсы и реквизиты
        МенеджерЗаписи.СтатусДела = СтатусДела;
        МенеджерЗаписи.Пользователь = ПараметрыСеанса.ТекущийПользователь;
        
        Попытка
            // Истина означает замещение записи, если на эту же секунду уже существует запись
            МенеджерЗаписи.Записать(Истина);
        Исключение
            ЗаписьЖурналаРегистрации("РегистрацияСтатуса", УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
            Отказ = Истина;
        КонецПопытки;
        
    КонецЕсли;

КонецПроцедуры

Используя этот метод, при каждом изменении реквизита СтатусДела в формуляр документа и последующем сохранении в регистр будет добавляться новая строка с актуальным временем, именем пользователя и новым статусом, при этом старые записи за прошлые периоды останутся нетронутыми.

---

Решение 2. Использование отдельных документов-регистраторов (Стандарт типовых конфигураций)

Этот метод является стандартом для крупных корпоративных систем на платформе 1С (ERP, КА, УТ). Он применяется тогда, когда смена статуса сама по себе является важным бизнес-событием, требующим согласования, указания дополнительных аналитик или фиксации ответственных лиц.

Рассмотрим структуру этого решения:

Разберем преимущества данного подхода:

  1. Аудит и ответственность: Каждый документ-регистратор имеет своего автора, дату создания и проведения. Всегда можно четко отследить, на основании какого именно документа изменился статус.
  2. Простота отмены изменений: Если статус был установлен ошибочно, пользователю достаточно просто отменить проведение документа установки статуса. Платформа 1С автоматически очистит его движения в регистре, и система вернется к предыдущему актуальному статусу. В случае с независимым регистром разработчику пришлось бы вручную писать сложный код удаления строки.

---

Решение 3. Использование платформенного механизма «История данных»

Если ваша задача состоит исключительно в аудите изменений (выяснить, кто, когда и какой статус установил) и эти данные не требуются для использования в тяжелых запросах, динамических списках или для логики проведения других документов, создавать регистр вообще не нужно.

Начиная с версии платформы 8.3.11, в 1С доступен мощный встроенный механизм «История данных» (версионирование на уровне платформы). Чтобы задействовать его, выполните следующие шаги:

  1. Откройте свойства вашего документа в конфигураторе.
  2. Перейдите на вкладку «История данных» и установите значение свойства в Использовать.
  3. Для реквизита СтатусДела убедитесь, что версионирование также включено.

После этого платформа автоматически при каждом сохранении документа будет записывать его версию в специальную системную таблицу. Пользователи смогут просматривать всю историю изменения полей документа (включая автора изменений, дату и старые/новые значения статусов) через стандартную команду «История изменений» непосредственно на форме документа.

---

Резюме

Выбор конкретного метода зависит от требований к вашей системе:

← На главную