Как запретить редактирование документа после проведения его в другой базе данных?

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

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

Проблема: Почему стандартный запрет мешает обмену?

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


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    // Стандартная проверка на загрузку данных
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Логика запрета редактирования
    Если ЭтотОбъект.ОтраженоВБухгалтерии Тогда
        Отказ = Истина;
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Документ отражен в бухгалтерии. Редактирование невозможно.";
        Сообщение.Сообщить();
    КонецЕсли;

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

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

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

Способ 1: Использование дополнительных свойств объекта

Проанализируем самый надежный программный метод решения проблемы — использование коллекции ДополнительныеСвойства. Этот механизм позволяет «пробросить» флаг через все этапы записи документа, даже если платформенный статус ОбменДанными.Загрузка меняется.

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


// В правилах обмена (обработчик ПослеЗагрузки)
Объект.ДополнительныеСвойства.Вставить("ПрограммнаяЗаписьИзОбмена", Истина);

Во-вторых, модифицируем проверку в модуле объекта документа:


Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Проверяем наше специфическое свойство
    Если ЭтотОбъект.ДополнительныеСвойства.Свойство("ПрограммнаяЗаписьИзОбмена") Тогда
        Возврат;
    КонецЕсли;

    Если ЭтотОбъект.ОтраженоВБухгалтерии Тогда
        // Проверка на Проведен, чтобы избежать блокировки при автоматическом перепроведении
        Если РежимЗаписи = РежимЗаписиДокумента.Запись ИЛИ ЭтотОбъект.Проведен Тогда
             Отказ = Истина;
             // Вывод сообщения пользователю...
        КонецЕсли;
    КонецЕсли;

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

Способ 2: Разделение логики объекта и логики формы

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

Рассмотрим вариант блокировки на уровне формы. В процедуре ПриЧтенииНаСервере мы можем анализировать наш реквизит и блокировать элементы управления:


&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
    
    Если ТекущийОбъект.ОтраженоВБухгалтерии Тогда
        ЭтаФорма.ТолькоПросмотр = Истина;
    КонецЕсли;
    
КонецПроцедуры

Преимущества этого подхода:

Способ 3: Проверка состояния проведения

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

Изменим код следующим образом:


Если ЭтотОбъект.ОтраженоВБухгалтерии И ЭтотОбъект.Проведен Тогда
    // Если документ уже был проведен ранее и имеет флаг — блокируем
    Если НЕ ОбменДанными.Загрузка Тогда
        Отказ = Истина;
        // Сообщение...
    КонецЕсли;
КонецЕсли;

Важно помнить, что при загрузке из другой базы свойство ЭтотОбъект.Проведен может принимать значение Истина, если оно передается в пакете данных. Поэтому данный метод требует аккуратной настройки правил конвертации объектов (ПКО).

Способ 4: Настройка правил конвертации (ПКО)

Проанализируем настройки самих правил обмена. Чтобы избежать двойного вызова ПередЗаписью (сначала запись, потом проведение), можно в ПКО для данного документа отключить автоматическое проведение при загрузке.

Вместо этого можно настроить соответствие свойств так, чтобы признак Проведен источника напрямую записывался в приемник. В этом случае документ сохранится сразу в нужном статусе под флагом ОбменДанными.Загрузка = Истина, и система не будет инициировать повторную запись для проведения, где флаг загрузки мог бы сброситься в Ложь.

Рекомендации по реализации

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

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

← На главную