Могут ли несколько пользователей одновременно редактировать и записывать один документ в 1С?

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

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

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

Технические ограничения платформы 1С при совместном редактировании

Отвечая на главный вопрос: штатно изменять и записывать один и тот же документ несколькими пользователями одновременно нельзя. Проанализируем причины такого поведения платформы 1С.

  1. Объектная модель и пессимистическая блокировка: В платформе 1С документ является неделимой сущностью. Когда первый пользователь начинает интерактивное редактирование строки или реквизита в форме, платформа накладывает пессимистическую блокировку на весь объект целиком. Второй пользователь при попытке открыть или изменить этот же документ получит предупреждение о том, что объект заблокирован.
  2. Контроль версий данных (оптимистическая блокировка): Запись документа происходит целиком в единой транзакции — записываются шапка и все табличные части. Если два пользователя откроют документ до наложения блокировки, в памяти их сеансов создадутся две независимые копии объекта. Если первый пользователь внесет правки в строку №1 и сохранит документ, версия объекта в базе данных изменится. Когда второй пользователь попытается записать изменения по строке №2 из своей локальной копии, платформа выбросит исключение конфликта версий данных (ошибка оптимистической блокировки). Если бы платформа позволила записать данные второго пользователя, правки первого пользователя были бы полностью затерты старым состоянием объекта.
  3. Блокировки регистров при проведении: Если документ является проводимым, его частая перезапись и перепроведение разными пользователями вызовут эксклюзивные блокировки связанных регистров накопления и сведений. Это принесет проблемы с производительностью всей системы.

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

Решение 1. Хранение строк табличной части в регистре сведений

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

Разберем по шагам схему реализации:

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

Решение 2. Архитектура с подчиненными документами по менеджерам

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

Проанализируем порядок работы данной схемы:

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

Решение 3. Использование АРМ (обработки) с программным слиянием (Delta-Update)

Если необходимо сохранить стандартную структуру документа, но предоставить менеджерам удобное место для параллельной работы, создается Специализированное Рабочее Место (обработка).

Посмотрим на алгоритм работы этой обработки в момент сохранения данных:

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

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


&НаСервере
Процедура ЗаписатьИзмененияМенеджераНаСервере(СсылкаДокумента, ТаблицаИзмененныхСтрок, ТекущийПользователь)
    
    // 1. Устанавливаем управляемую блокировку на документ для предотвращения коллизий
    Блокировка = Новый БлокировкаДанных;
    ЭлементБлокировки = Блокировка.Добавить("Документ.ПредложениеПокупателя");
    ЭлементБлокировки.УстановитьЗначение("Ссылка", СсылкаДокумента);
    ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
    
    НачатьТранзакцию();
    Попытка
        Блокировка.Заблокировать();
        
        // 2. Считываем актуальный объект из базы данных
        ОбъектДокумент = СсылкаДокумента.ПолучитьОбъект();
        
        // 3. Обновляем только строки текущего пользователя
        Для Каждого СтрИзмен из ТаблицаИзмененныхСтрок Цикл
            Отбор = Новый Структура("КлючСтроки", СтрИзмен.КлючСтроки);
            НайденныеСтроки = ОбъектДокумент.Товары.НайтиСтроки(Отбор);
            
            Для Каждого СтрДок из НайденныеСтроки Цикл
                ЗаполнитьЗначенияСвойств(СтрДок, СтрИзмен, "Цена, Поставщик, СрокПоставки");
            КонецЦикла;
        КонецЦикла;
        
        // 4. Записываем объект и завершаем транзакцию
        ОбъектДокумент.Записать(РежимЗаписиДокумента.Запись);
        ЗафиксироватьТранзакцию();
        
    Исключение
        ОтменитьТранзакцию();
        ВызватьИсключение;
    КонецПопытки;
    
КонецПроцедуры

При таком подходе транзакция и блокировка документа длятся единицы миллисекунд. Это полностью исключает конфликт версий данных и позволяет нескольким пользователям комфортно работать через единый АРМ.

Резюме

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

← На главную