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