Справочный пример. Это иллюстративная архитектура и контрольный список объёма работ, а не проверенный проект клиента или измеренное внедрение. Технологии, объём интеграции и результаты поставки согласуются для конкретного задания.
Сценарий и ограничения
Логистический оператор заменяет диспетчеризацию в электронных таблицах и ручное выставление счетов. Архитектуру определяют два ограничения: водители работают в районах без стабильного сигнала, а каждая строка счета должна быть обоснованной, если клиент её оспаривает. Поэтому система опирается на журнал событий только для добавления как на источник достоверных данных, а не на столбец статуса, который может перезаписать любой пользователь.
Архитектура
Уровни и зоны ответственности
| Уровень | Технология | Зона ответственности |
|---|---|---|
| Веб-система операций | Vue 3 + Element Plus | Приём заказов, диспетчерская доска, обработка исключений, проверка счетов. |
| Приложение водителя | Android (Kotlin), с поддержкой работы без подключения | Список заданий, сканирование, фото, подпись и фиксация статуса. Всё сначала записывается локально и загружается при наличии подключения. |
| Портал клиента | Мини-программа WeChat | Самостоятельное отслеживание; следует измерять любое изменение объёма запросов, а не предполагать его сокращение. |
| API | Go + Gin | Проверка данных, правила диспетчеризации, приём событий, расчёт начислений. |
| Хранилище | MySQL | Грузовые отправления, события, расчёты. Таблица событий доступна только для добавления и является системным источником записи. |
| Кэш / очередь | Redis | Кэширование диспетчерской доски, устранение дубликатов загрузок, фоновые задания для выставления счетов и уведомлений. |
| Файлы | Объектное хранилище | Фотографии и подписи, подтверждающие доставку, с обращением по ключу вместо хранения в базе данных. |
Модель данных
В приведённых ниже таблицах зафиксированы правила, от которых зависит всё остальное. Ошибки в них превращают работающую демонстрацию в систему, которую невозможно расширять.
Основные сущности
| Сущность | Ключевые поля, связи и правила |
|---|---|
| consignment | Запись об отправлении: стороны, адреса, тип услуги, временные окна, заявленные вес и объём, а также согласованная при приёме основа расчёта цены. |
| shipment_event | Только для добавления, с отметкой времени, оператором, местоположением, типом события и полезной нагрузкой. Текущий статус выводится из последнего события, а не хранится отдельно — именно это делает временную шкалу обоснованной при споре. |
| task / assignment | Назначение водителя и транспортного средства с последовательностью остановок, а также история переназначений при передаче задания. |
| pod_asset | Подтверждение доставки: ключи фотографии и подписи, время фиксации и местоположение устройства, хранящиеся как доказательства для выставления счета. |
| charge / invoice | Строки начислений, сформированные правилами на основе записанных событий; каждая содержит идентификатор события, которым обосновано начисление. Строка счета без отслеживаемого события отклоняется по замыслу системы. |
| rate_card | Правила ценообразования для конкретного клиента по весу, объёму, расстоянию, времени ожидания и надбавке; версии сохраняются, чтобы исторические счета продолжали воспроизводить исходные суммы. |
Ключевые интерфейсы
Конечные точки, содержащие бизнес-правила
| Конечная точка | Назначение и замечания по параллельной работе |
|---|---|
| POST /api/v1/consignments | Приём заказа с геокодированием адреса и подбором применимой тарифной карты в момент создания, чтобы основа расчёта цены была зафиксирована до выполнения задания. |
| POST /api/v1/events/batch | Пакетная загрузка событий из приложения водителя после перерыва в подключении. Дубликаты устраняются по UUID события на стороне клиента, а время фиксации хранится отдельно от времени получения, чтобы временная шкала оставалась достоверной. |
| POST /api/v1/tasks/{id}/pod | Загружает подпись и фотографии вместе со временем фиксации и возвращает ключи хранилища, привязываемые к отправлению. |
| POST /api/v1/billing/run | Формирует строки начислений по событиям за период. Идемпотентность обеспечивается для каждой пары (клиент, период), поэтому повторный запуск исправляет результат, а не создаёт дубликаты. |
| GET /api/v1/track/{no} | Публичное отслеживание с кэшированием, показывающее только доступную клиенту часть событий. |
Технические решения
- События как источник достоверных данных, статус как производное значение. Редактируемый столбец статуса утрачивает историю, от которой зависит разбор споров. Вычисление статуса требует join, но обеспечивает полный и обоснованный аудиторский след.
- Время фиксации и время получения хранятся отдельно. Сканирование водителем в 14:02, загруженное в 17:30, должно отображаться как 14:02 с известной задержкой загрузки; иначе каждая зона без подключения создаёт неверную временную шкалу.
- UUID событий, создаваемые клиентом. Повторные загрузки нормальны при плохом подключении, поэтому устранение дубликатов должно выполняться по идентификатору, которым управляет клиент.
- Версионирование тарифных карт вместо редактирования. Изменение цены не должно незаметно переписывать счета за прошлый месяц, поэтому старые версии сохраняются, а исторические начисления продолжают ссылаться на них.
- Начисления формируются, но не выставляются автоматически. Правила охватывают рассчитываемые случаи; всё, что требует человеческого суждения, попадает в очередь проверки, а не принудительно включается в автоматизацию.
Гипотетические целевые показатели проектирования
Приведённые ниже значения являются гипотетическими примерами для планирования ёмкости, а не измеренными результатами клиента, подтверждённой рекомендацией по конфигурации или SLA. Определите целевые показатели приёмки для конкретного проекта после описания нагрузки, устройств, данных, оборудования и зависимостей от сторонних систем; проверьте их на пилоте и нагрузочных испытаниях до принятия целевого показателя для промышленной эксплуатации.
Целевые показатели ёмкости и производительности
| Целевой показатель | Значение и допущение |
|---|---|
| Приём событий | Пакеты до нескольких сотен событий за одну загрузку, с устранением дубликатов; объём рассчитан на пакет событий после возвращения водителя из нескольких часов без подключения. |
| Диспетчерская доска | Отображает активный рабочий набор менее чем за 1 секунду, используя серверную фильтрацию и разбиение на страницы вместо загрузки всего набора в браузер. |
| Запуск выставления счетов | Месяц событий для одного клиента обрабатывается как фоновое задание с отображением прогресса; время выполнения масштабируется вместе с объёмом событий и измеряется на ваших реальных данных во время приёмки. |
| Загрузка фотографий | Сжимать и ставить в локальную очередь перед загрузкой, повторять попытку при сбое, а также проверять хранение, подтверждение и восстановление на фактических устройствах. |
Что входит в поставку
- Исходный код веб-системы операций, серверной части на Go, приложения водителя для Android и мини-программы
- Схема базы данных с описанием таблиц событий и расчётов, а также история миграций
- Документация API, включая контракт загрузки в автономном режиме и устранения дубликатов
- Примечания по развёртыванию, конфигурация объектного хранилища, процедура резервного копирования и восстановления
- План миграции данных из существующих электронных таблиц с отчётом о сверке после импорта
Планирование для вашего бизнеса
Описанные выше модули — отправная точка, а не фиксированный пакет. Обычно мы сокращаем первый выпуск до одного основного рабочего процесса и одного административного процесса, а затем расширяем его, когда реальное использование показывает фактические места нагрузки и нестандартных случаев. Отправьте описание объёма работ, и мы сопоставим его с этой архитектурой и сообщим, какие части пока не нужны.

