# 📱 REFERENCIA COMPLETA MÓVIL - Fuente Única de Verdad

**Versión:** 2.0  
**Actualizado:** 16 de Enero de 2026  
**Fuente:** ConfigWS.java (Apps Android/iOS) + Análisis de rutas  
**Propósito:** Documentación COMPLETA de endpoints móviles para proteger compatibilidad

---

## ⚠️ REGLA DE ORO

> **NINGÚN endpoint documentado en este archivo puede ser modificado sin coordinación explícita con el equipo móvil.**

**Los cambios en estos endpoints requieren:**
1. Notificación al equipo móvil
2. Actualización de las apps (Android/iOS)
3. Publicación en tiendas (Google Play / App Store)
4. Tiempo de adopción de usuarios (semanas/meses)

**Por lo tanto: ESTOS ENDPOINTS SON INTOCABLES DURANTE LA REFACTORIZACIÓN V2.**

---

## 🎯 ESTRATEGIA DE AISLAMIENTO

Para refactorizar el backend sin afectar mobile, usamos el **Adapter Pattern**:

```
Mobile App → /api/mobile/* → MobileAdapter → V2 Action → Repository → Model
```

El Adapter traduce entre:
- La API que espera mobile (formato viejo, parámetros legacy)
- La API V2 nueva (Actions, validaciones mejoradas)

**Ejemplos implementados:**
- `app/Http/Controllers/Mobile/Adapters/ConfigurationMobileAdapter.php`

---

## 📱 APLICACIONES MÓVILES

El sistema tiene **2 aplicaciones móviles**:

1. **App Cliente (Chariot)** - Para usuarios que solicitan servicios de taxi
2. **App Conductor** - Para conductores que aceptan y ejecutan servicios

Cada una usa diferentes endpoints según su ConfigWS.java (interfaz Retrofit).

---

## 🔐 AUTENTICACIÓN MÓVIL

**Sistema:** JWT (tymon/jwt-auth 1.0.0-rc.4.1)  
**Middleware:** `jwt-auth:` o `jwt-auth:driver` o `jwt-auth:client`

**Header requerido:**
```
Authorization: Bearer {token}
```

**⚠️ CRÍTICO - Password en MD5:**
```php
// Móvil envía:
{ "email": "user@example.com", "password": "md5(user@example.com)" }

// Backend valida:
\Hash::check($password, $user->password) 
// donde $user->password = bcrypt(md5(email))
```

**Ver regla completa en:** `CONTEXT_PROMPT.md` - Sección "Password en MD5"

---

## 🚗 APP CONDUCTOR - ENDPOINTS CRÍTICOS

### 1. Autenticación

#### POST `/auth/mobile/login`
**Parámetros:**
- `email` (string, required)
- `password` (string, required) - **MD5 del email**
- `device` (string, required) - Token del dispositivo
- `os` (string, required) - Sistema operativo (Android/iOS)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "message": "User successfully authenticated",
  "data": {
    "token": "eyJ0eXAiOiJKV1QiLCJ...",
    "role": 4,
    "user": "conductor@example.com",
    "profile_picture": null,
    "registered": false
  },
  "meta": []
}
```

**Lógica especial:**
- Si usuario NO existe → Auto-registra como cliente + Login inmediato
- Si usuario existe → Valida password + Genera token JWT

---

#### POST `/auth/mobile/relogin`
**Parámetros:**
- `email` (string, required)
- `password` (string, required)

**Respuesta:** Misma estructura que login

---

### 2. Información del Conductor

#### GET `/mobile/drivers`
**Requiere:** JWT Token (rol: conductor)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": {
    "id": 1,
    "user": {
      "id": 67,
      "name": "Conductor Name",
      "email": "conductor@example.com"
    },
    "vehicle": {
      "id": 1,
      "plate": "ABC-123",
      "model": "Sedan"
    },
    "flag_active": false,
    "flag_banned": false
  },
  "message": "Driver information"
}
```

---

#### GET `/mobile/drivers/flag/status`
**Requiere:** JWT Token (rol: conductor)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": {
    "flag_banned": false
  },
  "message": "Flag banned status"
}
```

---

#### GET `/mobile/drivers/flag/active`
**Requiere:** JWT Token (rol: conductor)  
**Acción:** Cambiar estado activo/inactivo (toggle)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": {
    "flag_active": true
  },
  "message": "Driver status updated"
}
```

---

#### PUT `/mobile/drivers`
**Requiere:** JWT Token (rol: conductor)  
**Parámetros:**
- `latitude` (float, required) - Latitud GPS
- `longitude` (float, required) - Longitud GPS
- `device` (string, required) - Token del dispositivo
- `id_service` (int, optional) - ID del servicio asignado

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "message": "Driver location updated"
}
```

**Nota:** Este endpoint se llama cada 5-10 segundos mientras el conductor está activo.

---

### 3. Servicios

#### GET `/mobile/services/asignado`
**Requiere:** JWT Token (rol: conductor)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": {
    "id": 123,
    "origin": "Calle A #123",
    "destination": "Calle B #456",
    "client_name": "Juan Pérez",
    "client_phone": "4611234567",
    "cost": 50.00,
    "distance": 5.2,
    "status": "N/A"
  },
  "message": "Assigned service"
}
```

