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