В практике разработки на платформе 1С:Предприятие 8 часто возникает задача: при отмене проведения документа необходимо зафиксировать какие-либо данные в регистре сведений. Однако многие программисты сталкиваются с ситуацией, когда код записи набора записей выполняется без ошибок, отладчик показывает наличие данных в наборе, но после завершения транзакции записи в регистре бесследно исчезают. Проанализируем, почему это происходит, и разберем способы решения этой задачи.
Рассмотрим типичную ситуацию. Программист пишет код в модуле объекта документа внутри процедуры ОбработкаУдаленияПроведения. Цель — записать данные в подчиненный регистр сведений, используя стандартный механизм наборов записей. Пример кода может выглядеть следующим образом:
НаборДвижения = РегистрыСведений.МойРегистр.СоздатьНаборЗаписей();
НаборДвижения.Отбор.Регистратор.Установить(ЭтотОбъект.Ссылка);
// Заполнение набора записей
НоваяЗапись = НаборДвижения.Добавить();
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.Регистратор = ЭтотОбъект.Ссылка;
// ... заполнение ресурсов и измерений
НаборДвижения.Записать(Ложь);
В процессе отладки мы видим, что метод Записать() отрабатывает, и в этот момент записи физически попадают в базу данных. Однако, как только выполнение процедуры ОбработкаУдаленияПроведения завершается и транзакция закрывается, записи пропадают. Выясним причину этого явления.
Основная причина кроется в свойстве документа Удаление движений. Если в конфигураторе для документа установлено значение Удалять автоматически, платформа берет на себя управление очисткой регистров. Процесс выглядит так:
ОбработкаУдаленияПроведения платформа помечает все движения документа к удалению или фактически очищает их.Самый прямой способ заставить систему сохранить программно созданные записи — изменить настройки самого документа. Разберем этот шаг подробно:
1. Откройте свойства документа в конфигураторе и перейдите на закладку Движения.
2. Найдите параметр Удаление движений и установите значение Не удалять автоматически.
3. Теперь ответственность за очистку движений ложится на разработчика. Вам необходимо вручную прописать удаление старых записей в процедурах проведения и отмены проведения, кроме тех случаев, когда записи должны остаться.
Посмотрим на пример кода в процедуре ОбработкаУдаленияПроведения при таком подходе:
Процедура ОбработкаУдаленияПроведения(Отказ)
// 1. Очищаем движения по другим регистрам, где автоматика больше не работает
Движения.ДругойРегистрНакопления.Записать = Истина;
Движения.ДругойРегистрНакопления.Очистить();
// 2. Формируем записи в нужный нам регистр сведений
Набор = РегистрыСведений.ИсторияОтмен.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(Ссылка);
НоваяЗапись = Набор.Добавить();
НоваяЗапись.Регистратор = Ссылка;
НоваяЗапись.Период = ТекущаяДата();
НоваяЗапись.Причина = "Техническая отмена";
Набор.Записать(); // Теперь записи сохранятся
КонецПроцедуры
Проанализируем ситуацию с точки зрения архитектуры. Если вам нужно хранить информацию, которая не должна пропадать при распроведении документа (например, лог действий пользователя, история изменений или причина отмены), то использование подчиненного регистра (с установленным свойством «Регистратор») методологически неверно.
Подчиненный регистр предназначен для хранения «движений», которые актуальны только тогда, когда документ проведен. Как только документ становится непроведенным, его движения теряют смысл для учета.
Для решения задачи лучше использовать Независимый регистр сведений:
Независимый.ДокументОбъект (тип Ссылка на ваш документ), чтобы сохранить связь.Рассмотрим пример записи в независимый регистр:
Набор = РегистрыСведений.ЛогСобытий.СоздатьНаборЗаписей();
Набор.Отбор.ДокументИсточник.Установить(Объект.Ссылка);
Запись = Набор.Добавить();
Запись.ДокументИсточник = Объект.Ссылка;
Запись.Событие = "Отмена проведения";
Запись.ДатаСобытия = ТекущаяДата();
Набор.Записать();
Важно помнить, что внутри модуля объекта документа предпочтительнее работать через свойство ЭтотОбъект.Движения, а не через прямое обращение к менеджеру регистра РегистрыСведений.ИмяРегистра.СоздатьНаборЗаписей(). Это связано с тем, что коллекция Движения уже находится в контексте текущей транзакции документа и более корректно обрабатывается платформой.
Если вы все же используете подчиненный регистр, попробуйте установить флаг записи напрямую в коллекции движений:
Движения.МойРегистр.Записывать = Истина;
НоваяЗапись = Движения.МойРегистр.Добавить();
НоваяЗапись.Период = ТекущаяДата();
// Заполнение остальных полей
Важный нюанс: при отмене проведения (распроведении) установка Записывать = Истина для подчиненного регистра часто игнорируется платформой, если включено автоматическое удаление. Поэтому Решение №1 и Решение №2 остаются приоритетными.
Иногда записи создаются, но не видны в отчетах или формах списка. Проверьте свойство Активность. Для записей, создаваемых при отмене проведения в подчиненных регистрах, платформа может принудительно устанавливать Активность = Ложь.
Выясним, как это проверить:
НоваяЗапись.Активность = Истина;.Если вы столкнулись с тем, что записи в регистре сведений не создаются (или удаляются сразу после создания) при отмене проведения:
Удалять автоматически программная запись движений в ОбработкаУдаленияПроведения неэффективна.Не удалять автоматически и управляйте очисткой движений вручную.Использование этих подходов позволит вам избежать трудноуловимых ошибок, связанных с автоматическими механизмами платформы 1С, и обеспечит сохранность важных данных в любой ситуации.