**Respuesta sin servicio (200):**
```json
{
  "flag": false,
  "message": "No service assigned"
}
```

---

#### POST `/mobile/services/aceptar`
**Requiere:** JWT Token (rol: conductor)  
**Body:** `ServiceRequest` (objeto completo del servicio)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "message": "Service accepted"
}
```

---

#### POST `/mobile/services/rechazar`
**Requiere:** JWT Token (rol: conductor)  
**Body:** `ServiceRequest` (objeto completo del servicio)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "message": "Service rejected"
}
```

---

#### POST `/mobile/services/terminar`
**Requiere:** JWT Token (rol: conductor)  
**Body:** `ServiceRequest` (objeto completo del servicio)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "message": "Service completed"
}
```

---

#### GET `/mobile/services/history`
**Requiere:** JWT Token (rol: conductor)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": [
    {
      "id": 120,
      "origin": "...",
      "destination": "...",
      "cost": 50.00,
      "status": "Terminado",
      "created_at": "2026-01-15 10:30:00"
    }
  ],
  "message": "Service history"
}
```

---

### 4. Configuración

#### GET `/mobile/configurations`
**Requiere:** JWT Token (rol: conductor)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": {
    "regular_cost": 10.00,
    "executive_cost": 15.00,
    "cost_per_km": 5.00,
    "cost_per_minute": 1.50,
    "min_version_android": "1.5.0",
    "min_version_ios": "1.5.0"
  },
  "message": "Configuration retrieved"
}
```

---

### 5. Servicios Web (Usados por Conductor)

#### POST `/web/services`
**Requiere:** JWT Token (rol: conductor)  
**Descripción:** Crear servicio ejecutivo desde la app conductor

**Parámetros:**
- `origin` (string, required) - Dirección de origen
- `destination` (string, required) - Dirección de destino
- `notes` (string, optional) - Notas del servicio
- `coordinates` (string, required) - JSON con coordenadas
- `polyline` (string, required) - Polilínea de Google Maps
- `distance` (float, required) - Distancia en km
- `cost` (float, required) - Costo del servicio
- `code` (string, required) - Código de verificación
- `flag_executive` (boolean, required) - true para ejecutivo
- `id_os` (int, required) - ID del sistema operativo
- `id_driver` (int, required) - ID del conductor
- `reservar` (boolean, optional) - true para programar
- `time_request` (datetime, optional) - Fecha/hora programada
- `client_phone` (string, required) - Teléfono del cliente
- `name` (string, required) - Nombre del cliente
- `device` (string, required) - Token del dispositivo
- `os` (string, required) - Sistema operativo
- `email` (string, optional) - Email del cliente

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": {
    "id": 124,
    "origin": "...",
    "destination": "...",
    "cost": 75.00
  },
  "message": "Service created"
}
```

---

#### GET `/web/services/{id_serv}/driver/{id_driver}/asignar/`
**Requiere:** JWT Token (rol: conductor)  
**Descripción:** Asignar conductor a servicio (auto-asignación)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "message": "Driver assigned"
}
```

---

## 👤 APP CLIENTE - ENDPOINTS CRÍTICOS

### 1. Autenticación

**Mismo sistema que conductor:**
- `POST /auth/mobile/login`
- `POST /auth/mobile/relogin`

**Diferencia:** Rol = 5 (client)

---

### 2. Solicitud de Servicio

#### POST `/api/client/services/request`
**Requiere:** JWT Token (rol: client)

**Parámetros:**
- `origin` (string, required)
- `destination` (string, required)
- `coordinates` (string, required)
- `polyline` (string, required)
- `distance` (float, required)
- `cost` (float, required)
- `notes` (string, optional)

**Respuesta exitosa (200):**
```json
{
  "flag": true,
  "data": {
    "id": 125,
    "status": "N/A",
    "estimated_time": 5
  },
  "message": "Service requested"
}
```

---

### 3. Historial

#### GET `/api/client/services/history`
**Requiere:** JWT Token (rol: client)

**Respuesta:** Lista de servicios del cliente

---

## 🚫 ENDPOINTS INTOCABLES - LISTA COMPLETA

**Autenticación:**
- `POST /auth/mobile/login`
- `POST /auth/mobile/relogin`

**Conductor:**
- `GET /mobile/drivers`
- `GET /mobile/drivers/flag/status`
- `GET /mobile/drivers/flag/active`
- `PUT /mobile/drivers`
- `GET /mobile/services/asignado`
- `POST /mobile/services/aceptar`
- `POST /mobile/services/rechazar`
- `POST /mobile/services/terminar`
- `GET /mobile/services/history`
- `GET /mobile/configurations`

**Servicios Web (desde móvil):**
- `POST /web/services`
- `GET /web/services/{id}/driver/{id}/asignar/`

**Cliente:**
- `POST /api/client/services/request`
- `GET /api/client/services/history`

---

## 🔒 SISTEMA DE PERMISOS MÓVIL

**Autenticación:** JWT con roles legacy  
**Tabla:** `roles` (id_role)

**Roles móviles:**
- **Driver** (id_role = 4, slug = 'driver')
- **Client** (id_role = 5, slug = 'client')

**Middleware:**
```php
Route::middleware('jwt-auth:driver') // Solo conductores
Route::middleware('jwt-auth:client') // Solo clientes
Route::middleware('jwt-auth:')       // Cualquier autenticado
```

**Validación:**
```php
// En controllers
if ($user->id_role !== 4) {
    return $this->sendErrorResponse('Unauthorized', 401);
}

