В процессе эксплуатации конфигурации «1С:Управление торговлей 10.3» (или других систем на платформе «1С:Предприятие 8») специалисты часто сталкиваются с ситуацией, когда в отчетах по взаиморасчетам или остаткам товаров отображаются некорректные данные. При попытке перейти к первичному документу выясняется, что документ либо помечен на удаление, либо вовсе отсутствует в базе, а в поле регистратора отображается надпись <Объект не найден>. Подобные «фантомные» движения не только искажают отчетность, но и могут привести к фатальным ошибкам при проведении регламентных операций или тестировании базы данных (ошибки SDBL).
В рамках данной статьи мы подробно разберем, как диагностировать причину появления таких записей и какими программными методами их можно корректно удалить, не повредив при этом структуру таблиц СУБД.
Прежде чем приступать к программному удалению, нам необходимо убедиться, что записи в регистре действительно принадлежат проблемному документу. Часто отчеты (особенно в УТ 10.3) строятся на основе сложных виртуальных таблиц или дополнительных регистров сведений, где в качестве аналитики может быть указан один документ, а фактическим регистратором записи выступает другой (например, Корректировка записей регистров).
Проанализируем ситуацию с помощью «Консоли запросов». Нам нужно выполнить запрос к физической таблице регистра накопления (например, РегистрНакопления.ВзаиморасчетыСКонтрагентами), наложив фильтр по периоду или сумме, которые видят бухгалтеры в отчете. Важно выводить поле Регистратор. Если в результате мы видим ссылку типа <Объект не найден> (8d74...), значит, мы имеем дело с нарушением ссылочной целостности.
Стандартный механизм Тестирование и исправление с настройками «Очищать ссылки» или «Удалять объект» иногда завершается аварийно с ошибкой SDBL. Это происходит из-за того, что платформа пытается пересчитать итоги в таблицах агрегатов, натыкается на запись, ссылающуюся на несуществующий в основной таблице документов ID, и не может корректно завершить транзакцию.
В этом случае ручное вмешательство программиста через написание небольшого кода обработки является наиболее безопасным и эффективным путем.
Если у нас есть ссылка на документ (даже если это битая ссылка «Объект не найден»), мы можем воспользоваться механизмом набора записей. В 1С запись пустого набора с установленным отбором по регистратору полностью удаляет все движения этого регистратора из таблицы.
Рассмотрим пример кода для удаления таких движений:
// Предположим, мы получили битую ссылку из консоли запросов или отчета
БитаяСсылка = РегистрыНакопления.ВзаиморасчетыСКонтрагентами.Выбрать().Регистратор;
// Создаем набор записей регистра
Набор = РегистрыНакопления.ВзаиморасчетыСКонтрагентами.СоздатьНаборЗаписей();
// Устанавливаем отбор по нашему «фантомному» документу
Набор.Отбор.Регистратор.Установить(БитаяСсылка);
// Записываем пустой набор (без добавления строк)
// Параметр Истина означает замещение существующих записей в БД
Набор.Записать(Истина);
После выполнения этого кода платформа удалит все записи из физической таблицы регистра, связанные с данным GUID, и отчеты станут корректными.
Иногда платформа не позволяет установить отбор по битой ссылке напрямую или требуется «оживить» документ, чтобы понять, какой пользователь его создал. В этом случае мы можем восстановить объект документа по его уникальному идентификатору (GUID).
Разберем по шагам, как это сделать:
8d74... в скобках).ПолучитьСсылку() менеджера документа.GUID.Пример кода для восстановления документа:
// Строка идентификатора, взятая из представления "Объект не найден"
СтрокаGUID = "5ec1578a-6663-11ef-810a-00155d013d02";
Идентификатор = Новый УникальныйИдентификатор(СтрокаGUID);
// Получаем ссылку для конкретного типа документа (например, ПКО)
СсылкаНаДок = Документы.ПриходныйКассовыйОрдер.ПолучитьСсылку(Идентификатор);
// Проверяем, существует ли объект на самом деле
Если СсылкаНаДок.ПолучитьОбъект() = Неопределено Тогда
// Создаем новый "пустой" документ
НовыйПКО = Документы.ПриходныйКассовыйОрдер.СоздатьДокумент();
// Устанавливаем ему идентификатор старого удаленного документа
НовыйПКО.УстановитьСсылкуНового(СсылкаНаДок);
// Заполняем минимально необходимые реквизиты (дата, организация) и записываем
НовыйПКО.Дата = ТекущаяДата();
НовыйПКО.Записать(РежимЗаписиДокумента.Запись);
Сообщить("Документ успешно восстановлен. Теперь его можно пометить на удаление и удалить штатно.");
КонецЕсли;
После того как документ «появился» в базе, его движения снова становятся связанными с объектом. Теперь вы можете зайти в форму документа, нажать «Действия» — «Движения документа по регистрам» и убедиться, что они отображаются. После этого достаточно пометить документ на удаление и воспользоваться стандартной обработкой «Удаление помеченных объектов». Система сама очистит все связанные записи в регистрах.
Важно помнить, что в конфигурации «Управление торговлей 10.3» данные по взаиморасчетам дублируются. Проанализируем основные регистры, которые стоит проверить при возникновении «фантомов»:
Если вы очистили движения в одном регистре, но забыли про другой, цифры в отчетах могут продолжать «ползти». Поэтому рекомендуется выполнять поиск записей по битой ссылке во всех регистрах, где данный тип документа может выступать регистратором.
Чтобы избежать подобных проблем в будущем, следует придерживаться следующих правил:
Удалить() без предварительной очистки движений. Используйте УстановитьПометкуУдаления().НачатьТранзакцию() ... ЗафиксироватьТранзакцию().Использование вышеописанных методов программной очистки через НаборЗаписей и восстановление ссылки через УстановитьСсылкуНового позволяет решить проблему «зависших» движений максимально корректно и вернуть учет в рабочее состояние.