Как запретить изменение документов в закрытом периоде при обмене через Конвертацию данных 2.1?

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

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

Почему стандартный подход с ОбъектМодифицирован не работает?

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

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

Итоговое решение о необходимости вызова метода Записать() принимается системой на основании следующей логической формулы:

НужноЗаписыватьОбъект = ОбъектМодифицирован ИЛИ СвойстваОбъектаМодифицированы

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

Решение проблемы: использование флага НеЗамещатьОбъект

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

Рассмотрим по шагам, как реализовать эту проверку в правилах конвертации объектов (ПКО):

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

Проанализируем пример кода, который позволит нам достичь желаемого результата:


// Проверяем, был ли объект найден в базе данных приемника.
// Если объект новый, условие ОбъектНайден будет Ложь.
Если ОбъектНайден Тогда  
    
    // Сравниваем дату документа с установленной границей запрета.
    // Параметры.ГраницаЗапретаИзменений должны быть определены заранее.
    Если Объект.Дата < Параметры.ГраницаЗапретаИзменений Тогда
        
        // Сообщаем системе, что объект не требует записи по причине модифицированности свойств
        ОбъектМодифицирован = Ложь;
        
        // Устанавливаем ключевой флаг, запрещающий перезапись существующего объекта
        НеЗамещатьОбъект = Истина;
        
        // Для уверенности можно также отключить проведение, если оно было включено в ПКО
        РежимЗаписи = "Запись"; 
        
    КонецЕсли;
КонецЕсли;

Важные нюансы при работе с закрытым периодом

Разберем дополнительные аспекты, которые помогут сделать ваш обмен более надежным и быстрым.

1. Опасность создания новых объектов

В приведенном выше коде используется условие Если ОбъектНайден Тогда. Это означает, что если в базе-источнике (ERP) создадут новый документ «задним числом» (в периоде, который в УПП уже закрыт), и в УПП такого документа еще нет, то ОбъектНайден будет равен Ложь. В этом случае система создаст и запишет новый документ в закрытом периоде! Если ваша задача — запретить любое появление новых данных в старых периодах, условие ОбъектНайден нужно убрать, либо добавить проверку на Объект.ЭтоНовый().

2. Использование переменной Отказ

Если вы хотите не просто «не замещать» объект, а полностью прервать его обработку (чтобы система даже не пыталась сопоставлять его свойства и не тратила ресурсы), в обработчике «При загрузке» или «Перед загрузкой» можно использовать Отказ = Истина. Это более радикальный способ, который полностью исключает текущий объект из процесса импорта.

3. Оптимизация на стороне источника (ERP)

Проанализируем ситуацию: зачем нам вообще выгружать документы из ERP, если мы заранее знаем, что УПП их не примет? Гораздо эффективнее добавить проверку в ПКО на стороне источника в обработчике «Перед выгрузкой»:


// В источнике (ERP)
Если Объект.Дата < ДатаНачалаВыгрузки Тогда
    Отказ = Истина;
КонецЕсли;

Это сократит размер XML-файла и значительно ускорит процесс обмена, так как приемнику не придется искать объекты по ГУИД-ам, чтобы потом решить их не записывать.

4. Передача даты запрета через параметры

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


// Пример получения даты запрета в приемнике
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ДатаЗапрета ИЗ РегистрСведений.ГраницыЗапретаИзменений ГДЕ ...";
// ... выполнение запроса ...
Параметры.Вставить("ГраницаЗапретаИзменений", РезультатЗапроса);

Подведение итогов

Мы проанализировали механизм работы Конвертации данных 2.1 и выяснили, что управление записью объектов в закрытых периодах требует комплексного подхода. Использование только ОбъектМодифицирован = Ложь недостаточно из-за автоматической проверки СвойстваОбъектаМодифицированы.

Ключевые рекомендации:

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