Почему при проведении документа в 1С возникает ошибка «Данные были изменены или удалены другим пользователем»?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С:Предприятие часто возникают ситуации, когда пользователь, пытаясь провести документ, сталкивается с сообщением: «Данные были изменены или удалены другим пользователем». Давайте разберем, почему это происходит и как правильно организовать логику изменения данных, чтобы избежать подобных конфликтов.

Анализ причин возникновения конфликта версий

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

Особенно критична ситуация, описанная в нашем случае: изменение реквизитов документа непосредственно внутри события ОбработкаПроведения. Попытки программного изменения объекта прямо в момент проведения, особенно если документ уже находится в состоянии, препятствующем проведению (например, помечен на удаление), вызывают логические конфликты и ошибки транзакции.

Почему нельзя менять данные внутри события проведения

Событие ОбработкаПроведения предназначено строго для одного действия — формирования движений документа по регистрам. Изменение реквизитов самого документа в этом модуле — это «дурной тон» разработки, который ведет к следующим проблемам:

  1. Рекурсивная запись: Вызов метода Записать() внутри проведения инициирует повторную транзакцию, что создает колоссальную нагрузку на СУБД.
  2. Взаимоблокировки (Deadlock): Транзакция проведения должна быть предельно короткой. Любые лишние манипуляции с другими объектами или реквизитами самого документа повышают вероятность возникновения взаимных блокировок.
  3. Конфликт состояний: Как выяснилось в нашей теме, попытка провести документ, который программно был помечен на удаление в процессе выполнения кода, приводила к аварийному завершению транзакции.

Как правильно организовать изменение документа

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

Использование события «ПередЗаписью»

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

Для того чтобы разделять логику для обычной записи и для проведения, мы используем параметр Отказ и РежимЗаписи. Рассмотрим пример реализации:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        // Выполняем специфические действия только при проведении
        ЭтотОбъект.Статус = Перечисления.СтатусыДокумента.Проведен;
        // Вносим изменения в табличные части
        Для Каждого СтрокаТЧ Из ЭтотОбъект.Товары Цикл
            СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

Таким образом, мы гарантируем, что все расчеты и изменения статусов произойдут до того, как система начнет фиксировать движения по регистрам.

Рекомендации по работе с формами и данными

Если вы используете несколько форм для редактирования одного объекта (как в примере с Форма1 и Форма2), следуйте этим правилам:

  1. Минимизируйте работу с владельцем: Старайтесь передавать данные между формами через параметры или оповещения, а не путем прямого обращения к ЭтотОбъект.ВладелецФормы и вызова Прочитать().
  2. Проверяйте статус объекта: Перед выполнением действий (особенно если есть риск пометки на удаление или изменения другими пользователями) проверяйте состояние объекта:
    
    Если Объект.ПометкаУдаления Тогда
        Сообщить("Документ помечен на удаление! Проведение невозможно.");
        Отказ = Истина;
        Возврат;
    КонецЕсли;
    
  3. Откажитесь от принудительного обновления: Использование Прочитать() из другой формы в момент проведения — это попытка «насильно» переписать данные, которые могут быть уже неактуальны. Перенесите логику подготовки данных на этап ПередЗаписью основного объекта, чтобы форма лишь инициировала процесс, а объект сам следил за своей целостностью.

Подводя итог: если вы сталкиваетесь с ошибкой изменения данных, проанализируйте, не выполняете ли вы запись объекта внутри транзакции проведения. Перенос логики в ПередЗаписью — это стандарт индустрии 1С, который позволит избежать 99% конфликтов блокировок.

← На главную