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