При реализации механизмов обмена данными через XML-файлы часто возникает ситуация, когда документ, уже выгруженный во внешнюю систему, подвергается корректировке в исходной базе. Если просто перезаписывать файл на FTP, можно столкнуться с потерей данных или рассинхронизацией. В рамках данной статьи мы проанализируем, как правильно организовать процесс обновления данных, разберем архитектурные подходы и выберем наиболее надежные инструменты платформы 1С.
Рассмотрим стандартный и наиболее профессиональный подход к решению задачи — использование объекта метаданных ПланыОбмена. Вместо того чтобы пытаться реализовать логику отслеживания изменений вручную через подписки на события и сложные условия, мы доверим эту работу платформе. Механизм планов обмена позволяет регистрировать изменения конкретных объектов для конкретных узлов (получателей).
Проанализируем преимущества этого метода:
Для реализации регистрации изменений в коде модуля объекта или в подписке на событие ПриЗаписи нам потребуется следующий код:
// Процедура для регистрации изменений документа в плане обмена
Процедура ЗарегистрироватьИзменениеДокумента(Источник, Отказ) Экспорт
УзелОбмена = ПланыОбмена.ИнтеграцияСВесами.НайтиПоКоду("Основной");
Если ЗначениеЗаполнено(УзелОбмена) Тогда
ПланыОбмена.ЗарегистрироватьИзменения(УзелОбмена, Источник.Ссылка);
КонецЕсли;
КонецПроцедуры
Разберем типичную ошибку, упомянутую в обсуждении: выгрузку файла непосредственно в событии ПриЗаписи. Если выгрузка происходит внутри транзакции записи, а затем документ не удается провести (например, из-за нехватки остатков), файл на FTP уже будет отправлен. В итоге внешняя база получит данные, которых в основной базе фактически нет.
Чтобы избежать этой ситуации, мы рекомендуем использовать следующий алгоритм:
ПередЗаписью или ПриЗаписи устанавливаем флаг необходимости выгрузки в ДополнительныеСвойства объекта.ПослеЗаписи проверяем этот флаг и инициируем выгрузку, но только если транзакция завершена успешно.Посмотрим на пример использования дополнительных свойств:
// В модуле документа
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
ЭтотОбъект.ДополнительныеСвойства.Вставить("ТребуетсяВыгрузкаXML", Истина);
КонецЕсли;
КонецПроцедуры
Процедура ПослеЗаписи(ПараметрыЗаписи)
Если ЭтотОбъект.ДополнительныеСвойства.Свойство("ТребуетсяВыгрузкаXML") Тогда
// Здесь можно вызвать фоновое задание, чтобы не заставлять пользователя ждать
// ответа от FTP-сервера
ФоновыеЗадания.Выполнить("ИнтеграцияМенеджер.ВыгрузитьДокументНаFTP", Новый Структура("Ссылка", Ссылка));
КонецЕсли;
КонецПроцедуры
Выясним причину, по которой простая перезапись файла по GUID документа может быть опасна. Если процесс чтения в принимающей базе совпадет по времени с процессом записи нового файла в отправляющей, файл может быть прочитан не полностью ("битый" XML).
Рассмотрим две стратегии именования:
Document_GUID_YYYYMMDDHHMMSS.xml. В этом случае каждый файл уникален. Принимающая база должна обрабатывать файлы в хронологическом порядке. Если для одного GUID найдено несколько файлов, обрабатывается самый свежий, а остальные помечаются как устаревшие.<Status>. При первичной выгрузке статус будет New, при последующих — Edited. Это позволит принимающей логике понять, что нужно не создавать новый документ, а обновить существующий.Пример формирования имени файла с версией:
Функция СформироватьИмяФайла(ДокументСсылка) Экспорт
ИмяФайла = "Realization_" + Строка(ДокументСсылка.УникальныйИдентификатор()) +
"_" + Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + ".xml";
Возврат ИмяФайла;
КонецФункции
Для обеспечения надежности передачи на FTP-сервер мы должны использовать механизм временных файлов. Это гарантирует, что принимающая сторона не начнет обрабатывать документ, пока он не будет полностью загружен.
Разберем по шагам правильный алгоритм работы с FTP:
FTPСоединение..tmp.Переместить (Rename) на FTP-сервере, меняя расширение с .tmp на .xml.Этот метод исключает коллизии при чтении файлов сторонними системами.
Посмотрим на ситуацию, когда в одной базе меняются реквизиты (контрагент, дата), а из другой базы приходит результат взвешивания. Если просто "затирать" документ данными из файла, можно потерять актуальную информацию.
Рекомендуем внедрить разделение ответственности за поля. При загрузке XML в базу с результатом взвешивания, система должна обновлять только строго определенные реквизиты (например, "ВесНетто", "ВесТары"), не затрагивая "Организацию" или "Склад", если они управляются в основной базе. Также полезно добавить проверку даты модификации: если документ в базе изменен позже, чем был сформирован XML-файл, загрузку следует пропустить или вывести предупреждение оператору.
Проанализируем предложение из сообщения №5 форума. Обмен через файлы — это асинхронный процесс с задержками. Если бизнес-процесс требует мгновенной реакции (например, весы должны сразу получить данные реализации), стоит рассмотреть HTTP-сервисы или Web-сервисы.
В этом случае при записи документа в Базе А происходит прямой вызов метода в Базе Б. Если База Б успешно приняла данные, она тут же возвращает результат. Это избавляет от необходимости мониторить папки на FTP и решает проблему актуальности данных в режиме реального времени. Статусы в таком случае становятся не нужны, так как обмен происходит синхронно в рамках одного вызова.
Важно: Выбор между файловым обменом и веб-сервисами зависит от стабильности интернет-канала и требований к скорости обмена. Для высоконагруженных систем с весовым оборудованием синхронный обмен через HTTP-сервисы является приоритетным.