При работе в конфигурации 1С:Управление торговлей (редакция 11.4), а также в родственных решениях 1С:ERP 2 и 1С:Комплексная автоматизация 2, пользователи часто сталкиваются со странным поведением системы. После полного удаления документа (например, «Пересортица товаров» или «Списание товаров») в регистрах накопления (в первую очередь, в регистре Себестоимость товаров) продолжают появляться движения этого документа при очередном закрытии месяца. При этом в качестве регистратора в отчетах или консоли запросов отображается «битая» ссылка вида Объект не найден (479:80f50cc47a57bedb11e997f022ea212e).
В этой статье мы подробно разберем, почему возникает этот технический сбой, как устроена архитектура распределенных вычислений расчета себестоимости в 1С и какими способами можно навсегда удалить эти «фантомные» записи из информационной базы.
Для того чтобы понять природу этой ошибки, нам необходимо проанализировать логику работы механизма расчета себестоимости. В современных версиях конфигураций ERP-класса расчет себестоимости строится не на прямом чтении документов «на лету», а на использовании вспомогательных (технических) таблиц и регистров. Рассмотрим основные причины возникновения «фантомов»:
Задания к расчету себестоимости. Это сообщает программе, что по данной аналитике за определенный период требуется пересчет. Если документ удаляется некорректно (например, напрямую программным способом в обход стандартных механизмов или при сбое транзакции), запись в «Заданиях» остается активной. При запуске закрытия месяца система видит задание, пытается обработать несуществующий документ и на основе кэшированных данных или остатков восстанавливает движения.Ключи аналитики учета номенклатуры. Даже после полного удаления документа сами ключи аналитики остаются в базе. При определенных условиях механизм партионного учета пытается «закрыть» зависшие по этим ключам остатки и генерирует корректирующие движения, привязывая их к последнему известному идентификатору транзакции (GUID удаленного документа).rphost). Если документ был изменен или удален прямо во время или непосредственно перед расчетом, фоновый процесс может использовать устаревшие данные из памяти.---
Если документ еще физически не удален из базы данных (например, он помечен на удаление, но движения все равно появляются), самым быстрым и действенным методом будет форсированное обновление транзакционных связей в СУБД. Рассмотрим этот алгоритм по шагам:
Удаление помеченных объектов.Зачем это нужно? Данный процесс заставляет платформу гарантированно перезаписать таблицы движений во всех связанных регистрах накопления и сведений, сбросить старые ключи аналитики и очистить регистрационные записи в таблицах заданий к расчету.
---
Очень часто фантомные записи порождаются некорректной работой локального или серверного кэша метаданных. Выполним полную очистку:
Agent 1C:Enterprise, зайти в каталог сервера (по умолчанию C:\Program Files\1C\1cv8\srvinfo) и удалить временные папки с кэшем метаданных (папки с длинными буквенно-цифровыми именами UID), после чего запустить службу заново.---
Если документ уже был удален непосредственно (минуя пометку на удаление), и в регистрах осталась только «битая» ссылка типа Объект не найден..., стандартными средствами интерактивно очистить движения не получится. В таком случае нам поможет написание внешней обработки или использование консоли кода для удаления записей с битыми ссылками из регистров.
Проанализируем пример кода на языке 1С для поиска и удаления таких движений из регистра накопления Себестоимость товаров:
// Создаем запрос для поиска движений с отсутствующими регистраторами
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| СебестоимостьТоваров.Регистратор КАК Регистратор
|ИЗ
| РегистрНакопления.СебестоимостьТоваров КАК СебестоимостьТоваров
|ГДЕ
| СебестоимостьТоваров.Регистратор.Ссылка ЕСТЬ NULL
| И НЕ СебестоимостьТоваров.Регистратор = ЗНАЧЕНИЕ(Документ.ПересортицаТоваров.ПустаяСсылка)";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Проверяем, действительно ли ссылка является "битой"
Если Выборка.Регистратор.ПолучитьОбъект() = Неопределено Тогда
// Создаем набор записей по найденному регистратору для его очистки
НаборЗаписей = РегистрыНакопления.СебестоимостьТоваров.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Выборка.Регистратор);
// Записываем пустой набор записей (это полностью удаляет движения из СУБД)
Попытка
НаборЗаписей.Записать(Истина);
Сообщить("Успешно очищены движения для битого регистратора: " + Строка(Выборка.Регистратор));
Исключение
Сообщить("Не удалось очистить движения: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Этот код находит все записи в регистре накопления, у которых битая ссылка в поле Регистратор, и перезаписывает их пустым набором, физически очищая таблицы базы данных SQL или файловой СУБД.
---
Для конфигураций, использующих «Партионный учет 2.2», критически важно также проверить специализированные технические регистры сведений. Очень часто расчетчик себестоимости черпает информацию о партиях из регистра Детализация партий товаров для себестоимости.
Выполним очистку заданий вручную:
Задания к расчету себестоимости.Очередь отражения документов в регламентированном учете, если в вашей программе ведется регламентированный учет.После выполнения указанных шагов запустите процедуру расчета себестоимости повторно. Расчет должен пройти в штатном режиме без появления старых «фантомных» проводок.