Initial commit

This commit is contained in:
marianesaldana
2026-05-23 08:59:34 -06:00
commit 80dbd947e5
36446 changed files with 3729147 additions and 0 deletions

261
docs/API.md Normal file
View File

@@ -0,0 +1,261 @@
# API REST — Referencia
> Base URL: `http://10.82.68.125:8000/api/v1` · Docs interactivos: `http://localhost:8000/docs`
Todos los endpoints (excepto `/auth/*`) requieren header:
```
Authorization: Bearer <JWT_TOKEN>
```
---
## 🔐 Autenticación
### POST `/auth/register`
Crea un usuario nuevo (rol CIUDADANO por defecto).
**Request:**
```json
{ "full_name": "Juan Pérez", "email": "juan@example.com", "password": "secret123" }
```
**Response 201:**
```json
{ "access_token": "eyJ...", "token_type": "bearer", "role": "CIUDADANO" }
```
### POST `/auth/login`
**Request:**
```json
{ "email": "demo@celaya.gob.mx", "password": "Celaya2026" }
```
**Response 200:**
```json
{ "access_token": "eyJ...", "token_type": "bearer", "role": "CIUDADANO" }
```
**Response 401:** `{"detail": "Credenciales inválidas"}`
### POST `/auth/oauth`
Login/registro vía OAuth (Google, Facebook, Apple).
```json
{ "provider": "google", "oauth_id": "abc123", "email": "juan@gmail.com", "full_name": "Juan", "push_token": "..." }
```
### GET `/me`
Devuelve el usuario actual.
**Response:** `{ "id": 1, "full_name": "...", "email": "...", "role": "CIUDADANO" }`
---
## 🏠 Domicilios (`/addresses`)
### GET `/addresses/`
Lista tus domicilios.
**Response:** `[{"id":1, "label":"Casa", "street":"...", "lat":20.5, "lng":-100.8, "route_id":"RUTA-01", "is_default":true}, ...]`
### POST `/addresses/`
Crea un domicilio. Si pasas `lat`/`lng`, se asigna ruta automáticamente.
```json
{ "label": "Casa", "street": "Hidalgo 245", "colony": "Centro", "lat": 20.5215, "lng": -100.8142, "is_default": true }
```
### PATCH `/addresses/{id}`
Actualiza un domicilio. Solo campos modificados.
```json
{ "is_default": true }
```
### DELETE `/addresses/{id}` → 204
---
## ⏰ ETA (`/eta`)
### GET `/eta/address/{id}` — núcleo del sistema
**Privacy-by-design:** nunca devuelve coordenadas del camión.
**Response 200:**
```json
{
"status": "EN_CAMINO",
"message": "El camión llegará a tu zona entre las 7:20 y 7:35",
"eta_minutes": 12,
"window_start": "07:20",
"window_end": "07:35",
"progress": 45.2,
"route_name": "Zona Centro - Las Arboledas",
"passes_today": true
}
```
**Estados posibles:**
- `PROGRAMADO` — la ruta aún no empieza hoy
- `EN_CAMINO` — el camión va en ruta
- `LLEGANDO` — faltan ≤10 minutos
- `PASO` — ya pasó por la zona
- `NO_SERVICIO` — no aplica hoy
### GET `/eta/schedule/{address_id}`
Devuelve días y horario aproximado.
```json
{ "route_id":"RUTA-01", "route_name":"Zona Centro - Las Arboledas",
"days_of_week":["Lunes","Miércoles","Viernes"], "approximate_time":"06:00 - 07:40",
"truck_id": 101 }
```
### POST `/eta/rate`
Califica el servicio.
```json
{ "address_id": 1, "rating": 5, "comment": "Excelente puntualidad" }
```
---
## 📋 Reportes ciudadanos (`/reports`)
### POST `/reports/`
Crea un reporte con folio único.
```json
{ "address_id": 1, "report_type": "NO_PASO", "description": "El camión no pasó hoy" }
```
**Response 201:**
```json
{ "id":5, "folio":"MRL-20260523-F6EC92", "status":"PENDIENTE",
"report_type":"NO_PASO", "description":"...", "created_at":"...", "address_label":"Casa" }
```
**Tipos:** `NO_PASO` · `RETRASO` · `ACUMULACION` · `OTRO`
### GET `/reports/`
Tus reportes (no los de otros usuarios).
### GET `/reports/{id}`
Detalle con la etiqueta del domicilio.
---
## 👮 Staff (`/staff`) — solo EMPLEADO o ADMIN
### GET `/staff/dashboard`
Métricas motivacionales del empleado.
```json
{
"employee_name": "Carlos Hernández",
"streak_days": 19,
"punctuality_pct": 88,
"bonus_accumulated_mxn": 950,
"next_milestone_days": 11,
"next_milestone_mxn": 500,
"reports_generated": 5,
"motivation_quote": "Tu puntualidad permite que miles de familias planifiquen su día",
"rating_label": "BUENO"
}
```
### GET `/staff/schedule`
Horario preestablecido con descansos.
### GET `/staff/categories`
Las 8 categorías disponibles para reportes operativos.
### POST `/staff/operational-reports`
Crea un reporte operativo (folio `OP-...`).
```json
{ "category": "FALLA_MECANICA", "severity": "MEDIA", "description": "Frenos haciendo ruido", "route_id": "RUTA-01", "truck_id": 12 }
```
**Categorías:** `NO_ARRANQUE` · `FALLA_MECANICA` · `ACCIDENTE` · `OBSTACULO` · `TRAFICO` · `COMBUSTIBLE` · `CLIMA` · `OTRO`
### GET `/staff/operational-reports`
Lista tus reportes operativos.
---
## 🛡️ Admin (`/admin`) — solo ADMIN
### GET `/admin/stats`
KPIs globales del sistema.
```json
{
"total_ciudadanos": 185, "total_domicilios": 302, "total_reportes": 280,
"reportes_24h": 8, "promedio_calificacion": 4.07,
"reportes_por_estado": {"PENDIENTE": 84, "EN_PROCESO": 56, "RESUELTO": 112, "CERRADO": 28},
"reportes_por_tipo": {"NO_PASO": 98, "RETRASO": 84, ...},
"rutas_activas": 15
}
```
### GET `/admin/reports?status=PENDIENTE&report_type=NO_PASO`
Lista TODOS los reportes ciudadanos (no solo los tuyos). Filtros opcionales.
### PATCH `/admin/reports/{id}/status?status=EN_PROCESO`
Cambia el estado de un reporte. Estados válidos: `PENDIENTE | EN_PROCESO | RESUELTO | CERRADO`.
### GET `/admin/routes`
Lista todas las rutas con su estado actual.
### GET `/admin/users?role=CIUDADANO`
Lista usuarios con conteos de domicilios y reportes.
### PATCH `/admin/users/{id}/role?role=EMPLEADO`
Cambia el rol de un usuario. Roles: `CIUDADANO | EMPLEADO | ADMIN`.
### GET `/admin/feedback`
Últimas 50 calificaciones del servicio.
---
## 🔒 Códigos de respuesta
| Código | Significado |
|--------|-------------|
| 200 | OK |
| 201 | Creado |
| 204 | Sin contenido (DELETE exitoso) |
| 400 | Bad request (validación falló) |
| 401 | No autenticado / token inválido |
| 403 | Sin permisos para este recurso |
| 404 | Recurso no encontrado o no te pertenece |
| 500 | Error del servidor |
---
## 🧪 Ejemplos con curl
### Flujo completo: ciudadano → reporte → admin lo resuelve
```bash
BASE=http://10.82.68.125:8000/api/v1
# 1. Login ciudadano
CTOKEN=$(curl -s -X POST $BASE/auth/login -H "Content-Type: application/json" \
-d '{"email":"demo@celaya.gob.mx","password":"Celaya2026"}' | jq -r .access_token)
# 2. Listar domicilios
curl -s $BASE/addresses/ -H "Authorization: Bearer $CTOKEN" | jq
# 3. Ver ETA del domicilio 1
curl -s $BASE/eta/address/1 -H "Authorization: Bearer $CTOKEN" | jq
# 4. Crear reporte
REPORT=$(curl -s -X POST $BASE/reports/ -H "Authorization: Bearer $CTOKEN" \
-H "Content-Type: application/json" \
-d '{"address_id":1,"report_type":"NO_PASO","description":"Hoy no pasó"}')
echo $REPORT | jq
REPORT_ID=$(echo $REPORT | jq -r .id)
# 5. Login admin
ATOKEN=$(curl -s -X POST $BASE/auth/login -H "Content-Type: application/json" \
-d '{"email":"admin@celaya.gob.mx","password":"Admin2026"}' | jq -r .access_token)
# 6. Admin ve TODOS los reportes
curl -s $BASE/admin/reports -H "Authorization: Bearer $ATOKEN" | jq '. | length'
# 7. Admin cambia el estado a EN_PROCESO
curl -s -X PATCH "$BASE/admin/reports/$REPORT_ID/status?status=EN_PROCESO" \
-H "Authorization: Bearer $ATOKEN" | jq
# 8. El ciudadano vuelve a consultar y ve el cambio
curl -s $BASE/reports/$REPORT_ID -H "Authorization: Bearer $CTOKEN" | jq .status
# → "EN_PROCESO" ✓
```