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