# Logiflow Бэкенд для логистической платформы. Управление заказами на перевозку, водителями, транспортом и складами. При создании заказа строится реальный маршрут через OSRM, считается стоимость перевозки, трекинг водителя в реальном времени через WebSocket. - **Backend:** [github.com/anxi0uz/logiflow](https://github.com/anxi0uz/logiflow) - **Frontend:** [github.com/siers22/logiflow-frontend](https://github.com/siers22/logiflow-frontend) - **Демо:** [logiflowadvanced.online](https://logiflowadvanced.online) > Демо развёрнуто в Kubernetes (k3s). ## Стек **Backend:** - **Go 1.25** — Chi v5, oapi-codegen, pgx/v5, go-redis, errgroup - **PostgreSQL** — миграции через Goose - **Redis** — хранение JWT access/refresh токенов - **Nominatim** — геокодинг адресов (OpenStreetMap, без ключа) - **OSRM** — построение маршрутов и расчёт дистанции - **Prometheus + Grafana** — мониторинг HTTP метрик - **Podman** — контейнеризация **Frontend:** - Репозиторий: [github.com/siers22/logiflow-frontend](https://github.com/siers22/logiflow-frontend) ## Запуск ### Зависимости **Linux:** - [Podman](https://podman.io/docs/installation) + [podman-compose](https://github.com/containers/podman-compose) ```bash # Arch sudo pacman -S podman pip install podman-compose # Или yay -S podman-compose # Ubuntu/Debian sudo apt install podman pip install podman-compose ``` **Windows:** - [Docker Desktop](https://www.docker.com/products/docker-desktop/) — включает docker-compose --- ### 1. Клонировать репозиторий ```bash git clone https://github.com/anxi0uz/logiflow.git cd logiflow ``` --- ### 2. Заполнить `.env` В корне проекта уже есть `.env` — просто заполни значения: ```env LOGIFLOW_DATABASE_USER=logiflow LOGIFLOW_DATABASE_PASSWORD=yourpassword LOGIFLOW_DATABASE_NAME=logiflow LOGIFLOW_REDIS_PASSWORD=yourredispassword LOGIFLOW_JWT_KEY=your-secret-jwt-key-min-32-chars ``` > `LOGIFLOW_JWT_KEY` — любая случайная строка, минимум 32 символа. --- ### 3. Создать сеть (только Linux / Podman) ```bash podman network create LogiflowNetwork ``` На Windows Docker создаёт сеть автоматически — этот шаг пропускай. --- ### 4. Запустить **Linux (Podman):** ```bash make up # запуск make build-up # пересборка образа + запуск make down # остановка make deploy # pull + пересборка + запуск (для деплоя) ``` **Windows (Docker):** ```bat docker compose up -d docker compose build && docker compose up -d docker compose down ``` Миграции БД применяются **автоматически** при старте приложения — делать ничего не нужно. --- ### 5. Проверить Открыть в браузере `http://localhost:3001/metrics` — если страница отвечает, сервер поднят. ## Тестовые данные Миграция `20260502120000_seed_test_data.sql` заполняет БД тестовыми данными автоматически при старте. Все пароли — `1`. | Email | Пароль | Роль | Имя | |---|---|---|---| | `admin@logiflow.ru` | `1` | admin | Александр Петров | | `manager.anna@logiflow.ru` | `1` | manager | Анна Смирнова (склад Москва) | | `manager.igor@logiflow.ru` | `1` | manager | Игорь Козлов (склад СПб) | | `driver.mikhail@logiflow.ru` | `1` | driver | Михаил Соколов — Газель Next, available | | `driver.dmitry@logiflow.ru` | `1` | driver | Дмитрий Новиков — MAN TGX, on_trip | | `driver.sergey@logiflow.ru` | `1` | driver | Сергей Волков — Ford Transit, available | | `kate@example.com` | `1` | client | Екатерина Морозова | | `alexey@example.com` | `1` | client | Алексей Попов | Также создаются 3 склада (Москва, СПб, Новосибирск), 3 машины, 5 заказов во всех статусах (`pending`, `assigned`, `in_transit`, `delivered`, `cancelled`) с реальными OSRM-маршрутами. --- ## Сервисы | Сервис | Адрес | |---|---| | API | `http://localhost:3001` | | Grafana | `http://localhost:3000` | | Prometheus | `http://localhost:9090` | | Метрики | `http://localhost:3001/metrics` | ## Конфигурация Конфиг читается из `configs/config.toml`, переменные окружения с префиксом `LOGIFLOW_` перекрывают файл. ```toml [server] host = "0.0.0.0" port = 3001 readTimeout = "10s" writeTimeout = "30s" idleTimeout = "60s" [redis] refreshTokenTTL = "168h" accessTokenTTL = "24h" [pricing] baseFee = 500.0 # базовая ставка, руб perKm = 25.0 # руб/км perKg = 3.0 # руб/кг perM3 = 150.0 # руб/м³ ``` Цена заказа считается по формуле: ``` total = baseFee + distance_km * perKm + weight_kg * perKg + volume_m3 * perM3 ``` ## Роли | Роль | Возможности | |---|---| | `client` | Создаёт и отменяет свои заказы, следит за статусом | | `driver` | Меняет свой статус, видит назначенные заказы, двигает статус in_transit/delivered | | `manager` | Назначает водителей на заказы, управляет статусами, смотрит отчёты | | `admin` | Создаёт профили водителей, видит всё | Клиенты регистрируются через `POST /auth/register`. Роль назначается вручную в БД. Водителей создаёт `admin`, менеджеров — авторизованный пользователь. ## Авторизация JWT (HS256) + refresh токены. Access токен живёт 24 часа, refresh — 7 дней в HTTP-only cookie. Оба хранятся в Redis — при логауте удаляются. ``` Authorization: ``` ## API ### Auth | Метод | Путь | Описание | |---|---|---| | POST | `/auth/register` | Регистрация клиента | | POST | `/auth/login` | Вход, получение токенов | | POST | `/auth/logout` | Выход, инвалидация токенов | | POST | `/auth/refresh` | Обновление access токена | ### Пользователь | Метод | Путь | Описание | |---|---|---| | GET | `/me` | Профиль текущего пользователя | | PATCH | `/me` | Обновить имя, аватар, пароль | | DELETE | `/me` | Удалить аккаунт | | GET | `/me/trips` | История поездок (driver) | ### Заказы | Метод | Путь | Описание | |---|---|---| | GET | `/orders` | Список заказов (по роли) | | POST | `/orders` | Создать заказ | | GET | `/orders/{id}` | Получить заказ | | DELETE | `/orders/{id}` | Отменить заказ | | PATCH | `/orders/{id}/status` | Обновить статус | | GET | `/orders/{id}/route` | Маршрут заказа | | GET | `/orders/{id}/route/ws` | WebSocket трекинг | ### Водители | Метод | Путь | Описание | |---|---|---| | GET | `/drivers` | Список водителей | | POST | `/drivers` | Создать водителя (admin) | | GET | `/drivers/{slug}` | Получить водителя | | PUT | `/drivers/{slug}` | Обновить водителя | | DELETE | `/drivers/{slug}` | Удалить водителя | | PATCH | `/drivers/me/status` | Обновить свой статус (driver) | ### Менеджеры | Метод | Путь | Описание | |---|---|---| | GET | `/managers` | Список менеджеров | | POST | `/managers` | Создать менеджера | | GET | `/managers/{slug}` | Получить менеджера | | DELETE | `/managers/{slug}` | Удалить менеджера | ### Склады | Метод | Путь | Описание | |---|---|---| | GET | `/warehouses` | Список складов | | POST | `/warehouses` | Создать склад | | GET | `/warehouses/{slug}` | Получить склад | | PUT | `/warehouses/{slug}` | Обновить склад | | DELETE | `/warehouses/{slug}` | Удалить склад | ### Транспорт | Метод | Путь | Описание | |---|---|---| | GET | `/vehicles` | Список ТС | | POST | `/vehicles` | Добавить ТС | | GET | `/vehicles/{slug}` | Получить ТС | | PUT | `/vehicles/{slug}` | Обновить ТС | | DELETE | `/vehicles/{slug}` | Удалить ТС | ### Отчёты | Метод | Путь | Описание | |---|---|---| | GET | `/reports/orders` | Отчёт по заказам (manager) | | GET | `/reports/dashboard` | Дашборд (manager) | ### Уведомления | Метод | Путь | Описание | |---|---|---| | GET | `/notifications` | Список уведомлений | | PATCH | `/notifications/{id}/read` | Отметить прочитанным | ## Флоу заказа ``` Клиент создаёт заказ (адреса → Nominatim → координаты → OSRM → маршрут) ↓ Менеджер назначает водителя (pending → assigned) ↓ Водитель начинает поездку (assigned → in_transit) ↓ Трекинг по WebSocket — current_index двигается по массиву координат ↓ Водитель завершает (in_transit → delivered) ``` ## Архитектура ``` cmd/ └── main.go — точка входа, инициализация зависимостей internal/ ├── api/ — OpenAPI спека + сгенерированный oapi-codegen код ├── config/ — загрузка конфига (TOML + ENV) ├── database/ — подключение к PostgreSQL и Redis, запуск миграций ├── handler/ — HTTP хендлеры (Chi), WebSocket хаб, Prometheus middleware ├── models/ — структуры БД └── services/ — бизнес-логика (OrderService: создание заказа, статусы, дашборд) pkg/ ├── storage.go — generic CRUD поверх pgx (GetOne, GetAll, Create, Update) └── geocode/ — клиенты Nominatim (геокодинг) и OSRM (маршруты) migrations/ — SQL миграции Goose, применяются автоматически при старте configs/ — config.toml, prometheus.yml, datasources Grafana ``` **Слои и зависимости:** ``` HTTP-запрос → Chi router → Auth middleware (JWT → Redis) → Handler → Service (бизнес-логика, внешние API) → pkg/storage (generic SQL) → PostgreSQL ``` **Внешние сервисы:** - **Nominatim** — геокодинг адресов при создании заказа и склада - **OSRM** — построение маршрута и расчёт дистанции/времени - **Redis** — хранение access/refresh токенов, инвалидация при логауте - **Prometheus** — сбор метрик с `/metrics` - **Grafana** — дашборд метрик ![Architecture scheme](docs/infra.jpg) ## Структура БД ![DB Schema](docs/db.jpg) ## Мониторинг Prometheus собирает метрики с `/metrics`. Grafana доступна на `localhost:3000` (admin/admin). Доступные метрики: - `logiflow_http_requests_total` — кол-во запросов по методу, пути, статусу - `logiflow_http_duration_seconds` — latency запросов Конфиг Prometheus: `configs/prometheus.yml` Datasource Grafana: `configs/datasources/` ## Тесты Юнит тесты хендлеров через `httptest` без реальной БД: ```bash go test ./tests/... ```