// O usando helper
if (!$user->inRoles('driver')) {
    return $this->sendErrorResponse('Unauthorized', 401);
}
```

**⚠️ NO USAR Bouncer para móvil:**
- Bouncer es solo para web dashboard
- Móvil usa sistema legacy de id_role
- Mezclar los dos sistemas causa bugs

**Ver documentación completa:** `docs/FIX_ROLES_COHERENCE.md`

---

## 📊 FORMATO DE RESPUESTAS

**Todas las respuestas móviles usan este formato:**

```json
{
  "flag": true/false,
  "code": 200,
  "message": "Mensaje descriptivo",
  "data": { ... },
  "meta": []
}
```

**Códigos de respuesta:**
- `200` - Éxito
- `401` - No autenticado
- `403` - Sin permisos
- `404` - No encontrado
- `500` - Error del servidor
- `510` - Error de validación

**⚠️ NUNCA CAMBIAR ESTA ESTRUCTURA** sin coordinar con equipo móvil.

---

## 🔍 VERIFICACIÓN ANTES DE MODIFICAR CÓDIGO

**Antes de cambiar CUALQUIER método, ejecutar:**

```bash
# ¿Está usado en rutas móviles?
grep -r "methodName" routes/api.php
grep -r "methodName" routes/api/mobile/

# ¿Está en ApiController (heredado por todos)?
grep -r "methodName" app/Http/Controllers/ApiController.php

# ¿Tiene referencias en mobile adapters?
grep -r "methodName" app/Http/Controllers/Mobile/
```

**Si encuentra resultados:** ⛔ **NO MODIFICAR** sin crear Adapter

---

## 🎯 ESTRATEGIA DE REFACTORIZACIÓN V2

### Paso 1: Crear Action V2
```php
// app/Actions/Driver/GetDriverInfoAction.php
class GetDriverInfoAction extends BaseAction
{
    public function execute(User $user): JsonResponse
    {
        // Lógica nueva con validaciones, type hints, etc.
    }
}
```

### Paso 2: Crear Mobile Adapter
```php
// app/Http/Controllers/Mobile/Adapters/DriverMobileAdapter.php
class DriverMobileAdapter extends ApiController
{
    protected GetDriverInfoAction $action;
    
    public function getInfo(Request $request): JsonResponse
    {
        // Traducir formato viejo → nuevo
        $user = auth()->user();
        
        // Llamar Action V2
        $result = $this->action->execute($user);
        
        // Traducir respuesta nueva → formato viejo esperado por móvil
        return $this->sendSuccessResponse(
            $result->getData()->data,
            'Driver information'
        );
    }
}
```

### Paso 3: Mantener Ruta Original
```php
// routes/api/mobile/driver.php
Route::get('/drivers', 'Mobile\Adapters\DriverMobileAdapter@getInfo')
    ->middleware('jwt-auth:driver');
```

**Resultado:**
- ✅ Móvil sigue funcionando sin cambios
- ✅ Backend V2 refactorizado con Actions
- ✅ Adapter traduce entre ambos mundos
- ✅ Futuro: Cuando móvil actualice, eliminar Adapter

---

## 📝 CHECKLIST DE COMPATIBILIDAD

**Antes de cada release, verificar:**

- [ ] Todos los endpoints móviles responden 200
- [ ] Formato de respuesta JSON sin cambios
- [ ] Login móvil funciona (con MD5)
- [ ] Conductores pueden aceptar/rechazar servicios
- [ ] GPS se actualiza correctamente
- [ ] Configuración se carga en app
- [ ] No hay cambios en ApiController sin Adapter
- [ ] Tests móviles pasan (si existen)

---

## 🚀 ROADMAP FUTURO

**Largo plazo (6-12 meses):**
1. Coordinar con equipo móvil actualización a API V2
2. Migrar de MD5 a bcrypt directo
3. Migrar de JWT a Laravel Sanctum
4. Eliminar ApiController legacy
5. Eliminar Adapters cuando móvil actualice

**Mientras tanto:**
- ⛔ NO modificar endpoints móviles
- ✅ Usar Adapters para nuevas funcionalidades
- ✅ Mantener compatibilidad 100%

---

**Última actualización:** 16 de Enero de 2026  
**Mantenido por:** Alberto Granados + AI Assistant  
**Próxima revisión:** Al actualizar apps móviles

---

_"Mobile is king, web is prince. Proteger compatibilidad móvil es CRÍTICO."_ 📱
