Как обнаружить процесс или пользователя, который меняет документ в 1С:Управление торговлей 10

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

В практике работы с «1С:Управление торговлей 10» (на обычных формах) программисты часто сталкиваются с неприятной ситуацией: пользователь открывает документ, работает с ним некоторое время, но при попытке сохранения получает системную ошибку: «Версия объекта изменилась». Это явный признак того, что пока форма была открыта, данные в базе данных были изменены другим сеансом или фоновым процессом. Разберем по шагам, как эффективно провести расследование и найти «виновника» этих изменений.

Метод 1. Глубокий анализ Журнала регистрации

Прежде чем переходить к сложным техническим инструментам, проверим стандартный механизм. Однако делать это нужно правильно. Рассмотрим, как настроить фильтры, чтобы увидеть скрытые процессы.

  1. Запустим Журнал регистрации и установим отбор по конкретному объекту (ссылке на документ ЗК).
  2. Обратим внимание на колонку «Сеанс» и «Имя пользователя».
  3. Проанализируем время записи. Если время совпадает с моментом, когда основной пользователь держал форму открытой, смотрим на тип соединения.
  4. Если в поле пользователя указано имя, отличное от текущего, — мы нашли того, кто меняет данные вручную.
  5. Если же в журнале фигурирует пустой пользователь или специальная учетная запись для обмена, а тип сеанса — «Фоновое задание» или «COM-соединение», значит, документ меняет автоматика.

Проанализируем ситуацию, если Журнал регистрации пуст или не дает ответа. Такое бывает, если запись производится с отключенной регистрацией в журнале (хотя это редкость для типовых механизмов) или если изменения касаются не самого документа, а связанных с ним наборов записей, которые в коде могут вызывать перезапись «владельца».

Метод 2. Поиск «фантомных» изменений в коде формы

Как справедливо отмечено в обсуждении, ошибка версии не всегда означает, что документ изменил другой пользователь. Рассмотрим ситуацию, когда сама форма «подкладывает свинью» программисту. Если в модуле формы или в общих модулях, вызываемых из формы (например, в обработчике ожидания или при изменении реквизита), написан код, создающий новый объект на основании текущей ссылки, произойдет конфликт версий.

Выясним причину через поиск по коду. Ищем конструкцию ПолучитьОбъект(). Если мы видим нечто подобное:


ОбъектДляЗаписи = Ссылка.ПолучитьОбъект();
// ... какие-то манипуляции с реквизитами ...
ОбъектДляЗаписи.Записать();

В этом случае в базе данных версия объекта увеличивается. Однако объект ЭтотОбъект, с которым работает открытая форма пользователя, об этом «не знает». В его памяти хранится старый номер версии. При нажатии кнопки «ОК» форма пытается записать свои данные, сравнивает версию в памяти с версией в БД, видит расхождение и блокирует запись.

Метод 3. Программная «ловушка» в модуле объекта

Если визуальный поиск по коду не помог, создадим диагностическую ловушку. Этот метод считается одним из самых надежных, так как он срабатывает непосредственно в момент записи в базу данных, независимо от того, откуда пришел вызов.

Перейдем в модуль объекта документа ЗК и добавим код в процедуру ПередЗаписью. Нам нужно зафиксировать стек вызовов — цепочку процедур, которая привела к выполнению метода Записать().


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Включаем лог только для конкретного случая или пользователя, чтобы не спамить
    Если НЕ ОбменДанными.Загрузка Тогда
        ТекстЛога = "Документ " + Ссылка + " записывается. Пользователь: " + ИмяПользователя();
        ТекстЛога = ТекстЛога + Символы.ПС + "Стек вызовов:" + Символы.ПС + ПолучитьСтекВызовов();
        
        // Запись в текстовый файл для анализа
        ЗаписьТекста = Новый ЗаписьТекста("C:\temp\log_zk.txt", КодировкаТекста.UTF8, , Истина);
        ЗаписьТекста.ЗаписатьСтроку(ТекущаяДата() + ": " + ТекстЛога);
        ЗаписьТекста.Закрыть();
    КонецЕсли;

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

Функция ПолучитьСтекВызовов()
    // В старых версиях платформы 8.2/8.3 (Обычные формы) 
    // прямой функции получения стека может не быть.
    // Используем хитрость с вызовом исключения:
    ТекстСтека = "";
    Попытка
        ВызватьИсключение "ЛовимСтек";
    Исключение
        ТекстСтека = ИнформацияОбОшибке().Описание;
    КонецПопытки;
    Возврат ТекстСтека;
КонецФункции

После внедрения этого кода достаточно дождаться воспроизведения ошибки у пользователя. В файле log_zk.txt вы увидите полную картину: какая подписка на событие, регламентное задание или общий модуль инициировали запись документа.

Метод 4. Использование Технологического журнала (ТЖ)

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

Настроим файл logcfg.xml для сбора событий DBV8DBENG (обращения к СУБД) или SDBL (внутренний язык запросов 1С). Разберем пример настройки фильтра:

  1. В фильтре укажем имя таблицы, соответствующей нашему документу в SQL (например, _Document123).
  2. Добавим событие CALL, чтобы видеть стек вызовов на языке 1С.
  3. ТЖ покажет нам не только факт команды UPDATE в таблице, но и контекст выполнения на стороне сервера 1С.

Этот метод хорош тем, что он показывает изменения, вносимые даже внешними системами через COM-интерфейс или Web-сервисы, которые могут «проскакивать» мимо некоторых проверок в коде.

Метод 5. Анализ регламентных заданий и подписок

В перепиленных конфигурациях УТ 10 часто встречаются «самописные» механизмы актуализации данных. Посмотрим на наиболее вероятные места:

Проанализируем ситуацию комплексно. Если вы обнаружили, что документ меняет регламентное задание, стоит пересмотреть логику: действительно ли нужно перезаписывать весь объект? Часто достаточно изменить состояние в регистре сведений, не трогая сам документ, чтобы не блокировать работу пользователей.

Резюме по решению проблемы

Для эффективного поиска выполним следующие действия:

  1. Проверим Журнал регистрации с отбором по ссылке объекта и анализом колонки сеанса.
  2. Исключим «самострел» — поищем в коде формы использование ПолучитьОбъект().Записать().
  3. Установим «ловушку» в модуле объекта для фиксации стека вызовов в файл.
  4. Проверим подписки на события, которые могут модифицировать документ при записи других связанных объектов.

Используя эти методы, вы быстро определите, кто именно меняет версию объекта, и сможете либо исправить некорректный код, либо договориться с пользователями о регламенте работы с документами.

← На главную