Как правильно реализовать изменение данных в одном документе при проведении другого?

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

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

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

Проблема прямой модификации и технические риски

Рассмотрим ситуацию, когда мы используем метод ПолучитьОбъект() и Записать() для изменения анкеты прямо в коде проведения ведомости. Почему это плохо? Проанализируем основные причины:

  1. Взаимоблокировки (Deadlocks): Когда документ «Экзаменационная ведомость» начинает транзакцию проведения, он блокирует себя в базе данных. Пытаясь записать «Анкету», он накладывает блокировку и на неё. Если в это же время другой процесс попытается выполнить обратное действие или просто изменить анкету, система может войти в состояние бесконечного ожидания, которое закончится аварийным завершением транзакции.
  2. Целостность данных при отмене проведения: Если пользователь ошибся и нажал «Отмена проведения» в ведомости, статус в анкете останется измененным («Отозвано»). Вам придется писать сложную и ненадежную логику в процедуре ОбработкаУдаленияПроведения, чтобы попытаться вернуть «как было».
  3. Производительность: Каждая запись объекта — это тяжелая операция. Если в ведомости 100 абитуриентов, система будет вынуждена 100 раз открывать и записывать тяжелые объекты документов, что катастрофически замедлит работу.

Рекомендуемое решение: Использование периодических регистров сведений

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

Вместо того чтобы хранить статус «Подано/Отозвано» в табличной части документа АнкетаАбитуриента, мы создадим регистр СтатусыЗаявлений. Это позволит нам не менять документы «прошлого», а просто фиксировать новое событие в истории.

Шаг 1. Настройка регистра:

Создадим регистр сведений со следующими параметрами:

Шаг 2. Запись данных из документов:

Теперь документ Анкета при проведении будет делать запись в этот регистр со статусом Подано. А документ ЭкзаменационнаяВедомость при проведении создаст новую запись с тем же набором измерений, но со статусом НеПрошел (или Отозвано).

Проанализируем пример кода в процедуре ОбработкаПроведения для документа ЭкзаменационнаяВедомость:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    
    // Удаляем старые записи по этому регистратору, чтобы избежать дублирования
    Движения.СтатусыЗаявлений.Записывать = Истина;
    Движения.СтатусыЗаявлений.Очистить();
    
    Для Каждого СтрокаВедомости Из ТабличнаяЧастьЭкзамены Цикл
        Если СтрокаВедомости.Результат = Перечисления.РезультатыЭкзамена.НеСдал Тогда
            
            НоваяЗапись = Движения.СтатусыЗаявлений.Добавить();
            НоваяЗапись.Период = Дата;
            НоваяЗапись.Абитуриент = СтрокаВедомости.Абитуриент;
            НоваяЗапись.КонкурснаяГруппа = СтрокаВедомости.КонкурснаяГруппа;
            НоваяЗапись.Статус = Перечисления.СтатусыЗаявлений.Отозвано;
            
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

При такой схеме, если ведомость будет отменена, запись в регистре исчезнет автоматически, и система снова будет «видеть» предыдущий актуальный статус, записанный анкетой.

Как получать актуальные данные в отчетах и других документах

Теперь, когда данные хранятся в регистре, нам не нужно искать их в анкете. Для формирования документа РейтингАбитуриентов или любого отчета мы будем использовать виртуальную таблицу СрезПоследних. Рассмотрим, как составить запрос, который выберет только тех, кто успешно сдал экзамены.

Разберем пример запроса:


ВЫБРАТЬ
    СтатусыСрезПоследних.Абитуриент КАК Абитуриент,
    СтатусыСрезПоследних.Статус КАК ТекущийСтатус
ИЗ
    РегистрСведений.СтатусыЗаявлений.СрезПоследних(&ДатаРейтинга, ) КАК СтатусыСрезПоследних
ГДЕ
    СтатусыСрезПоследних.Статус <> ЗНАЧЕНИЕ(Перечисление.СтатусыЗаявлений.Отозвано)

Этот подход гарантирует, что вы всегда работаете с самой свежей информацией, не перегружая базу данных лишними операциями записи документов.

Использование подписок на события

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

Создадим объект ПодпискаНаСобытие:

В обработчике мы реализуем ту же логику записи в регистр. Это делает систему более гибкой: если завтра появится новый документ «Апелляция», который тоже должен влиять на статус, мы просто добавим его в источники этой же подписки.

Визуализация статуса в форме документа

Часто возникает вопрос: «Но как пользователь увидит статус в самой анкете, если мы его там не сохраняем?». Решение очень простое — динамическое отображение.

Выясним, как это сделать программно: В форме документа АнкетаАбитуриента в обработчике ПриЧтенииНаСервере или ПриСозданииНаСервере можно выполнить быстрый запрос к регистру сведений и вывести результат в декорацию (надпись) или в реквизит формы, не связанный с данными объекта. Таким образом, пользователь всегда видит актуальное состояние, а база данных остается стройной и производительной.

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

← На главную