Как организовать одновременную работу нескольких пользователей в одном документе 1С без ошибок блокировки?

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

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

Анализ проблемы: почему возникает ошибка блокировки?

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

В сценарии, описанном автором темы, два сотрудника выполняют разные роли: один вносит номера заказов, другой отмечает факт выдачи. С точки зрения логики бизнеса — это независимые действия. Но с точки зрения 1С — это изменение одного и того же объекта (документа), что и вызывает конфликт.

Решение №1: Использование независимого регистра сведений

Это самый надежный и рекомендуемый архитектурный подход. Мы переносим оперативную работу из табличной части документа в Регистр сведений. Разберем этот метод по шагам.

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

Рассмотрим пример кода для переноса данных из регистра в документ при нажатии итоговой кнопки:


Процедура ПеренестиДанныеИзРегистраВДокумент(ДокументОбъект)
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   ОперативныеДанныеЗаказов.НомерЗаказа КАК НомерЗаказа,
        |   ОперативныеДанныеЗаказов.ЗаказВыдан КАК ЗаказВыдан
        |ИЗ
        |   РегистрСведений.ОперативныеДанныеЗаказов КАК ОперативныеДанныеЗаказов
        |ГДЕ
        |   ОперативныеДанныеЗаказов.ДокументОснование = &СсылкаНаДокумент";
    
    Запрос.УстановитьПараметр("СсылкаНаДокумент", ДокументОбъект.Ссылка);
     РезультатЗапроса = Запрос.Выполнить();
    
    ДокументОбъект.ТабличнаяЧастьЗаказы.Очистить();
    
    Выборка = РезультатЗапроса.Выбрать();
    Пока Выборка.Следующий() Цикл
        НоваяСтрока = ДокументОбъект.ТабличнаяЧастьЗаказы.Добавить();
        ЗаполнитьЗначенияСвойств(НоваяСтрока, Выборка);
    КонецЦикла;
    
    ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
    
КонецПроцедуры

Решение №2: Произвольные формы с коротким циклом «Прочитал-Записал»

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

Проанализируем алгоритм работы такой формы:

Важный нюанс: Чтобы не затереть изменения другого пользователя, которые он мог внести секунду назад, перед записью необходимо использовать ЗаблокироватьДанныеДляРедактирования() или проверять версию объекта. Рассмотрим пример функции записи отдельного реквизита в строку табличной части:


&НаСервере
Процедура ЗаписатьПризнакВыдачиНаСервере(ИдентификаторСтроки, ЗначениеГалочки)
    
    // Блокируем только на время транзакции записи
    ОбъектДок = РеквизитФормыВЗначение("Объект");
    // Находим нужную строку по идентификатору
    СтрокаТЧ = ОбъектДок.Заказы.НайтиПоИдентификатору(ИдентификаторСтроки);
    
    Если СтрокаТЧ <> Неопределено Тогда
        СтрокаТЧ.ЗаказВыдан = ЗначениеГалочки;
        Попытка
            ОбъектДок.Записать(РежимЗаписиДокумента.Запись);
        Исключение
            Сообщить("Не удалось сохранить данные: " + КраткоеОписаниеОшибки(ИнформацияОбОшибке()));
        КонецПопытки;
    КонецЕсли;
    
    // Обновляем данные на форме, чтобы видеть актуальную картину
    ЗначениеВРеквизитФормы(ОбъектДок, "Объект");
    
КонецПроцедуры

Решение №3: Механизм «Мягких» блокировок строк

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

Создается вспомогательный регистр ТекущиеРедактируемыеСтроки. Когда пользователь начинает редактировать ячейку, в этот регистр записывается: Кто, Какой документ и Какую строку редактирует. Если второй пользователь попытается нажать на ту же строку, система программно проверит наличие записи в этом регистре и выдаст предупреждение: «Эту строку сейчас заполняет менеджер Иванов».

Это позволяет избежать платформенной ошибки Объект уже заблокирован, так как мы управляем доступом на уровне бизнес-логики, а не на уровне СУБД или объектных механизмов 1С.

Решение №4: Разделение на «Документы-задания»

Вместо того чтобы заставлять всех работать в одном огромном документе «за день», можно изменить саму парадигму учета. Выясним, как это упростит систему:

  1. Создается один документ-распоряжение (реестр заказов).
  2. Каждый факт отметки (номер заказа или выдача) фиксируется отдельным небольшим документом СобытиеЗаказа.
  3. В реестре заказов данные отображаются консолидированно (через отчет или динамический список), собирая информацию из всех мелких документов.

Этот метод полностью исключает конфликты, так как каждый пользователь создает свой собственный новый объект в базе данных.

Что нужно знать про Управляемые блокировки?

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

Резюме

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

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

← На главную