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