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

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

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

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

Решение 1: Простая блокировка при открытии формы (принцип "Кто первый успел")

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

Для реализации этого механизма в управляемых формах существует штатный метод ЗаблокироватьДанныеФормыДляРедактирования(). Разместим его вызов в обработчике события формы ПриСозданииНаСервере. При написании кода рекомендуем проверять конфигурацию на наличие ошибок, чтобы убедиться в правильности вызовов экспортных процедур.

Посмотрим на пример кода:


Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

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

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

Как это работает?

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

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

Решение 2: Пользовательская блокировка через регистр сведений

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

Разберем по шагам, как это сделать:

  1. Создаем регистр сведений. Назовем его, например, ЗанятыеОбъекты. Он будет непериодическим, с режимом записи "Независимый".
    Измерения:
    • Объект (тип ДокументСсылка или составной тип, если блокировать нужно разные объекты)
    Ресурсы:
    • Пользователь (тип СправочникСсылка.Пользователи)
    • ВремяНачала (тип Дата)
    • Сеанс (тип УникальныйИдентификатор) - полезно для отслеживания "зависших" сеансов.
  2. Дорабатываем форму документа.

    В модуле формы в обработчике ПриСозданииНаСервере пишем логику проверки и установки блокировки.

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

    В обработчике ПриЗакрытии необходимо не забыть снять блокировку, удалив соответствующую запись из регистра.

  3. Решаем проблему "зависших" блокировок.

    Главный недостаток этого метода: если сеанс пользователя завершится аварийно (пропадет сеть, выключат свет), запись в регистре останется, и документ будет "заблокирован" навсегда. Эту проблему нужно решать отдельно.

    Варианты решения:
    • Кнопка для администратора: Создать обработку, доступную администратору или руководителю, которая покажет все активные блокировки и позволит вручную удалить любую из них.
    • Автоматическая очистка: Создать регламентное задание, которое будет запускаться раз в несколько минут. Для гибкой настройки периодичности можно применить конструктор Cron расписания. Задание должно получать список активных сеансов 1С и сравнивать их со списком блокировок в регистре. Если блокировка установлена из сеанса, которого уже нет в системе, такая блокировка удаляется.

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

Архитектурный подход: изменение бизнес-процесса

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

Рассмотрим классический пример из обсуждения — инвентаризация на большом складе.

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

Правильный подход:

  1. Бизнес-процесс разбивается на более мелкие, независимые задачи. Например, каждый кладовщик отвечает за свой сектор склада или за свою группу товаров.
  2. В системе создаются не один, а несколько документов, например, "Пересчет товаров". Каждый кладовщик работает со своим собственным документом и заполняет только свою часть данных. Эти документы не пересекаются, и конфликты исключены.
  3. После того как все кладовщики завершили свою работу, запускается конвейер обработки задач, который автоматически собирает данные из всех документов "Пересчет товаров" и формирует итоговый, сводный документ "Инвентаризация товаров", который затем обрабатывает бухгалтер или менеджер.

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

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

Заключение

Проблему одновременного редактирования документов можно решать на разных уровнях.

← На главную