При настройке обмена данными между конфигурациями (например, из 1С:ERP в 1С:УПП) специалисты часто сталкиваются с проблемой: документы загружаются и перезаписываются в периодах, которые уже закрыты для редактирования. Стандартная дата запрета изменений, установленная в информационной базе, часто игнорируется механизмами обмена, так как загрузка выполняется в привилегированном режиме или с установленным флагом ОбменДанными.Загрузка = Истина. В этой статье мы подробно разберем, почему попытки просто «сбросить» флаг модифицированности объекта не работают, и как правильно настроить правила конвертации объектов (ПКО), чтобы защитить данные прошлых периодов.
Рассмотрим ситуацию, с которой столкнулся автор темы. В обработчике ПослеЗагрузки прописан код, который проверяет дату документа и, если она попадает в закрытый период, устанавливает ОбъектМодифицирован = Ложь. Логика кажется верной: если объект не модифицирован, значит, записывать его не нужно. Однако система всё равно выполняет Объект.Записать().
Проанализируем внутреннее устройство обработки «Универсальный обмен данными в формате XML» (УОД), которая используется в КД 2.1. Процесс загрузки объекта включает автоматическое сравнение всех входящих свойств (ПКС) с теми значениями, которые уже есть в базе данных. Если хотя бы одно свойство в файле обмена отличается от значения в ИБ, платформа автоматически устанавливает внутреннюю переменную СвойстваОбъектаМодифицированы в значение Истина.
Итоговое решение о необходимости вызова метода Записать() принимается системой на основании следующей логической формулы:
НужноЗаписыватьОбъект = ОбъектМодифицирован ИЛИ СвойстваОбъектаМодифицированы
Таким образом, даже если вы программно установили ОбъектМодифицирован = Ложь, наличие хотя бы одной измененной буквы в комментарии или копейки в сумме приведет к тому, что СвойстваОбъектаМодифицированы станет Истина, и документ будет сохранен, проигнорировав ваши ограничения.
Для того чтобы гарантированно запретить запись существующего объекта в базе данных приемника, необходимо использовать специальную переменную НеЗамещатьОбъект. Этот флаг дает понять алгоритму загрузки, что, даже если данные в файле отличаются от данных в базе, текущий объект в информационной базе трогать нельзя.
Рассмотрим по шагам, как реализовать эту проверку в правилах конвертации объектов (ПКО):
Проанализируем пример кода, который позволит нам достичь желаемого результата:
// Проверяем, был ли объект найден в базе данных приемника.
// Если объект новый, условие ОбъектНайден будет Ложь.
Если ОбъектНайден Тогда
// Сравниваем дату документа с установленной границей запрета.
// Параметры.ГраницаЗапретаИзменений должны быть определены заранее.
Если Объект.Дата < Параметры.ГраницаЗапретаИзменений Тогда
// Сообщаем системе, что объект не требует записи по причине модифицированности свойств
ОбъектМодифицирован = Ложь;
// Устанавливаем ключевой флаг, запрещающий перезапись существующего объекта
НеЗамещатьОбъект = Истина;
// Для уверенности можно также отключить проведение, если оно было включено в ПКО
РежимЗаписи = "Запись";
КонецЕсли;
КонецЕсли;
Разберем дополнительные аспекты, которые помогут сделать ваш обмен более надежным и быстрым.
1. Опасность создания новых объектов
В приведенном выше коде используется условие Если ОбъектНайден Тогда. Это означает, что если в базе-источнике (ERP) создадут новый документ «задним числом» (в периоде, который в УПП уже закрыт), и в УПП такого документа еще нет, то ОбъектНайден будет равен Ложь. В этом случае система создаст и запишет новый документ в закрытом периоде! Если ваша задача — запретить любое появление новых данных в старых периодах, условие ОбъектНайден нужно убрать, либо добавить проверку на Объект.ЭтоНовый().
2. Использование переменной Отказ
Если вы хотите не просто «не замещать» объект, а полностью прервать его обработку (чтобы система даже не пыталась сопоставлять его свойства и не тратила ресурсы), в обработчике «При загрузке» или «Перед загрузкой» можно использовать Отказ = Истина. Это более радикальный способ, который полностью исключает текущий объект из процесса импорта.
3. Оптимизация на стороне источника (ERP)
Проанализируем ситуацию: зачем нам вообще выгружать документы из ERP, если мы заранее знаем, что УПП их не примет? Гораздо эффективнее добавить проверку в ПКО на стороне источника в обработчике «Перед выгрузкой»:
// В источнике (ERP)
Если Объект.Дата < ДатаНачалаВыгрузки Тогда
Отказ = Истина;
КонецЕсли;
Это сократит размер XML-файла и значительно ускорит процесс обмена, так как приемнику не придется искать объекты по ГУИД-ам, чтобы потом решить их не записывать.
4. Передача даты запрета через параметры
Чтобы код в обработчиках был универсальным, рекомендуется передавать дату запрета как параметр обмена. Выясним, как это сделать:
ГраницаЗапретаИзменений.
// Пример получения даты запрета в приемнике
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ ДатаЗапрета ИЗ РегистрСведений.ГраницыЗапретаИзменений ГДЕ ...";
// ... выполнение запроса ...
Параметры.Вставить("ГраницаЗапретаИзменений", РезультатЗапроса);
Мы проанализировали механизм работы Конвертации данных 2.1 и выяснили, что управление записью объектов в закрытых периодах требует комплексного подхода. Использование только ОбъектМодифицирован = Ложь недостаточно из-за автоматической проверки СвойстваОбъектаМодифицированы.
Ключевые рекомендации:
НеЗамещатьОбъект = Истина в обработчике При загрузке, если нужно защитить существующие данные.Отказ = Истина, если загрузка объекта (включая создание новых) в данный период категорически запрещена.ОбменДанными.Загрузка = Истина отключает встроенные проверки конфигурации, поэтому вся ответственность за целостность данных в закрытых периодах ложится на логику ваших правил конвертации.