«Да я сам за выходные накидаю приложение под ТСД»: анатомия одного архитектурного заблуждения и как устроена платформа для ТСД под капотом
В основу этой статьи легли живые технические воркшопы, которые разработчик платформы Mobile SMARTS Саргис проводил в разных городах — от Новосибирска и Красноярска до Краснодара и Ставрополя, — а также те самые честные кулуарные разговоры с программистами и интеграторами, которые начинаются уже после официальной части, когда выключается проектор и люди подходят со своими реальными болями.
На одном из таких воркшопов произошел показательный диалог. В зале сидела классическая сборная солянка: разработчики 1С и директора небольших франчайзи, авторы самописных учетных систем, опытные интеграторы (уже проходившие базовое обучение и заглянувшие послушать про тонкости написания кода внутри платформы) и пара программистов, которые случайно зашли на огонек с первого дня конференции.
В разгар демонстрации один парень из зала, явно считавший себя хардкорным технарем, скептически поднял руку: — Слушайте, ну это всё понятно, это базовые вещи для широкой публики. А можно в следующий раз придет кодер платформы? Я хочу спросить, как оно внутри устроено. Саргис посмотрел на него, улыбнулся и ответил: — Так я и есть кодер платформы. Какие у вас вопросы? Давайте разбираться, как это работает под капотом.
Они проговорили пятнадцать минут — про объектный слой, XML-схему базы, работу гибридных справочников и механику синхронизации. Скептицизм быстро улетучился: собеседник признал, что слегка недооценил глубину кроличьей норы.
Этот эпизод отлично вскрывает главную детскую болезнь всей индустрии мобильной автоматизации. Когда обычному разработчику — неважно, пишет он на C#, Kotlin, Python или 1С, — прилетает задача «прикрутить терминалы сбора данных (ТСД) к нашей учетной системе», первая мысль в его голове почти всегда звучит одинаково:
«Господи, да что там делать? Экранчик с двумя кнопками, текстовое поле под штрихкод и отправка JSON по REST API на бэкенд. Зачем мне разбираться в какой-то сторонней платформе, если я сам напишу своё приложение и мне там всё будет понятно? Тем более сегодня, с Cursor и Codex!»
И знаете что? Давайте сразу будем честны друг с другом. В некоторых случаях самописка — это действительно рабочее решение.
Если у вас один небольшой магазин или крошечный склад, ровно один ТСД, одна намертво застывшая конфигурация учетной системы, которую никто не обновляет, а в ваших процессах нет (и никогда не будет) обязательной маркировки — открывайте любимую IDE, запускайте ИИ-ассистента, пилите свое мини-приложение и даже не читайте эту статью дальше. Вы справитесь за месяц и забудете об этой задаче. А разгребать за вами эту задачу потом уже будет другой программист, с внутренним миром богаче вашего, которого будет ломать разбираться в вашей разработке (но это уже проблемы бизнеса, а не ваши).
Однако если у вас больше одного терминала, живой растущий бизнес, дырявый складской Wi-Fi, зоопарк штрихкодов от поставщиков или товары, подпадающие под «Честный ЗНАК», — добро пожаловать в реальный мир. Давайте разберем по косточкам и без маркетинговой шелухи, почему «простое приложение для сканера» неизбежно превращается в долгострой, какие архитектурные паттерны лежат внутри зрелой платформы для ТСД (даже без привязки к бренду Клеверенс) и как готовая платформа с коннекторами экономит разработчикам месяцы жизни.
Почему «просто пикнуть штрихкод» превращается в инженерный ад
Чтобы понять, почему самописные клиенты для ТСД так быстро обрастают костылями, нужно начать с фундаментального конфликта двух систем. Разработчики ERP, WMS и учетных систем привыкли мыслить категориями офисного или серверного софта. Но учетная система и мобильный терминал в руках кладовщика решают принципиально разные физические задачи:
-
Задача ERP — аккуратно зафиксировать прошлое. Транзакция уже произошла. Оператор сидит за большим монитором со стабильным интернетом, и у него есть 5–10 минут, чтобы без спешки разнести накладную, сверить реквизиты и провести документ.
-
Задача мобильной платформы на ТСД — управлять настоящим в реальном времени. Транзакция совершается прямо сейчас. Кладовщик стоит в холодном проходе между стеллажами, в одной руке коробка, в другой — терминал. Ему нужно зафиксировать операцию за доли секунды (в идеале — быстрее 0,8 секунды на скан), тут же получить от системы проверку по бизнес-правилам и увидеть следующий шаг маршрута. Мобильное приложение здесь — не «удаленная форма ввода в БД», а навигатор, который ведет работника по процессу и физически отсекает ошибки до того, как они попадут в учетную систему.
Именно поэтому попытки пробросить на ТСД десктопные экраны ERP через удаленный рабочий стол (RDP) или открыть в браузере терминала обычную веб-форму учетки всегда проваливаются: функционально на экране есть всё, но работать на 4-дюймовом дисплее в таком режиме невозможно.
Когда же разработчик решает написать собственный мобильный клиент с нуля, он последовательно наступает на три системные мины.
Мина №1. Реальное складское железо, периферия и ловушка UI-потока
В офисе программист тестирует свое приложение на мощном ноутбуке в эмуляторе или на современном смартфоне. Но на реальных складах работают совсем другие устройства. Самые массовые рабочие лошадки на рынке — это бюджетные и среднебюджетные промышленные терминалы (уровня Atol Smart.Lite, Smart.Prime, Urovo DT40), а на многих предприятиях в строю до сих пор стоят устройства на старых версиях Android (от 5 до 11) и даже терминалы на Windows CE / Windows Mobile.
Попробуйте запустить на бюджетном ТСД приложение, собранное на тяжелом кроссплатформенном фреймворке вроде Flutter или на базе сложного веб-движка (как в современных банковских супераппах или сервисах доставки). Вы обнаружите, что холодный старт такого приложения на слабом процессоре ТСД занимает от 2 до 5 минут. Любой синхронный сетевой вызов или лишняя перерисовка интерфейса в главном потоке мгновенно вешает окно и вызывает ANR (Application Not Responding) — системную плашку «Приложение не отвечает». На практике даже замена простой линейной полоски прогресса (ProgressBar) на обычный крутящийся спиннер в окне загрузки на медленном ТСД отъедает 10–15% времени старта и ускоряет разряд батареи просто за счет лишних вызовов отрисовки.
А дальше начинается аппаратная интеграция. Вам предстоит вручную подружить приложение:
-
со встроенными аппаратными считывателями штрихкодов разных вендоров (у каждого свои broadcast-интенты и SDK);
-
с внешними Bluetooth-сканерами и RFID-считывателями (работающими в том числе по низкоуровневому протоколу LLRP);
-
с мобильными и стационарными принтерами этикеток и чеков, чтобы печатать маркировку напрямую с терминала по Bluetooth или Wi-Fi даже при полном отсутствии связи с сервером;
-
с аппаратной индикацией самого ТСД — звуком и виброоткликом (потому что при потоковом сканировании или работе с прайс-чекером человек ориентируется на звук ошибки, а не вглядывается в экран).
Если писать и поддерживать всё это самому, то, как лаконично заметил Саргис на воркшопе, «можно просто устать». В специализированной платформе весь аппаратный слой уже абстрагирован: перехват сканирования работает в любом визуальном окне из коробки, а управление вибрацией, звуком или записью в системный лог вызывается одной командой встроенного объекта.
Мина №2. Изменчивость среды: «Честный ЗНАК» и обновления учетной системы
Предположим, вы победили железо и через месяц выкатили первую версию своей самописки. Она отлично сканирует линейные штрихкоды и складывает их в вашу базу.
Но через три месяца в бизнес приходят изменения: вводится обязательная маркировка для новой товарной группы (или меняются правила проверки в «Честном ЗНАКе»), поставщики начинают присылать паллеты с агрегированными кодами, а заодно выходит очередное обновление вашей ERP или конфигурации 1С, в котором поменялась структура документов.
Вот здесь самописный проект встает колом. Разработчику приходится «вручную» разбирать спецификации GS1 и DataMatrix, писать логику разделения идентификаторов применения (AI), высчитывать криптохвосты и учить свой парсер понимать, что именно сейчас пикнул кладовщик — пачку молока, бутылку воды или пару обуви, но самое сложное понять к какой товарной группе принадлежит маркированный товар и в этом случае надо пилить еще больше исключений из правил и еще больше интеграций. В платформе эта головная боль снята архитектурно: там уже живет готовый системный объект маркировки, который обновляется вендором платформы. Разработчику не нужно парсить сырую строку символов — после сканирования штрихкода в коде операции сразу доступны готовые типизированные поля марки.
Мина №3. Bus Factor = 1 и стоимость поддержки
У любого кастомного приложения под ТСД, написанного внутри компании на Java, Kotlin или C#, есть фатальная уязвимость: оно держится на том единственном разработчике, который его создал.
Как только этот человек увольняется или переходит на другой проект, бизнес остается один на один с репозиторием, который некому поддерживать. Найти на рынке мобильного разработчика, который согласится разбираться в чужом узкоспециализированном коде складского терминала ради мелких правок бизнес-логики, — задача долгая и экономически нерентабельная.
Анатомия платформенного решения: четыре инженерных паттерна под капотом
Давайте теперь посмотрим на задачу без привязки к брендам, с позиции системной инженерии. Какие архитектурные механизмы отличают специализированную платформу, связывающую парк ТСД и учетную систему, от простого «клиента для REST API»?
Паттерн 1. Эволюция оффлайн-хранения, гибридная БД и парадокс серверного кэша
Проследим, как обычно развивается мысль разработчика, когда он проектирует обмен данными для ТСД.
Первый соблазн — сделать тонкий онлайн-клиент: отсканировал штрихкод →→ отправил HTTP-запрос в ERP →→ получил ответ. В офисе всё работает идеально. Но склад — это клетка Фарадея из металлических стеллажей, бетонных стен и паллет с жидкостями. В мертвых зонах Wi-Fi пакеты теряются, соединение рвется, и тонкий клиент превращается в кирпич.
«Хорошо, — решает архитектор, — делаем Offline-First с локальной базой на устройстве». Но тут выясняется фундаментальное ограничение: для мобильных ОС вроде Android не существует тяжеловесных реляционных СУБД корпоративного класса (уровня Oracle или MS SQL Server), которые умели бы работать локально на слабом мобильном чипе и при этом из коробки обеспечивать двустороннюю репликацию с центральной базой. У вас есть только локальный движок SQLite, а поверх него вам придется самостоятельно спроектировать целый стек синхронизации:
-
Определить, какие справочники нужно держать в памяти ТСД целиком, какие — запрашивать с промежуточного сервера, а за какими обращаться напрямую в ERP.
-
Построить систему версионирования данных и дифференциальной синхронизации, чтобы при обмене передавать только компактные бинарные дельты изменений, а не перекачивать гигабайтные таблицы по слабой сети.
-
Вынести за скобки основных транзакций тяжелые бинарные данные (фотографии товаров, сканы документов), организовав их фоновую покусочную (чанковую) докачку при появлении связи.
-
Реализовать идемпотентность сетевых вызовов при коллективной работе: если связь оборвалась в момент отправки запроса, повторный запрос после реконнекта должен распознаваться по уникальному
GUID, чтобы сервер не создал дубликат документа, а вернул клиенту результат уже выполненной операции.
Именно эта инженерная задача в платформе Mobile SMARTS решена через технологию HYDB (Hybrid Database — гибридная база данных). Под капотом она объединяет локальный движок SQLite, систему XML-метаданных и поисковых индексов (включая тяжелые индексы для быстрого поиска по подстроке), отдельное хранилище бинарных блобов и собственный слой ORM.
Для разработчика прикладного уровня вся эта сложность скрыта: он работает с данными через простые запросы SELECT и транзакции, не задумываясь о физическом расположении записей. В свойствах любой таблицы достаточно задать её поведение:
-
хранится ли она в реляционном формате или в виде XML;
-
выгружается ли таблица на терминал или живет только на сервере (
Server Table); -
разрешен ли для неё прямой внешний вызов в учетную систему (
External Call) и с каким интервалом устаревания кэша (Data Refresh Period).
Практический кейс с воркшопов: ловушка гибридного справочника Саргис рассказывает, что именно на гибридных таблицах у разработчиков чаще всего случается показательный затык. Представьте ситуацию: программист настроил онлайн-обращение к 1С за остатками товара, но одновременно с этим вчера вечером выгрузил справочник остатков из 1С на сервер платформы. За ночь в 1С остаток товара изменился и стал равен 10 штукам, а в выгруженной на сервер платформы таблице со вчерашнего дня осталась лежать старая запись — 5 штук. Утром кладовщик сканирует товар на ТСД. Терминал делает запрос… и показывает на экране 5 штук! Разработчик в недоумении: «Почему он не сходил в 1С, у меня же включен онлайн?!» Ответ кроется в архитектуре разрешения запросов
HYDB: когда мобильный клиент запрашивает данные гибридной таблицы, сервер платформы сначала проверяет свою локальную серверную таблицу. Поскольку запись по этому товару там найдена (пусть и со вчерашним значением 5 штук),HYDBсчитает запрос успешно выполненным и не идет дальше во внешний вызов к ERP, экономя сетевые ресурсы и не нагружая учетную систему. Внешний запрос срабатывает как каскадный fallback тогда, когда локальная выборка вернула пустой результат. Понимание этой цепочки («Локальная БД ТСД →→ БД сервера платформы →→ Внешняя ERP») позволяет тонко управлять тем, какие данные должны кэшироваться, а какие — всегда тянуться вживую.
Паттерн 2. Умное управление объемом данных: Table Slices и Table Extensions
Когда бизнес вырастает до сети магазинов или нескольких распределительных центров, в центральной базе легко накапливается 1 000 000 записей остатков и цен по 10 филиалам. Выгружать весь этот миллион строк на каждый терминал бессмысленно — устройству в конкретном магазине нужны данные только своего филиала.
В платформенной архитектуре эта проблема решается двумя комплементарными механизмами:
-
Нарезка таблиц (
Table Slices): специальный коннектор на сервере (TableSlicerConnector) берет общую таблицу (например,Stock), делит её по указанной колонке (например,WarehouseId) и раскладывает на диске сервера по отдельным физическим подпапкам. Когда конкретный ТСД запрашивает обновление таблицы, на клиенте вычисляется выражение привязки (например,CurrentWarehouse.Id), и сервер отдает терминалу только его персональный срез данных. При этом разработчик сам задает политику обработки ошибок (Error Behavior): что делать, если выражение среза не удалось вычислить — отдать пустой ответ (оставив старые данные) или переслать полную таблицу (понимая риск сетевого шторма). -
Расширения таблиц документа (
Table Extensions): еще более тонкий механизм оптимизации внутриHYDB. Когда на ТСД выгружается конкретный документ задания (допустим, заказ поставщику №10021), прямо внутрь этого экземпляра документа упаковывается микро-таблица расширения (Stock table extension), содержащая остатки, серии и адресные ячейки только по товарам этого конкретного заказа.Инженерная красота здесь в том, что структура колонок (метаданные) расширения на 100% совпадает со структурой основной таблицы
Stock. Прикладной код на ТСД выполняет обычный запрос к таблицеStock, даже не зная о существовании кэша: платформа сама перехватывает обращение и мгновенно отдает данные из локального расширения документа. Если же кладовщик сканирует товар, которого не было в заказе, запрос к расширению возвращает0 записей— и только в этот момент платформа автоматически пробрасывает запрос к серверу или ERP. Более того, в ходе приемки мобильное приложение может дописывать новые строки прямо в это расширение, формируя готовый пакет изменений для последующей синхронизации с бэкендом.
Паттерн 3. Двухсписочная транзакционная модель документа (Expected vs Actual) и контейнерный учет
Новички, пишущие свою первую складскую программу, почти всегда делают в документе одну таблицу товаров: выгружают из ERP плановый список (Товар А — План: 10, Факт: 0) и при каждом скане просто увеличивают число в колонке Факт.
На реальном складе такая схема рушится в первый же день. Почему? Потому что 10 штук Товара А по факту приезжают в двух разных коробках по 5 штук, каждая коробка лежит на паллете со своим уникальным серийным кодом транспортировки (SSCC), у них разные серии, а следом кладовщик вообще сканирует 1 штуку Товара С, которого не было в заказе поставщика. Если вы просто инкрементируете число в одной строке плана, вы безвозвратно теряете детальную структуру принятых грузомест.
Поэтому в платформе документ при конвертации из ERP всегда разделяется минимум на два связанных табличных списка:
-
Expected Items(Плановые строки): исходное задание из ERP (Item A — Expected: 10, Actual: 10;Item B — Expected: 3, Actual: 1;Item C — Expected: 0, Actual: 1). -
Actual Items(Фактические строки): детальная расшифровка каждого скана с тарой, сериями и таймстампами. При этом в каждой строке факта тоже присутствует колонкаExpected Qty, но в ней отражается не вся сумма заказа, а аллоцированная доля плана, приходящаяся конкретно на эту строку факта:
Item Code
Item Name
Expected Qty (доля плана)
Actual Qty (факт)
SSCC (код паллеты/короба)
101
Item A
5 (из 10)
5
10005413119
101
Item A
5 (из 10)
5
10006715311
102
Item B
1 (из 3)
1
—
103
Item C
0 (вне плана)
1
—
В момент каждого скана платформа синхронно обновляет три структуры: «грязную» таблицу сырых сканов, витрину для мгновенного отображения прогресса в UI и итоговую таблицу документа для выгрузки в ERP. Все три записи выполняются внутри одной атомарной транзакции: при любой ошибке происходит полный откат (rollback), поэтому рассогласование между экраном и базой исключено.
Поверх этого работает встроенная модель Упаковок (Packings) с коэффициентами пересчета к базовой единице измерения и Контейнеров (Containers) — индивидуально отслеживаемых паллет, весовых монокоробов и сборных микс-коробов.
Паттерн 4. Декларативные шаблоны штрихкодов (Barcode Data Templates)
В идеальном мире из учебников все товары промаркированы стандартным EAN-13 или GS1-128 с разделителями групп. В реальном мире, как подтверждает Саргис по опыту десятков воркшопов, бизнес обожает изобретать собственные форматы штрихкодов.
Самый частый пример из ритейла и пищевки — весовой EAN-13: внешне это обычный 13-символьный баркод, но его нужно налету распилить на две части: первые цифры кодируют сам товар, по которому нужно сделать поиск в справочнике, а последние 5 или 6 цифр перед контрольной суммой содержат вес конкретной упаковки. Другой пример с производства — внутренние этикетки на коробах без спецсимволов-разделителей, где в одной строке склеены артикул, номер партии и вес: B123456W000250 или P970001S211000101.
Вместо того чтобы писать кастомный парсер на регулярках под каждого клиента, в платформе используются Шаблоны штрихкодов (Barcode Data Templates), состоящие из констант и именованных переменных заданной длины:
P{ProductCode:6}S{SerialNumber:9}
или для сборного микс-короба:
MXD{BoxID:5}Q{Quantity:3}ITM{ItemCode:5}
Как только луч сканера считывает такой штрихкод, ядро платформы автоматически сопоставляет его с зарегистрированными шаблонами, понимает, какой именно объект отсканирован (товар, упаковка, адресная ячейка, документ или определенный тип контейнера), и само раскладывает извлеченные переменные {ProductCode}, {Quantity} или {Weight} в поля операции. А стандартные коды GS1-128 вроде (01)012345678905(10)ABC123(17)231231(30)025 разбираются платформой автоматически вообще без настройки шаблонов.
Практика: как устроена разработка внутри платформы (по следам живых воркшопов)
Посмотрим теперь, с чем сталкивается программист, когда открывает среду разработки платформы (Панель управления Mobile SMARTS), и почему подход с визуальными действиями позволяет собирать рабочие решения в разы быстрее классического кодинга.
Двухуровневая архитектура разработки
Платформа разделяет разработку на два независимых слоя, чтобы простые бизнес-задачи решались за минуты, но при этом у системных программистов не было потолка возможностей:
Слой разработки
Инструментарий и стек
Какие задачи решает
Прикладной уровень (разработка и кастомизация мобильных приложений)
Визуальный редактор действий («стрелочки»), встроенный скриптовый язык с упрощенным C#-подобным синтаксисом, Cleverence Framework, СУБД HYDB
Сборка экранов ТСД, логика переходов, валидация сканов, верстка интерфейса, шаблоны ШК, работа с таблицами и документами
Системный уровень (ядро, тяжелые интеграции и расширения)
C# (.NET Core 6) для сервера и клиентов, JavaScript (React Web) для веб-приложений, SQLite / PostgreSQL, XML, бинарные индексы
Написание собственных внешних коннекторов (Inventory API), серверных расширений, веб-интерфейсов и высоконагруженной логики
Саргис формулирует суть прикладного уровня просто: «Это разработка мобильных приложений с помощью визуальных действий и одновременный инструмент интеграции с учетными системами».
Для разработчиков 1С интерфейс Панели управления оказывается интуитивно знакомым — структура дерева конфигурации создавалась с оглядкой на конфигуратор 1С, но без его избыточной перегруженности. Главное отличие кроется в самом процессе создания форм и алгоритмов: даже в 1С разработчику приходится кодом или ручной привязкой задавать элементы форм, их размеры и обработчики кнопок. В платформе же операция собирается как блок-схема из готовых визуальных действий, соединенных переходами, а внутри каждого действия при необходимости дописывается обычная скриптовая логика — на встроенном языке с сильно упрощенным, лаконичным C#-подобным синтаксисом (без лишних сложных конструкций, которые на ТСД просто не нужны). Прямо в Панели управления по сочетанию клавиш работает встроенный IntelliSense, подсказывающий все доступные свойства и методы внутренних объектов.
Базовый воркшоп-тест: рабочий обмен с учеткой за 3 действия
Чтобы участники воркшопа сразу почувствовали разницу в скорости разработки, первое упражнение делается буквально за пять минут вживую:
-
В Панели управления создается новый Тип документа.
-
В алгоритм документа перетаскиваются всего три визуальных действия:
Сканирование товара→→Ввод количества→→Запись в документ. -
В учетной системе (например, в 1С) в пару кликов клонируется типовой бизнес-процесс и привязывается к только что созданному типу документа.
Никакой возни с сокетами, сериализацией JSON и версткой списков: участник сканирует штрихкод, вводит число — и готовый документ с товаром и количеством уже создан в учетной системе.
А дальше на этой базе разбираются реальные кастомные задачи, ради которых разработчики и приходят на воркшоп.
Кейс 1. Привязка фотографий на ТСД за 2 действия
На одном из первых воркшопов Саргис показал доработку, которая вызвала такой живой отклик у зала, что её включили в обязательную программу всех следующих городов: обязательное фотографирование товара при сборе штрихкодов. Оказывается, многие интеграторы и разработчики даже не подозревали, насколько просто платформа работает с медиафайлами. В существующий алгоритм сканирования добавляются буквально два действия: запрос снимка с камеры на каждый скан и сохранение фотографии. При этом разработчику не нужно думать, как пропихнуть тяжелые JPEG-файлы через слабый складской интернет: HYDB сама отделяет бинарный блоб от легкой структуры документа, передает его на сервер в фоновом режиме по частям и позволяет гибко настроить, куда именно эта фотография должна улететь и где храниться на стороне учетной системы.
Кейс 2. Живая верстка в отладчике и полная стилизация APK через файлы базы
Второй момент, который неизменно удивляет программистов на воркшопах, — то, как в платформе устроено управление внешним видом приложения:
-
Мгновенная разметка внутри окон: на воркшопе в Новосибирске участник попросил показать, как поменять оформление кнопок и шрифтов в документе. Вы запускаете отладку в десктопном эмуляторе
WinClient, открываете свойство кнопки, пишете словамиRed— и кнопка тут же становится красной. Хотите поменять черный текст внутри строки на белый? Оборачиваете текст в простой HTML-подобный тегТекст, и он мгновенно перекрашивается на экране без какого-либо лишнего кода. -
Переопределение главного бургер-меню и цветовых тем без пересборки APK: многие считают, что раз стандартные продукты имеют фиксированные цвета (например, «Склад 15» — оранжевый, «Магазин 15» — красный), а шапка и боковое бургер-меню принадлежат самому Android-клиенту, то изменить их без пересборки APK нельзя. На самом деле в платформе это решено гораздо элегантнее: и палитра цветов всех кнопок, и структура главного бургер-меню могут задаваться внешними файлами стилей и конфигурации, которые лежат на сервере внутри конкретной базы. Когда ТСД подключается к этой базе, эти файлы прилетают на устройство, и мобильный клиент отрисовывает бургер-меню уже не по дефолтному шаблону, зашитому в APK, а по файлу вашей базы. Вы можете самостоятельно, без обращения к вендору, перекрасить интерфейс в корпоративные цвета заказчика, добавить в бургер-меню собственные пункты со своими иконками и повесить на нажатие прямой запуск нужного типа документа.
Кейс 3. Универсальность конструктора: регистрация гостей и печать бейджей за 3 часа
Наконец, самый наглядный ответ на вопрос «разве это не просто узкая программа для складского сканера?» участники видели прямо на входе в зал. Регистрация самих гостей воркшопа, их запись в базу и мгновенная печать именных бейджей на принтере этикеток работали на мобильном приложении, собранном на этой же платформе. Как признается Саргис, всю эту конфигурацию регистратора он написал с нуля «на выходных за три часа под банку пива». Потому что визуальные действия позволяют собирать на Android практически любые прикладные сценарии ввода, обработки и печати данных.
Архитектурный нюанс отладки: почему новички путаются в Hot Reload (WinClient vs Сервер)
Если вы впервые сядете за Панель управления после классических IDE вроде Android Studio или Visual Studio, есть один архитектурный момент, который гарантированно вызовет у вас вопросы. На воркшопах вокруг него регулярно возникают дискуссии.
В привычной мобильной разработке схема линейная: вы запустили эмулятор, изменили код в IDE, нажали Hot Reload — и IDE напрямую подменила файлы внутри работающего эмулятора. В Панели управления Mobile SMARTS вы тоже можете подключить к отладчику живой ТСД или запустить встроенный десктопный эмулятор терминала (WinClient), менять визуальные действия или серверную логику и сразу видеть результат. Но как только вы добавляете новый справочник или меняете структуру таблиц для типа документа, вы замечаете, что в открытом эмуляторе эти данные не появляются до тех пор, пока вы явно не выполните операцию «Обмен».
Почему так происходит? Потому что в Панели управления вы редактируете не файлы внутри мобильного устройства, а конфигурацию самой серверной базы данных платформы. В одном и том же окне редактора вы пишете и серверный код, и клиентский код. Все ваши правки сохраняются в виде XML-файлов конфигурации на сервере. Поэтому, когда вы отлаживаете серверные операции, изменения подхватываются мгновенно — они уже на сервере. А вот клиентское устройство (и эмулятор WinClient, который честно эмулирует работу отдельного терминала) должно получить обновленную структуру и справочники с сервера через штатный механизм синхронизации.
Из этой же архитектуры следует важное практическое правило: хотя вся конфигурация базы физически представляет собой набор текстовых XML-файлов, править эти XML-файлы напрямую в стороннем текстовом редакторе или Visual Studio крайне опасно. Если вы допустите малейшую опечатку или забудете закрыть тег, база при запуске не упадет с фатальной ошибкой, но парсер просто отбросит невалидный узел — и написанные вами операции бесследно исчезнут из приложения. Панель управления тем и ценна, что позволяет безопасно вносить правки и одновременно вести отладку сразу в трех контурах: на сервере, на удаленно подключенном физическом ТСД и в локальном WinClient. (маленькое уточнение от автора -с использованием ИИ это уже кажется лишним и грамотные специалисты научились тупо править файлы).
«А у нас сервера на Linux!»: как устроена работа в Linux-окружении
Отдельная большая тема, которая звучит почти на каждой встрече с корпоративными разработчиками, — работа под Linux. Поскольку демонстрация на воркшопах обычно идет на ноутбуке с Windows, из зала обязательно спрашивают: «У нас в компании все сервера переведены на Linux (Ubuntu, Debian, Astra Linux). Как нам разворачивать платформу и как её конфигурировать, если ваша Панель управления работает только под Windows?»
Здесь нужно четко разделить серверную среду исполнения (Apps Server) и инструмент разработки (Панель управления):
-
Сервер платформы нативно работает на Linux. Серверное ядро написано на
.NET Coreи штатно разворачивается на Linux-серверах (включая отечественные дистрибутивы вроде Astra Linux). Для установки не нужна графическая оболочка: достаточно выполнить в терминале буквально три команды — скачать архив с сайта, распаковать его и запустить консольный установщик. -
Конфигурирование работает удаленно по клиент-серверной схеме. Пытаться запустить десктопную Панель управления или
WinClientнапрямую внутри графической оболочки Ubuntu не нужно — они созданы под Windows-среду. Вместо этого разработчики работают точно так же, как с серверной базой 1С или классической СУБД:-
На Linux-сервере в контейнере или службе разворачивается база платформы и формируется строка подключения.
-
Разработчик копирует эту строку подключения на свою рабочую машину с Windows, вставляет её в Панель управления и подключается к серверной базе по сети.
-
Вся разработка, настройка таблиц и отладка ведутся удаленно с рабочего места инженера, в то время как сама база и серверные операции крутятся на Linux-сервере.
-
А для того чтобы сделать запуск и проверку клиентских форм полностью независимыми от операционной системы, команда платформы сейчас ведет разработку браузерного Web-клиента, который позволит открывать интерфейс терминала прямо в браузере (и станет кроссплатформенной заменой WinClient).
Интеграция с учетными системами: готовые коннекторы, свои велосипеды и «путь здоровой лени»
Переходим к главному вопросу для авторов самописных учетных систем и разработчиков 1С: как именно платформа стыкуется с внешним бэкендом и где проходит граница ответственности между кодом платформы и кодом ERP?
Во-первых, для большинства популярных систем на рынке уже существуют готовые тиражируемые коннекторы: от десятков типовых, отраслевых и облачных конфигураций 1С и МойСклад до iiko, SAP S/4HANA, Microsoft Dynamics (AX 2012 / D365) и Odoo (v13–v17). Во-вторых, сама архитектура интеграции построена так, чтобы подключение любой нестандартной или полностью самописной ERP сводилось к реализации простого, четко описанного контракта.
Архитектура двустороннего обмена и единый Inventory API
В распределенной системе с мобильными терминалами роли «клиента» и «сервера» определяются тем, кто инициирует соединение. Главная аксиома надежности здесь звучит так: сервер никогда не инициирует подключение к мобильному терминалу. ТСД может находиться в спящем режиме, ехать в лифте или лежать вне зоны покрытия Wi-Fi — поэтому сервер платформы (Apps Server) лишь подготавливает данные и ждет, пока мобильный клиент сам выйдет на связь и заберет их.
А вот взаимодействие между сервером платформы и вашей ERP является полноценным двусторонним (2-Way Integration) и может работать по двум моделям:
-
Модель 1 (ERP как сервер данных — рекомендуемый путь): ваша учетная система выставляет наружу стандартный интерфейс Inventory API (набор типовых REST/JSON эндпоинтов для отдачи справочников/документов и приема результатов). Сервер платформы сам обращается к этому API как за данными по расписанию, так и при синхронных онлайн-запросах с ТСД.
-
Модель 2 (ERP как активный инициатор): ваша учетная система сама выступает клиентом, вызывая API сервера платформы, чтобы принудительно выгрузить новое задание на сборку или обновить справочник, а затем забирает готовый результат (например, когда ТСД завершает документ и платформа шлет в учетку сигнал о готовности).
Ключевое инженерное преимущество этого подхода в том, что для Real-Time (онлайн) и Batched (пакетного) обмена используется одна и та же архитектура и один и тот же код коннектора Inventory API. Разработчику не нужно писать две разные интеграции для онлайн-проверок и для ночной выгрузки справочников.
При этом сам обмен данными опирается на документно-ориентированную модель транзакций (Document-Based Transaction Model): вместо того чтобы нагружать ERP сотнями мелких запросов на каждое действие кладовщика, платформа агрегирует все собранные сканы, серии и тару в структурированный документ и передает его в учетную систему одним пакетом.
Таблицы «Бизнес-процессов»: декларативный оркестратор обмена
Чтобы не хардкодить логику преобразования документов внутри интеграционного модуля, в платформе используется механизм Бизнес-процессов (Business Processes).
По сути, таблица бизнес-процессов — это конфигурационный словарь, который связывает три сущности:
-
Исходный документ ERP (
erpSourceDocumentType+erpSourceConfigSettings): какой документ берем из учетной системы (например,PurchaseOrder), каким алгоритмом конвертируем и с какими JSON-параметрами фильтрации ({ "scanLot": true, "allowUnknown": false }). -
Документ мобильного приложения (
mobileAppDocumentType+mobileExecutionSettings): в какой тип документа на ТСД он трансформируется (Receiving Document) и какие правила действуют на устройстве ({ "scanSerialNum": true }). -
Результирующий документ ERP (
erpResultDocumentType+erpResultConfigSettings): какой документ создается или обновляется в ERP по итогам сканирования и с какими настройками алгоритма ({ "highlightDiscrepancies": true }).
Если для выбранного документа в таблице существует только один подходящий бизнес-процесс, терминал подхватывает и запускает его автоматически, просто выводя в шапке подсказку для пользователя. Если же к одному типу документа привязано несколько процессов (например, обычная приемка и приемка с отбраковкой), ТСД автоматически выведет всплывающее меню выбора.
Как один C#-коннектор закрывает 4 разных процесса за счет JSON-конфигурации В архитектурном руководстве платформы приведен отличный пример того, как эта схема экономит время бэкенд-разработчика. Допустим, в вашей облачной учетной системе (будь то кастомная 1С в облаке, веб-система уровня iiko или МойСклад, подключенная через C#-коннектор
InventoryAPI) есть один базовый документ корректировки запасов (Stock Quantity Adjustment), который принимает на вход артикул и разницу количества (QTY Difference). На складе же кладовщики выполняют четыре разные операции:
Выборочный пересчет (
Partial Stock Count): инициируется прямо на ТСД без документа из ERP, считает фактический остаток в ячейке.Полная инвентаризация (
Full Stock Count): идет по выгруженному слепку остатков из ERP.Списание брака (
Write Off): фиксирует только количество разбитого товара.Производство по спецификации (
BOM Execution): списывает сырье и приходует готовую продукцию.Разработчику коннектора не нужно писать четыре разных обработчика. Он пишет один универсальный алгоритм на C#, который смотрит в JSON-поле
erpResultConfigSettingsконкретного бизнес-процесса:
Если в JSON передан параметр
"Adjustment Type": "New Stock Value"(для инвентаризаций), коннектор сам запрашивает из ERP текущий учетный остаток товара, вычитает его из присланного с ТСД факта (QTY Difference = New - Current) и записывает дельту.Если в JSON стоит
"Adjustment Type": "Direct Adjustment"(для списания брака или BOM), коннектор использует количество с ТСД напрямую как готовую дельту и автоматически подставляет нужный комментарий (Memo) и правило расчета себестоимости. Чтобы добавить пятый вариант складской операции, программисту вообще не нужно трогать C#-код — достаточно скопировать строку в таблице бизнес-процессов и поменять JSON-параметры.
Два пути кастомизации: внутри платформы или на стороне своей ERP
Наблюдая за тем, как реальные программисты внедряют и дорабатывают проекты после воркшопов, Саргис выделил два характерных сценария работы.
-
Путь 1 (Логика внутри платформы): если вам нужно отправить внешний REST-запрос к стороннему сервису или обработать данные прямо на сервере Mobile SMARTS, в платформе для этого есть готовые системные объекты и подробные примеры в базе знаний, а для сложной логики — возможность подключить собственные расширения на C#.
-
Путь 2 («Путь здоровой лени» на языке своей учетной системы): большинство разработчиков 1С и авторов собственных ERP рассуждают прагматично: зачем тратить время на изучение синтаксиса REST-запросов внутри новой платформы, если свою учетную систему они знают как свои пять пальцев? Поэтому они разделяют задачи:
-
На стороне платформы делают то, что невозможно сделать в ERP: визуальную верстку экранов под требования заказчика, настройку шаблонов для разбора нестандартных и весовых штрихкодов, управление камерой/сканером и добавление пользовательских полей в документ ТСД.
-
На стороне своей учетной системы (через вызов метода внешней системы и словарь бизнес-процессов) принимают собранные с ТСД данные и уже в привычной среде — в обработке 1С, на Python, C# или ABAP — пишут все внешние HTTP-вызовы, специфические проверки или логику разбиения одного большого заказа на десяток мелких заданий для терминалов.
-
И даже тогда, когда клиенты устраивают в своей учетной базе полный хаос (например, заводят штрихкоды с нарушением всех мыслимых правил, из-за чего падает стандартная коробочная логика), открытая архитектура платформы позволяет решить проблему малой кровью. Саргис вспоминает, как в Ростове, Краснодаре и Ставрополе интеграторы специально приезжали на воркшоп из соседних городов ради одного вопроса: «Клиент наворотил такое в базе, что коробка не взлетает. Нам что, переписывать всю операцию с нуля?». Вместо тотального переписывания мы просто открывали Панель управления, находили нужный шаг в визуальном алгоритме и точечно вставляли туда одно короткое условие-проверку конкретно под аномалию этого клиента. Пять минут работы, нулевая просадка по скорости — и проблема закрыта.
Итог: инженерная матрица выбора «Самописка vs Модуль ERP vs Платформа»
Чтобы свести всё воедино, вот честная сравнительная таблица, по которой можно оценивать трудозатраты перед стартом проекта мобильной автоматизации:
Архитектурный критерий
Кастомная разработка с нуля (Kotlin / Flutter / Мобильная 1С)
Штатные мобильные модули внутри ERP
Специализированная платформа для ТСД
Стартовая скорость (Time-to-Market)
Прототип с ИИ делается быстро, но доводка под реальные ТСД, сеть и периферию съедает месяцы
Быстро только в том случае, если бизнес-процесс на 100% совпадает со стандартной логикой ERP
Простой процесс с выгрузкой в ERP собирается за 3 действия; есть готовые коробочные конфигурации
Работа на слабом железе и в плохом Wi-Fi
Нужно с нуля писать кэширование, дельта-синхронизацию, идемпотентность по GUID и бороться с ANR
Зачастую требуют постоянного онлайна (тонкий клиент / RDP / тяжелый веб) и встают при обрыве связи
Гибридная БД (HYDB), бинарная дельта-синхронизация, Table Slices, Table Extensions и легковесный нативный рендерер
Аппаратный слой, сложные ШК и маркировка
Интеграция каждого SDK сканера, принтера и поддержка изменений «Честного ЗНАКа» ложатся на ваши плечи
Поддерживают только базовые сценарии; кастомные весовые ШК и тара требуют сложной переделки
Поддержка сотен моделей ТСД, принтеров и RFID из коробки; декларативные шаблоны ШК и готовый объект маркировки
Гибкость интеграции с учетной системой
Полный контроль, но весь транспортный уровень и батчинг документов вы пишете сами
Жесткая привязка к одной ERP; кастомизация мобильных экранов крайне ограничена
Готовые коннекторы + открытый Inventory API для самописных систем; бизнес-логику можно писать как в платформе, так и на языке своей ERP
Сопровождение и Bus Factor
Критическая зависимость от автора кода; дорогой поиск замены при увольнении
Требуются дорогие профильные разработчики конкретной ERP
Наглядный визуальный граф действий + простой C#-подобный скриптовый синтаксис со встроенными подсказками
Когда в финале интервью мы спросили Саргиса, что бы он посоветовал разработчикам, которые смотрят на платформу со стороны и сомневаются, стоит ли тратить время на знакомство с ней, он ответил очень точно:
«Не пугайтесь, если в первый момент вы увидите непривычные визуальные действия со стрелочками и незнакомые названия внутренних объектов. Попробуйте залезть чуть глубже под капот, поэкспериментируйте с версткой, стилями, шаблонами штрихкодов и гибридными справочниками. Вы быстро увидите, что это не просто закрытая «программа для сканирования на складе», а универсальный визуальный конструктор, который берет на себя всю грязную низкоуровневую рутину и оставляет вам чистое инженерное творчество».
А как вы решаете задачу подключения ТСД к своим учетным системам? Пилили свой клиент с нуля или используете готовую платформу? Делитесь своим опытом и набитыми шишками в комментариях!
Источник: habr.com