Почему движения документа не видны в отладчике при проведении, но появляются в регистрах?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

Встречались ли вы с ситуацией, когда при отладке проведения документа происходит нечто необъяснимое? Вы пошагово проходите всю процедуру ОбработкаПроведения, внимательно следите за коллекцией движений документа, а она до самого конца остается пустой. Но как только процедура завершается, вы открываете движения документа и видите, что они сформированы. Откуда они взялись, если в основном модуле их не было? Давайте вместе разберемся в этом феномене, проанализируем возможные причины и рассмотрим надежные способы отладки таких "скрытых" механизмов.

Эта проблема, хоть и выглядит как магия, имеет вполне логичные технические объяснения, связанные с архитектурой платформы 1С и типовых конфигураций. Рассмотрим основные гипотезы, от самых вероятных к более редким.

Причина №1: Отложенное проведение и фоновые задания

Самая частая причина такого поведения в современных конфигурациях — использование механизма отложенного проведения. Чтобы пользователь не ждал долго, пока выполняются все ресурсоемкие расчеты (например, расчет себестоимости по партиям), основная процедура ОбработкаПроведения выполняет только самые быстрые операции или просто готовит данные. Основная же работа по формированию движений выносится в отдельное фоновое задание, которое запускается сразу после основной транзакции.

Как это работает? Процедура проведения может создавать запись в специальном регистре-очереди, а фоновое задание, работающее параллельно, подхватывает эту запись и уже в своем потоке формирует и записывает движения. Стандартный отладчик, подключенный к сеансу пользователя, просто "не видит" этот параллельный процесс.

Как отладить? Чтобы поймать выполнение кода в фоновом задании, нужно правильно настроить отладчик:

  1. Откройте Конфигуратор и перейдите в меню "Отладка" -> "Подключение...".
  2. В открывшемся окне найдите раздел "Автоматическое подключение".
  3. Установите флажок напротив пункта "Фоновые задания".

После этого отладчик будет автоматически "присоединяться" к запускаемым фоновым процессам, и вы сможете поймать выполнение кода точкой останова, даже если он выполняется не в вашем основном сеансе. Часто в типовых конфигурациях используются общие модули с названием вроде ДлительныеОперации, которые как раз и отвечают за запуск таких фоновых обработчиков.

Причина №2: Магия модуля набора записей

Еще один ключевой момент, который часто сбивает с толку — это то, как платформа работает с наборами записей регистра. Запись движений — это не просто добавление строк. Платформа сначала полностью удаляет все старые движения по этому документу-регистратору, а затем записывает новый набор. Это приводит к интересному эффекту.

Если вы поставите точку останова в модуле набора записей регистра (например, в событии ПередЗаписью), она сработает дважды:

  1. Первый раз: при записи пустого набора записей. Это и есть момент очистки старых движений. В этот момент коллекция движений будет пустой.
  2. Второй раз: при записи нового, уже заполненного набора записей. Это то, что нам нужно!

Как использовать для отладки? Это самый надежный способ найти источник записи. Поставим "умную" точку останова.

Разберем по шагам:

  1. Найдите нужный регистр накопления в дереве конфигурации (в нашем примере это ПартииПереданные).
  2. Откройте его свойства и нажмите на лупу у события "ПередЗаписью", чтобы перейти в модуль набора записей.
  3. В процедуре ПередЗаписью напишем небольшой код и поставим точку останова.

Посмотрим на пример кода. Важно добавить проверку, что записываемый набор не пустой.


// Модуль набора записей регистра "ПартииПереданные"
Процедура ПередЗаписью(Отказ, Замещение)

    // Эта проверка отсекает первый вызов, когда платформа очищает старые движения.
    // Нас интересует только момент записи новых, непустых данных.
    Если ЭтотОбъект.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    // Ставим точку останова на следующей строке.
    Сообщить("Выполняется запись непустого набора записей в регистр!");
    
    // Когда отладчик остановится здесь, нужно немедленно посмотреть "Стек вызовов".
    // В стеке будет видна вся цепочка процедур, которая привела к этой записи,
    // и вы точно найдете ту самую "скрытую" процедуру, формирующую движения.

КонецПроцедуры

Важный момент: внутри модуля набора записей текущий набор доступен через ЭтотОбъект. Анализ стека вызовов в момент остановки на этом коде — это практически гарантированный способ найти источник проблемы.

Причина №3: Вызовы из общих модулей и подписок на события

Часто логика формирования движений вынесена из модуля документа в общие модули для переиспользования кода. Например, в УТ10 существует общий модуль УправлениеЗапасамиПартионныйУчет, который содержит процедуры вроде ПоступлениеПереданныхУпр. Вызов таких процедур может происходить не напрямую, а через механизм подписок на события (например, на событие ОбработкаПроведения документа).

Как найти?

  1. Глобальный поиск. Это ваш лучший друг. Выполните поиск по всей конфигурации по имени вашего регистра (например, "ПартииПереданные"). Это покажет все места, где к нему есть обращение, включая общие модули и подписки.
  2. Замер производительности. Это мощный инструмент. Перед проведением документа запустите замер ("Сервис" -> "Замер производительности"), выполните проведение, остановите замер. В полученном отчете вы увидите дерево всех выполненных процедур и функций с указанием времени их выполнения. Внимательно проанализировав это дерево, вы сможете обнаружить вызовы неочевидных процедур, которые и формируют движения.

Причина №4: Проблемы с кэшем конфигурации

Иногда причина странного поведения платформы кроется в поврежденном или устаревшем кэше. Платформа хранит скомпилированные модули и метаданные локально для ускорения работы. Если что-то пошло не так, исполняемый код может не соответствовать тому, что вы видите в конфигураторе.

Что делать? Перед сложной отладкой всегда полезно выполнить "гигиеническую" процедуру — очистку кэша. Это простое действие решает массу необъяснимых проблем. Способов несколько, самый простой — удалить папку с кэшем вручную из профиля пользователя в %APPDATA%\1C\1Cv8.

Итоговый план действий по поиску "невидимых" движений

Итак, проанализировав ситуацию, составим четкий алгоритм действий:

  1. Очистите кэш. Всегда начинайте с этого, чтобы исключить самые простые и глупые ошибки.
  2. Настройте отладку фоновых заданий. Это позволит поймать отложенные операции.
  3. Поставьте точку останова в модуле набора записей. Используйте условную точку останова или проверку ЭтотОбъект.Количество() > 0, чтобы остановиться в нужный момент. Проанализируйте стек вызовов.
  4. Используйте глобальный поиск и замер производительности, чтобы найти все упоминания регистра и скрытые вызовы процедур.

Следуя этому плану, вы с очень высокой вероятностью найдете истинный источник формирования движений и сможете внести необходимые изменения в правильном месте, не прибегая к "костылям" вроде изменения стандартных процедур восстановления последовательности.

← На главную