Improve CarPass product UX and service flows

This commit is contained in:
VPN SaaS Dev
2026-05-14 19:33:25 +09:00
parent b85db333d8
commit caa5f6d3db
36 changed files with 1836 additions and 366 deletions

218
README.md
View File

@@ -1,205 +1,35 @@
# Drivers Bot
# CarPass
Telegram bot + Telegram Mini App для учета автомобилей, заправок, сервиса, жидкостей, напоминаний и стоимости владения.
CarPass — цифровой паспорт автомобиля в Telegram. Он помогает владельцу видеть реальную стоимость владения, вести сервисную историю и аккуратно собирать данные, которые повышают доверие к автомобилю.
## Состав
## Для автовладельца
- `app/` - FastAPI API, статика Mini App, бизнес-логика и Alembic.
- `bot/` - aiogram 3 бот, который открывает Mini App и работает с API через внутренний токен.
- `web/` - статический frontend Telegram WebApp.
- `alembic/` - миграции PostgreSQL.
- `tests/` - базовые security/API тесты.
- Все автомобили в одном гараже.
- Заправки, ТО, ремонт, страховка, налоги, штрафы, парковки, мойки и другие расходы.
- Стоимость владения за период, стоимость 1 км и прогноз ближайших расходов.
- Расход топлива по корректным полным бакам.
- Мягкий прогресс заполнения профиля авто: VIN, госномер, пробег, масло, параметры обслуживания.
- Бейджи качества истории без игровых очков и токсичных рейтингов.
- Напоминания о ТО, страховке и важных событиях.
- OCR чеков: фото или файл распознается, затем пользователь проверяет данные перед сохранением.
## Production Mini App
## Для СТО
Для production Mini App должен открываться только по публичному HTTPS-домену. Для текущего проекта:
- Регистрация автосервиса через Mini App.
- Заявка на проверку и статус модерации.
- Публичная карточка СТО после подтверждения.
- Отзывы, рейтинг и ответы сервиса.
- Запрос доступа к конкретному автомобилю только с подтверждением владельца.
- Добавление визитов, работ и рекомендаций с аудитом действий.
```text
https://drivers.smartsoltech.kr
```
## Безопасность данных
В BotFather нужно выполнить:
CarPass не раскрывает историю автомобиля по одному VIN или госномеру. СТО видит только разрешенный владельцем объем данных: базовую карточку, историю обслуживания или полный доступ. Любые чувствительные изменения, включая VIN, номер, пробег и технические параметры, проходят подтверждение владельца.
```text
/setdomain
@your_bot_username
drivers.smartsoltech.kr
```
## Telegram Mini App
Важно:
Mini App открывается через кнопку внутри Telegram-бота. Так Telegram передает защищенную авторизацию, а гараж привязывается к аккаунту пользователя. Если страницу открыть напрямую в браузере, CarPass покажет понятное приглашение открыть приложение через Telegram.
- в BotFather указывается домен без `https://`;
- `WEBAPP_URL` или `PUBLIC_WEBAPP_URL` в `.env` должны быть `https://drivers.smartsoltech.kr`;
- нельзя использовать `localhost`, `127.0.0.1`, внутренний IP или `http://` для Telegram Mini App в production;
- если появляется `Bot domain invalid`, сначала проверь `/setdomain` и значение `WEBAPP_URL` в контейнере бота.
## Почему это полезно
## Production .env
```dotenv
POSTGRES_DB=drivers
POSTGRES_USER=drivers
POSTGRES_PASSWORD=change-this-db-password
POSTGRES_PORT=5433
DATABASE_URL=postgresql+asyncpg://drivers:change-this-db-password@db:5432/drivers
BOT_TOKEN=123456:telegram-token
BOT_USERNAME=your_bot_username
WEBAPP_URL=https://drivers.smartsoltech.kr
PUBLIC_WEBAPP_URL=https://drivers.smartsoltech.kr
API_BASE_URL=http://api:8000
CORS_ORIGINS=https://drivers.smartsoltech.kr,https://t.me
INTERNAL_API_TOKEN=change-this-long-random-token
APP_ENV=production
ALLOW_DEV_AUTH=false
VAPID_PUBLIC_KEY=
```
`BOT_TOKEN`, `DATABASE_URL`, `WEBAPP_URL`, `API_BASE_URL`, `CORS_ORIGINS`, `INTERNAL_API_TOKEN` читаются только из env. Секреты не хранятся в коде.
## Nginx
Пример reverse proxy:
```nginx
server {
listen 80;
server_name drivers.smartsoltech.kr;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name drivers.smartsoltech.kr;
ssl_certificate /etc/letsencrypt/live/drivers.smartsoltech.kr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/drivers.smartsoltech.kr/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
```
## Запуск
```bash
cp .env.example .env
docker compose up -d --build
```
API локально: `http://localhost:8000`.
Локальные проверки:
```bash
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest -q
.venv/bin/ruff check app bot tests
docker compose build
docker compose up -d db api
curl http://127.0.0.1:8000/health
docker compose down
```
## Авторизация API
Пользовательские endpoint-ы требуют Telegram WebApp `initData` в заголовке:
```http
X-Telegram-Init-Data: query_id=...&user=...&auth_date=...&hash=...
```
Backend проверяет подпись Telegram, создает/обновляет пользователя и разрешает операции только с объектами владельца. Бот использует `INTERNAL_API_TOKEN` и `X-Telegram-User-Id`.
Публичное `/api/users` закрыто внутренним токеном. Для Mini App создание пользователя выполняется через `/api/users/webapp-auth`.
## Основные endpoint-ы
- `GET /api/users/me`
- `GET /api/me`
- `GET /api/my/vehicles`
- `POST /api/my/vehicles`
- `PATCH /api/my/vehicles/{vehicle_id}`
- `GET /api/my/vehicles/{vehicle_id}/service-history`
- `POST /api/my/vehicles/{vehicle_id}/grant-service-access`
- `POST /api/cars`, `GET /api/cars`, `GET/PATCH/DELETE /api/cars/{id}`
- `POST /api/fuel`, `GET /api/cars/{car_id}/fuel?limit=50&offset=0`
- `PATCH /api/fuel/{id}`, `DELETE /api/fuel/{id}`
- `POST /api/service`, `GET /api/cars/{car_id}/service?limit=50&offset=0`
- `PATCH /api/service/{id}`, `DELETE /api/service/{id}`
- `GET /api/cars/{car_id}/stats`
- `GET /api/users/{user_id}/reminders?limit=50&offset=0`
- `POST /api/service-centers`
- `GET /api/service-centers/my`
- `POST /api/service-centers/{id}/verification`
- `POST /api/service-centers/{id}/employees/invite`
- `GET /api/service-centers/{id}/visits`
- `POST /api/service-centers/{id}/visits`
- `POST /api/service-visits/{id}/work-items`
- `POST /api/service-visits/{id}/complete`
- `POST /api/service-visits/{id}/confirm`
- `POST /api/service-visits/{id}/dispute`
- `POST /api/service-visits/{id}/vehicle-change-requests`
- `POST /api/vehicle-change-requests/{id}/approve`
- `POST /api/vehicle-change-requests/{id}/reject`
- `GET /api/admin/service-centers/pending`
- `POST /api/admin/service-centers/{id}/verify`
- `POST /api/admin/service-centers/{id}/reject`
- `POST /api/admin/service-centers/{id}/suspend`
- `GET /api/admin/audit-log`
- `GET /api/admin/disputes`
- `POST /api/ocr/parse-text-receipt`
- `POST /api/ocr/license-plate`
- `POST /api/ocr/vin`
- `POST /api/ocr/service-document`
- `GET /api/me/achievements`
- `GET /api/my/vehicles/{vehicle_id}/score`
- `GET /api/my/vehicles/{vehicle_id}/timeline`
- `GET /api/service-centers/{service_center_id}/trust-score`
CarPass quality and trust scores are backend-owned. The scoring engine in `app/services/scoring.py` calculates vehicle profile completeness, verified maintenance history, maintenance health, service-center trust, evidence-style achievements, and cooldown-protected engagement events. Frontend only displays the result.
Расход топлива считается по интервалам между полными баками (`is_full_tank=true`). Если данных мало, API возвращает `null`, а не выдуманную цифру.
## OCR
Настоящий OCR по фото/PDF пока не подключен. Endpoint `POST /api/ocr/parse-text-receipt` честно разбирает только текстовый чек. Старый `/api/ocr/fuel-receipt` оставлен как deprecated-совместимость.
Новая OCR-архитектура использует заменяемый provider:
- `OCRProvider`
- `StubOCRProvider`
- будущие `TesseractOCRProvider`, cloud OCR или VLM provider
OCR возвращает кандидаты и не меняет данные автомобиля напрямую:
```json
{
"recognized_text": "VIN KMHCT41BAHU123456",
"candidates": [
{"type": "vin", "value": "KMHCT41BAHU123456", "confidence": 0.84}
]
}
```
## Platform Roadmap
Проектное расширение в сторону владельцев авто и СТО описано в `PROJECT_PLAN.md`. В код добавлен первый совместимый слой платформы:
- расширенный `ServiceCenter`;
- верификация СТО;
- сотрудники СТО;
- `VehicleAccess`;
- `ServiceVisit`;
- `ServiceWorkItem`;
- `VehicleDataChangeRequest`;
- `AuditLog`;
- нормализация VIN и госномера.
СТО не получает персональные данные владельца по VIN/номеру. Поиск возвращает только минимальную маскированную карточку и пишет действие в аудит. Критичные изменения автомобиля проходят через запрос подтверждения владельцем.
Для владельца CarPass превращает хаотичные чеки и заметки в понятную картину расходов и обслуживания. Для сервиса это аккуратный канал взаимодействия с клиентом, подтвержденная история работ и доверие без лишнего доступа к персональным данным.