В распределенных информационных базах (РИБ) часто возникает ситуация, когда стандартные механизмы платформы ведут себя не так, как ожидается, особенно в самописных конфигурациях. Типичная проблема: бухгалтер в центральном узле помечает документ на удаление, в центре движения по регистрам исчезают, но после синхронизации в периферийном узле документ помечается на удаление, а его "хвосты" в виде записей в регистрах накопления или сведений остаются. Проанализируем ситуацию, выясним причины и разберем по шагам, как это исправить.
При обмене данными через РИБ платформа 1С использует специализированный режим записи объектов. Проанализируем свойство ОбменДанными.Загрузка. Когда данные приходят из другого узла, этому свойству устанавливается значение Истина. Это делается для того, чтобы:
ПередЗаписью и ПриЗаписи, которые могут помешать загрузке (например, контроль остатков).Важный момент: в режиме загрузки стандартный механизм очистки движений при пометке удаления может не срабатывать, если он завязан на логику, которая обходится этим флагом. Если ваш документ в узле просто записывается с новым признаком ПометкаУдаления, но при этом не происходит вызов процедуры отмены проведения, движения останутся в базе "навсегда".
Выясним причину, по которой движения регистра могут игнорироваться. Если документ включен в состав плана обмена, а регистр (например, ОстаткиТоваров) — нет, то платформа при обмене передает только состояние самого документа. В штатном режиме РИБ это означает, что записи регистра в периферийном узле живут своей жизнью.
Рассмотрим ситуацию подробнее: когда в центре документ помечается на удаление, платформа удаляет его движения. Но так как регистр не в плане обмена, информация об удалении этих строк не попадает в пакет обмена. В узел приходит только измененный "заголовок" документа с пометкой на удаление. Если в коде конфигурации нет явной команды на очистку движений при получении такого документа, движения останутся актуальными, хотя документ уже будет помечен как недействительный.
Если конфигурация не типовая, обмен может быть реализован через подписки на события или специализированные модули. Проанализируем, где может прятаться логика перепроведения или записи документа при обмене:
ПриЗаписи или ПередЗаписью для вашего документа. Обратите внимание на те, где в обработчике проверяется Источник.ОбменДанными.Загрузка.ПередЗаписью и ПриЗаписи. Возможно, там стоит условие Если ОбменДанными.Загрузка Тогда Возврат; КонецЕсли;, которое блокирует очистку движений.Если мы обнаружили, что документ при загрузке помечается на удаление, но сохраняет движения, нам необходимо вмешаться в процесс записи. Рассмотрим пример кода, который можно разместить в подписке на событие ПриЗаписи документа.
Посмотрим на пример реализации очистки движений:
Процедура ПриЗаписиДокументаДляОбмена(Источник, Отказ) Экспорт
// Нас интересует только режим загрузки из другого узла
Если Не Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем, что документ помечен на удаление
Если Источник.ПометкаУдаления Тогда
// Нам нужно вручную очистить движения по конкретному регистру
// Создаем набор записей регистра, по которому "зависли" движения
НаборЗаписей = РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Источник.Ссылка);
// Читаем текущие движения (если они есть)
НаборЗаписей.Прочитать();
// Если движения существуют, очищаем их
Если НаборЗаписей.Количество() > 0 Тогда
НаборЗаписей.Очистить();
НаборЗаписей.Записать();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот код принудительно очищает записи в регистре ОстаткиТоваров, если документ загружается с пометкой на удаление. Обратите внимание, что мы используем НаборЗаписей, так как это самый быстрый и надежный способ работы с движениями документа.
Выясним, как настроены свойства самого документа в конфигураторе. Откройте свойства документа Переоценка и перейдите на закладку "Движения". Рассмотрим поле "Удаление движений". Там может быть три варианта:
Загрузка = Истина этот механизм часто игнорируется.ОбработкаУдаленияПроведения.В случае с РИБ, если документ приходит сразу помеченным на удаление, он может миновать стадию "отмены проведения", и тогда автоматика не сработает. Проанализируем ситуацию: если в коде обмена используется метод Источник.Записать(РежимЗаписиДокумента.Запись) вместо Источник.УстановитьПометкуУдаления(Истина), то классические триггеры удаления движений могут не активироваться.
Если вы не знаете, где именно происходит магия обмена, воспользуйтесь глобальным поиском (Ctrl+Shift+F). Проанализируем ключевые фразы, которые помогут найти "виновника":
.Записать(РежимЗаписиДокумента.Запись — поиск мест, где документ записывается принудительно без проведения.РегистрыНакопления.ОстаткиТоваров.СоздатьНаборЗаписей() — поиск мест, где программно управляют вашим регистром.ПланыОбмена.ВыбратьИзменения — поможет найти самописные узлы выгрузки/загрузки.ОбменДанными.Загрузка = Истина — поиск логики, специфичной для загрузки данных.Важное предостережение: Будьте осторожны при программной очистке движений. Если в вашей системе настроен сложный обмен, при котором движения должны приходить отдельными объектами (хотя в данном случае это не так, раз регистра нет в плане обмена), вы можете спровоцировать расхождение данных. Но в вашей ситуации, когда регистр не является частью РИБ, ручная очистка в момент пометки удаления документа — это единственный верный путь сохранить целостность остатков в узлах.
Мы проанализировали проблему "зависших" движений в РИБ и выяснили, что она кроется в сочетании режима загрузки данных и отсутствия регистра в составе плана обмена. Разберем краткий алгоритм действий для исправления:
ОстаткиТоваров действительно не должен быть в плане обмена.ПриЗаписи для документа Переоценка.ОбменДанными.Загрузка и ПометкаУдаления.НаборЗаписей регистра с отбором по регистратору.Следование этим шагам позволит вам синхронизировать состояние базы в центре и в узлах, исключив ошибки в отчетах по остаткам товаров.