# 🎯 CONTEXT_PROMPT - Fuente Única de Verdad para AI Agents

**Sistema:** Traffic_webapp - Plataforma de gestión de servicios de taxi ejecutivos  
**Versión Backend:** Laravel 5.8.38 + PHP 7.4.33  
**Versión Frontend:** Vue 2.6.11 + Vuetify  
**Base de Datos:** PostgreSQL  
**Autenticación:** JWT (tymon/jwt-auth) + Bouncer  
**Última actualización:** 16 de Enero de 2026

---

## 📖 TABLA DE CONTENIDOS

1. [Resumen Ejecutivo](#-resumen-ejecutivo)
2. [Reglas de Negocio Críticas](#-reglas-de-negocio-críticas)
3. [Arquitectura del Sistema](#-arquitectura-del-sistema)
4. [Estándares de Desarrollo](#-estándares-de-desarrollo)
5. [Estrategia de Testing](#-estrategia-de-testing)
6. [Restricciones y Limitaciones](#-restricciones-y-limitaciones)
7. [Deuda Técnica](#-deuda-técnica)
8. [Quick Reference](#-quick-reference)

---

## 🎯 RESUMEN EJECUTIVO

### Estado del Proyecto

**Refactorización V2:**
- ✅ **14/15 módulos completados (93%)**
- 🔄 **1 módulo pendiente:** Analytics
- ⏱️ **Tiempo estimado completar:** 2-3 días

**Deuda técnica total:**
- 📊 **66% del sistema requiere modernización**
- ⏱️ **19-25 semanas de trabajo estimado**
- 🎯 **Prioridad:** EOL de stack (Laravel 5.8 + PHP 7.4)

### Stack Técnico

**Backend:**
- Laravel 5.8.38 (EOL Agosto 2024) ⚠️
- PHP 7.4.33 (EOL Noviembre 2022) ⚠️
- PostgreSQL
- JWT Auth (tymon/jwt-auth 1.0.0-rc.4.1)
- Bouncer (Permisos web dashboard)
- PHPStan Level 5
- PHPUnit 7.5.20

**Frontend:**
- Vue 2.6.11 (EOL Diciembre 2023) ⚠️
- Vuetify 2.x
- Webpack
- Axios

**Infraestructura:**
- Cronjob (servicios agendados)
- API REST
- 2 Apps Móviles (Android + iOS)

### Métricas de Código

**PHP:**
- ~16,695 líneas de código
- 50 Actions creadas
- 16 Repositories
- 35 Controllers refactorizados
- 17 Form Requests

**Frontend:**
- 72 archivos Vue/JS
- Componentes con Actions pattern frontend

**Tests:**
- 268 tests total
- ✅ 227 pasando
- ❌ 5 failures (bugs conocidos)
- ⏭️ 36 skipped (requieren cleanup)
- 🐛 **Bug crítico:** ScheduledService no se crea prevented

---

## ⚠️ REGLAS DE NEGOCIO CRÍTICAS

### 1. Password en MD5 (Sistema Legacy)

**⚠️ NUNCA CAMBIAR - Aplicaciones móviles dependen de esto**

```php
// Móvil envía:
{
  "email": "user@example.com",
  "password": "md5(user@example.com)" // MD5 del email como password
}

// Backend almacena:
password = bcrypt(md5(email)) // Doble hash

// Validación:
\Hash::check($password, $user->password) // Compara bcrypt(md5(email))
```

**Contexto:**
- Sistema heredado de decisión de seguridad legacy
- Cambiar requiere actualizar apps móviles + re-publicar en tiendas
- **ROADMAP:** Migrar a bcrypt directo cuando móvil actualice (6-12 meses)

**Ver documentación completa:** [MOBILE_REFERENCE.md](MOBILE_REFERENCE.md)

---

### 2. Sistema Híbrido de Roles (Bouncer + Legacy)

**⚠️ CRÍTICO: Dos sistemas de permisos coexisten**

**Web Dashboard (Bouncer):**
```php
// Tabla: permissions (nuevo)
$user->can('driver-update'); // Bouncer ability

// Middleware
Route::middleware('web-auth:driver-update');

// Form Request
public function authorize(): bool {
    return $this->user()->can('driver-update');
}
```

**API Móvil (Legacy id_role):**
```php
// Tabla: roles (legacy)
if ($user->id_role !== 4) { // 4 = driver
    return $this->sendErrorResponse('Unauthorized', 401);
}

// Middleware
Route::middleware('jwt-auth:driver'); // Valida id_role = 4
```

**Roles existentes:**
| ID | Slug | Nombre | Sistema |
|----|------|--------|---------|
| 1 | superadministrator | Super Administrador | Bouncer |
| 2 | administrator | Administrador | Bouncer |
| 3 | operator | Operador | Bouncer |
| 4 | driver | Conductor | Legacy (Móvil) |
| 5 | client | Cliente | Legacy (Móvil) |

**⚠️ REGLA DE ORO:**
- Web → Usar Bouncer (`$user->can()`)
- Móvil → Usar id_role (`$user->id_role === 4`)
- **NUNCA mezclar** los dos sistemas en el mismo endpoint

**Ver documentación completa:** [docs/FIX_ROLES_COHERENCE.md](docs/FIX_ROLES_COHERENCE.md)

---

### 3. Vehículo Placeholder (ID = 47)

**⚠️ NUNCA ELIMINAR - Registro especial del sistema**

```php
// Registro en tabla vehicles:
{
  "id": 47,
  "plate": "PLACEHOLDER",
  "model": "N/A",
  "active": false,
  "deleted_at": null
}
```

**Uso:**
- Asignado a conductores sin vehículo activo
- Servicios ejecutivos sin vehículo específico
- Pruebas y demos del sistema

**Reglas:**
- ✅ Puede asignarse temporalmente
- ❌ NO puede eliminarse (soft delete o hard delete)
- ❌ NO puede modificarse su plate
- ⚠️ Verificar existencia en migraciones

---

### 4. Servicios Agendados (Cronjob)

**Sistema:** Cronjob ejecuta cada minuto verificando servicios programados

**Tabla `services` - Campos críticos:**

| Campo | Tipo | Descripción | Reglas |
|-------|------|-------------|--------|
| `flag_scheduled` | boolean | Indica servicio programado | `true` = agendado, `false` = inmediato |
| `time_request` | timestamp | Fecha/hora programada | Required si flag_scheduled=true |
| `id_status` | integer | Estado del servicio | Ver tabla estados |

**Estados de servicios:**

| ID | Nombre | Descripción | Transiciones |
|----|--------|-------------|--------------|
| 1 | N/A | Sin asignar | → 2 (aceptado), → 5 (cancelado) |
| 2 | Aceptado | Conductor asignado | → 3 (iniciado), → 5 (cancelado) |
| 3 | Iniciado | En camino origen | → 4 (en curso) |
| 4 | En Curso | Cliente a bordo | → 6 (terminado) |
| 5 | Cancelado | Cancelado antes de iniciar | [Final] |
| 6 | Terminado | Completado | [Final] |

**⚠️ REGLA CRÍTICA: `flag_scheduled` es permanente**

```php
// ✅ CORRECTO
// flag_scheduled permanece true INCLUSO después de ejecutarse
$service = Service::create([
    'flag_scheduled' => true,
    'time_request' => '2026-01-17 10:00:00'
]);

// Cuando cronjob ejecuta a las 10:00:
// NO cambiar flag_scheduled a false
// Solo cambiar id_status de 1 (N/A) → 2 (Aceptado) si hay conductor

// ❌ INCORRECTO
$service->update(['flag_scheduled' => false]); // NUNCA HACER ESTO
```

**Lógica del Cronjob:**

```php
// Pseudo-código del cronjob (ejecuta cada minuto)

// 1. Buscar servicios programados cuya hora ya llegó
$servicios = Service::where('flag_scheduled', true)
    ->where('time_request', '<=', now())
    ->where('id_status', 1) // Solo N/A
    ->get();

// 2. Para cada servicio:
foreach ($servicios as $servicio) {
    // 3. Buscar conductor disponible
    $conductor = Driver::available()->nearest($servicio->origin)->first();
    
    if ($conductor) {
        // 4. Asignar conductor y cambiar estado
        $servicio->update([
            'id_driver' => $conductor->id,
            'id_status' => 2 // Aceptado
            // ⚠️ NO cambiar flag_scheduled
        ]);
        
        // 5. Notificar conductor
        NotificationService::sendPush($conductor, 'Nuevo servicio asignado');
    } else {
        // 6. Si no hay conductor, reintenta en próxima ejecución
        Log::warning("No hay conductor disponible para servicio {$servicio->id}");
    }
}
```

**Comandos de verificación:**

```bash
# Ver servicios agendados pendientes
php artisan tinker
>>> Service::where('flag_scheduled', true)->where('id_status', 1)->get();

# Ver servicios agendados ejecutados (mantienen flag=true)
>>> Service::where('flag_scheduled', true)->whereIn('id_status', [2,3,4,5,6])->get();

# Ejecutar cronjob manualmente
php artisan schedule:run
```

**Ver documentación completa:** [docs/SCHEDULED_SERVICES_BUSINESS_RULES.md](docs/SCHEDULED_SERVICES_BUSINESS_RULES.md)

---

### 5. API Móvil INTOCABLE

**⚠️ REGLA DE ORO: Ningún endpoint móvil puede modificarse sin coordinación con equipo móvil**

**Impacto de cambios:**
1. Requiere actualizar apps (Android + iOS)
2. Publicación en tiendas (Google Play + App Store)
3. Tiempo de adopción de usuarios (semanas/meses)

**Endpoints INTOCABLES (18 total):**

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

**Conductor (10 endpoints):**
- `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, 2 endpoints):**
- `POST /web/services`
- `GET /web/services/{id}/driver/{id}/asignar/`

**Cliente (2 endpoints):**
- `POST /api/client/services/request`
- `GET /api/client/services/history`

**Formato de respuesta INTOCABLE:**
```json
{
  "flag": true,
  "code": 200,
  "message": "Mensaje descriptivo",
  "data": { ... },
  "meta": []
}
```

**Estrategia de refactorización (Mobile Adapter Pattern):**

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

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

**Ver documentación completa:** [MOBILE_REFERENCE.md](MOBILE_REFERENCE.md)

---

## 🏗️ ARQUITECTURA DEL SISTEMA

### 1. Actions Pattern (Refactorización V2)

**Filosofía:** Una Action = Una responsabilidad única (SRP)

**Estructura de directorios:**
```
app/Actions/
├── Configuration/
│   ├── GetConfigurationAction.php
│   └── UpdateConfigurationAction.php
├── Driver/
│   ├── CreateDriverAction.php
│   ├── UpdateDriverAction.php
│   ├── ListDriversAction.php
│   └── DeleteDriverAction.php
└── Service/
    ├── CreateServiceAction.php
    └── UpdateServiceAction.php
```

**Template de BaseAction:**

```php
<?php

namespace App\Actions;

use Illuminate\Http\JsonResponse;
use App\Traits\ApiResponseTrait;

/**
 * Class BaseAction
 * 
 * Clase base para todas las Actions del sistema
 * 
 * @package App\Actions
 */
abstract class BaseAction
{
    use ApiResponseTrait;

    /**
     * Ejecuta la acción principal
     * 
     * @param mixed ...$params
     * @return JsonResponse
     */
    abstract public function execute(...$params): JsonResponse;
}
```

**Ejemplo de Action concreta:**

```php
<?php

namespace App\Actions\Driver;

use App\Actions\BaseAction;
use App\Repositories\Web\Driver\DriverRepository;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;

/**
 * Class UpdateDriverAction
 * 
 * Actualiza la información de un conductor
 * 
 * @package App\Actions\Driver
 */
class UpdateDriverAction extends BaseAction
{
    /**
     * Repository de conductores
     * 
     * @var DriverRepository
     */
    protected DriverRepository $driverRepository;

    /**
     * Constructor
     * 
     * @param DriverRepository $driverRepository
     */
    public function __construct(DriverRepository $driverRepository)
    {
        $this->driverRepository = $driverRepository;
    }

    /**
     * Actualiza un conductor
     * 
     * @param int $id ID del conductor
     * @param array $data Datos validados
     * @return JsonResponse
     */
    public function execute(int $id, array $data): JsonResponse
    {
        try {
            $driver = $this->driverRepository->update($id, $data);
            
            Log::info("Conductor actualizado", [
                'driver_id' => $id,
                'updated_fields' => array_keys($data)
            ]);
            
            return $this->success(
                $driver,
                'Conductor actualizado exitosamente'
            );
            
        } catch (\Exception $e) {
            Log::error("Error actualizando conductor", [
                'driver_id' => $id,
                'error' => $e->getMessage()
            ]);
            
            return $this->serverError('Error actualizando conductor');
        }
    }
}
```

**Principios SOLID aplicados:**
- **S**ingle Responsibility: Una Action, una operación
- **O**pen/Closed: Extendible vía herencia de BaseAction
- **L**iskov Substitution: Todas las Actions son intercambiables
- **I**nterface Segregation: Solo método execute() obligatorio
- **D**ependency Inversion: Inyección de Repositories

**Reglas de Actions:**
- ✅ Máximo 150 líneas por Action
- ✅ Un solo método público: `execute()`
- ✅ Type hints obligatorios en parámetros y retorno
- ✅ PHPDoc completo
- ✅ Try-catch con logs
- ✅ Retornar JsonResponse usando ApiResponseTrait

---

### 2. Arquitectura de Controllers V2

**Patrón:** Controller solo orquesta, Actions ejecutan

**Template de Controller:**

```php
<?php

namespace App\Http\Controllers\Web\V2;

use App\Actions\Driver\UpdateDriverAction;
use App\Http\Requests\Web\Driver\UpdateDriverRequest;
use App\Http\Controllers\Controller;
use Illuminate\Http\JsonResponse;

/**
 * Class DriverController
 * 
 * Gestiona las operaciones de conductores
 * 
 * @package App\Http\Controllers\Web\V2
 */
class DriverController extends Controller
{
    /**
     * Actualiza la información de un conductor
     * 
     * @param int $id
     * @param UpdateDriverRequest $request
     * @param UpdateDriverAction $action
     * @return JsonResponse
     */
    public function update(
        int $id,
        UpdateDriverRequest $request,
        UpdateDriverAction $action
    ): JsonResponse {
        return $action->execute($id, $request->validated());
    }
}
```

**Reglas de Controllers:**
- ✅ Máximo 100 líneas por Controller
- ✅ Máximo 7 métodos REST (index, create, store, show, edit, update, destroy)
- ✅ Inyectar Actions en métodos (no en constructor)
- ✅ Usar Form Requests para validación
- ✅ Retornar solo JsonResponse
- ❌ NO usar DB::, Eloquent, lógica de negocio

---

### 3. Repositorios

**Responsabilidad:** Abstraer acceso a datos

**Template:**

```php
<?php

namespace App\Repositories\Web\Driver;

use App\Driver;
use Illuminate\Database\Eloquent\Collection;

/**
 * Class DriverRepository
 * 
 * Maneja el acceso a datos de Driver
 * 
 * @package App\Repositories\Web\Driver
 */
class DriverRepository
{
    /**
     * Obtiene conductor por ID
     * 
     * @param int $id
     * @return Driver
     */
    public function find(int $id): Driver
    {
        return Driver::with(['user', 'vehicle'])
            ->where('canceled', false)
            ->findOrFail($id);
    }

    /**
     * Actualiza conductor
     * 
     * @param int $id
     * @param array $data
     * @return Driver
     */
    public function update(int $id, array $data): Driver
    {
        $driver = $this->find($id);
        
        // Actualizar usuario si hay datos de usuario
        if (isset($data['name']) || isset($data['email'])) {
            $driver->user->update([
                'name' => $data['name'] ?? $driver->user->name,
                'email' => $data['email'] ?? $driver->user->email,
            ]);
        }
        
        // Actualizar conductor
        $driver->update($data);
        
        return $driver->fresh(['user', 'vehicle']);
    }
}
```

**Reglas de Repositories:**
- ✅ Un Repository por modelo principal
- ✅ Solo queries de base de datos
- ❌ NO lógica de negocio
- ✅ Métodos con nombres claros (get, find, create, update, delete)
- ✅ Eager loading para evitar N+1

---

### 4. Form Requests (Validación)

**Template:**

```php
<?php

namespace App\Http\Requests\Web\Driver;

use Illuminate\Foundation\Http\FormRequest;

/**
 * Class UpdateDriverRequest
 * 
 * Valida la actualización de conductor
 * 
 * @package App\Http\Requests\Web\Driver
 */
class UpdateDriverRequest extends FormRequest
{
    /**
     * Determina si el usuario está autorizado
     * 
     * @return bool
     */
    public function authorize(): bool
    {
        return $this->user()->can('driver-update');
    }

    /**
     * Reglas de validación
     * 
     * @return array
     */
    public function rules(): array
    {
        return [
            'name' => 'required|string|max:255',
            'email' => 'required|email|unique:users,email,' . $this->driver,
            'phone' => 'required|string|max:10',
            'expiration_policy' => 'date|after_or_equal:today',
        ];
    }

    /**
     * Mensajes de validación personalizados
     * 
     * @return array
     */
    public function messages(): array
    {
        return [
            'name.required' => 'El nombre es requerido',
            'email.unique' => 'Este correo ya está registrado',
            'phone.max' => 'El teléfono no debe exceder 10 dígitos',
            'expiration_policy.after_or_equal' => 'La fecha de póliza debe ser igual o posterior a hoy',
        ];
    }
}
```

**Sistema de Validación Mejorado (ValidationResponseTrait):**

```php
use App\Traits\ValidationResponseTrait;

class UpdateDriverAction extends BaseAction
{
    use ValidationResponseTrait;

    public function execute(int $id, array $data): JsonResponse
    {
        // Validación manual con mensajes mejorados
        $validator = \Validator::make($data, [
            'name' => 'required|string|max:255',
            'email' => 'required|email',
        ]);

        if ($validator->fails()) {
            // ✅ Retorna mensajes user-friendly en español
            return $this->validationErrorResponse($validator);
        }

        // ... resto de la lógica
    }
}
```

**Formato de respuesta de validación:**

```json
{
  "flag": false,
  "code": 422,
  "message": "Error de validación",
  "errors": {
    "email": [
      "El correo electrónico debe ser una dirección de correo válida."
    ],
    "phone": [
      "El teléfono no debe exceder 10 dígitos."
    ]
  },
  "meta": {
    "received_values": { ... },
    "validation_rules": { ... },
    "timestamp": "2026-01-16 10:30:00"
  }
}
```

**Ver documentación completa:** [docs/VALIDATION_MESSAGES_USAGE_GUIDE.md](docs/VALIDATION_MESSAGES_USAGE_GUIDE.md)

---

### 5. API Responses (ApiResponseTrait)

**Trait universal para respuestas JSON:**

```php
namespace App\Traits;

use Illuminate\Http\JsonResponse;

trait ApiResponseTrait
{
    /**
     * Respuesta de éxito (200)
     */
    protected function success($data, string $message = 'Success'): JsonResponse
    {
        return response()->json([
            'flag' => true,
            'code' => 200,
            'message' => $message,
            'data' => $data
        ], 200);
    }

    /**
     * Recurso creado (201)
     */
    protected function created($data, string $message = 'Resource created'): JsonResponse
    {
        return response()->json([
            'flag' => true,
            'code' => 201,
            'message' => $message,
            'data' => $data
        ], 201);
    }

    /**
     * Error de validación (422)
     */
    protected function validationError(string $message, array $errors): JsonResponse
    {
        return response()->json([
            'flag' => false,
            'code' => 422,
            'message' => $message,
            'errors' => $errors
        ], 422);
    }

    /**
     * No encontrado (404)
     */
    protected function notFound(string $message = 'Resource not found'): JsonResponse
    {
        return response()->json([
            'flag' => false,
            'code' => 404,
            'message' => $message,
            'data' => null
        ], 404);
    }

    /**
     * No autorizado (401)
     */
    protected function unauthorized(string $message = 'Unauthorized'): JsonResponse
    {
        return response()->json([
            'flag' => false,
            'code' => 401,
            'message' => $message
        ], 401);
    }

    /**
     * Prohibido (403)
     */
    protected function forbidden(string $message = 'Forbidden'): JsonResponse
    {
        return response()->json([
            'flag' => false,
            'code' => 403,
            'message' => $message
        ], 403);
    }

    /**
     * Error del servidor (500)
     */
    protected function serverError(string $message = 'Internal server error'): JsonResponse
    {
        return response()->json([
            'flag' => false,
            'code' => 500,
            'message' => $message,
            'data' => null
        ], 500);
    }
}
```

---

## 📐 ESTÁNDARES DE DESARROLLO

### 1. Principios de Código Limpio

**SRP (Single Responsibility Principle):**
```php
// ✅ CORRECTO: Una Action, una responsabilidad
class CreateDriverAction { /* solo crear */ }
class UpdateDriverAction { /* solo actualizar */ }

// ❌ INCORRECTO: Múltiples responsabilidades
class DriverAction { 
    public function create() {}
    public function update() {}
    public function delete() {}
}
```

**DRY (Don't Repeat Yourself):**
```php
// ✅ CORRECTO: Extraer lógica común a Trait o Service
trait ApiResponseTrait {
    protected function success($data, $message) { /* ... */ }
}

// ❌ INCORRECTO: Duplicar código en cada Action
class Action1 {
    public function execute() {
        return response()->json(['flag' => true, 'data' => $data]);
    }
}
class Action2 {
    public function execute() {
        return response()->json(['flag' => true, 'data' => $data]); // Duplicado
    }
}
```

**KISS (Keep It Simple, Stupid):**
```php
// ✅ CORRECTO: Simple y directo
$active = $driver->flag_active;

// ❌ INCORRECTO: Complejidad innecesaria
$active = ($driver->flag_active === true) ? true : false;
```

---

### 2. Límites de Código

| Elemento | Límite | Razón |
|----------|--------|-------|
| Action | ≤ 150 líneas | Mantener responsabilidad única |
| Controller | ≤ 100 líneas | Solo orquestación |
| Método | ≤ 30 líneas | Legibilidad y testabilidad |
| Complejidad ciclomática | ≤ 10 | Evitar código complejo |

---

### 3. Convenciones de Nombres

**Actions:**
```
{Verbo}{Entidad}Action
CreateDriverAction, UpdateServiceAction
```

**Controllers:**
```
{Entidad}Controller
DriverController, ServiceController
```

**Form Requests:**
```
{Verbo}{Entidad}Request
CreateDriverRequest, UpdateServiceRequest
```

**Repositories:**
```
{Entidad}Repository
DriverRepository, ServiceRepository
```

---

### 4. Documentación (PHPDoc)

**Obligatorio en:**
- ✅ Clases (qué hace, responsabilidad)
- ✅ Métodos públicos (parámetros, retorno, excepciones)
- ✅ Propiedades públicas/protegidas

**Opcional en:**
- Variables locales (solo si complejo)
- Métodos privados obvios

**Template:**
```php
/**
 * Descripción breve de la clase o método
 * 
 * Descripción más detallada si es necesario.
 * Puede incluir ejemplos de uso.
 * 
 * @param TipoParametro $nombreParametro Descripción del parámetro
 * @return TipoRetorno Descripción del retorno
 * @throws TipoExcepcion Cuándo se lanza la excepción
 */
```

**Comentarios en código:**
```php
// ✅ CORRECTO: Explicar el "por qué", no el "qué"
// Cancelamos servicios > 24hrs para liberar conductores trabados
$this->cancelStaleServices(24);

// ❌ INCORRECTO: Explicar el obvio
// Asignar valor a variable
$name = 'John';
```

---

### 5. Frontend (Vue + Vuetify) - ALIO Standard

**ALIO = Actions, Loaders, Inputs, Outputs**

**10 Principios:**
1. **Layout Flexbox** (no CSS grid)
2. **v-toolbar** para headers
3. **v-form + validation** para formularios
4. **v-btn** con :loading para acciones
5. **v-card** para contenido
6. **Scrollbar visible** (no auto-hide)
7. **Responsive** (mobile-first)
8. **v-data-table** para listados
9. **Snackbars** para notificaciones
10. **Confirmaciones** para acciones destructivas

**Ejemplo de componente:**

```vue
<template>
  <v-container>
    <v-card>
      <v-toolbar color="primary" dark>
        <v-toolbar-title>Conductores</v-toolbar-title>
      </v-toolbar>

      <v-card-text>
        <v-form ref="form" v-model="valid">
          <v-text-field
            v-model="name"
            label="Nombre"
            :rules="[v => !!v || 'El nombre es requerido']"
            required
          />
          
          <v-btn
            color="primary"
            :loading="loading"
            :disabled="!valid"
            @click="save"
          >
            Guardar
          </v-btn>
        </v-form>
      </v-card-text>
    </v-card>

    <v-snackbar v-model="snackbar" :color="snackbarColor">
      {{ snackbarMessage }}
    </v-snackbar>
  </v-container>
</template>

<script>
export default {
  data() {
    return {
      valid: false,
      loading: false,
      name: '',
      snackbar: false,
      snackbarMessage: '',
      snackbarColor: 'success'
    };
  },
  
  methods: {
    async save() {
      if (!this.$refs.form.validate()) return;
      
      this.loading = true;
      
      try {
        const response = await this.$axios.post('/api-web/v2/drivers', {
          name: this.name
        });
        
        if (response.data.flag) {
          this.snackbarMessage = 'Conductor creado exitosamente';
          this.snackbarColor = 'success';
          this.snackbar = true;
          this.$refs.form.reset();
        }
      } catch (error) {
        this.snackbarMessage = error.response?.data?.message || 'Error al guardar';
        this.snackbarColor = 'error';
        this.snackbar = true;
      } finally {
        this.loading = false;
      }
    }
  }
};
</script>
```

**Prevención de doble clic:**
```vue
<v-btn
  :loading="loading"
  :disabled="loading"
  @click="submit"
>
  Enviar
</v-btn>
```

**Ver documentación completa:** [docs/FRONTEND_DESIGN_STANDARDS.md](docs/FRONTEND_DESIGN_STANDARDS.md)

---

### 6. Checklist Pre-Commit

**Calidad de código:**
- [ ] PHPDoc completo en clases y métodos públicos
- [ ] Controlador ≤ 100 líneas
- [ ] Action ≤ 150 líneas
- [ ] Método ≤ 30 líneas
- [ ] PHPStan Level 5: 0 errores
- [ ] Nomenclatura consistente

**Testing:**
- [ ] Tests creados y pasando
- [ ] Coverage ≥ 80% en Actions

**Compatibilidad:**
- [ ] No afecta endpoints mobile (verificar grep)
- [ ] Form Request creado (si aplica)
- [ ] Respuestas usan ApiResponseTrait
- [ ] No rompe dashboard web

**Seguridad de refactorización:**
- [ ] Verificar rutas activas (`grep -r "ControllerName" routes/`)
- [ ] Mantener formato de respuesta
- [ ] Verificar uso con `grep -r "ClassName" app/`
- [ ] Probar con datos de producción

**Ver checklist completo:** [docs/REFACTORING_SAFETY_CHECKLIST.md](docs/REFACTORING_SAFETY_CHECKLIST.md)

---

## 🧪 ESTRATEGIA DE TESTING

### 1. TestLabSeeder (Datos de Prueba)

**Propósito:** Seeder con datos de prueba realistas y completos

**Ejecutar:**
```bash
# Limpiar BD + Ejecutar seeder
php artisan migrate:fresh --seed

# O solo seeder
php artisan db:seed --class=TestLabSeeder
```

**Datos creados por TestLabSeeder:**

| Entidad | Cantidad | Detalles |
|---------|----------|----------|
| Users | 15 | Admin, Operadores, Conductores, Clientes |
| Drivers | 5 | Con vehículos y documentos |
| Vehicles | 6 | Incluye placeholder ID=47 |
| Services | 20 | Varios estados (N/A, Aceptado, Terminado, etc.) |
| Configurations | 1 | Configuración activa |
| Roles | 5 | Superadmin, Admin, Operator, Driver, Client |

**Usuarios de prueba:**

| Email | Password | Rol | Uso |
|-------|----------|-----|-----|
| super@traffic.test | md5(super@traffic.test) | Superadministrador | Testing admin panel |
| admin@traffic.test | md5(admin@traffic.test) | Administrador | Testing permisos |
| conductor1@traffic.test | md5(conductor1@traffic.test) | Conductor | Testing app conductor |
| cliente1@traffic.test | md5(cliente1@traffic.test) | Cliente | Testing app cliente |

**Ventajas:**
- ✅ Datos consistentes entre tests
- ✅ Realistas (como producción)
- ✅ Fácil reset (`migrate:fresh --seed`)
- ✅ Documentado en `database/seeds/TestLabSeeder.php`

---

### 2. Constantes de Testing (TestConstants.php)

**Propósito:** IDs y valores fijos para tests predecibles

```php
<?php

namespace Tests;

class TestConstants
{
    // Usuarios
    const USER_ADMIN_ID = 1;
    const USER_CONDUCTOR_ID = 3;
    const USER_CLIENTE_ID = 5;
    
    // Vehículos
    const VEHICLE_PLACEHOLDER_ID = 47;
    const VEHICLE_TEST_ID = 1;
    
    // Estados
    const STATUS_NA = 1;
    const STATUS_ACEPTADO = 2;
    const STATUS_TERMINADO = 6;
    
    // Roles
    const ROLE_SUPERADMIN = 1;
    const ROLE_ADMIN = 2;
    const ROLE_DRIVER = 4;
    const ROLE_CLIENT = 5;
}
```

**Uso en tests:**
```php
use Tests\TestConstants;

class DriverTest extends TestCase
{
    /** @test */
    public function conductor_puede_ver_su_informacion()
    {
        $this->actingAs(
            User::find(TestConstants::USER_CONDUCTOR_ID)
        );
        
        $response = $this->getJson('/mobile/drivers');
        
        $response->assertStatus(200);
    }
}
```

---

### 3. Estructura de Tests

**Patrón AAA (Arrange, Act, Assert):**

```php
/** @test */
public function puede_actualizar_conductor_exitosamente()
{
    // ARRANGE (Preparar)
    $driver = Driver::where('canceled', false)->first();
    $data = ['name' => 'Nuevo Nombre'];
    
    // ACT (Actuar)
    $response = $this->putJson("/api-web/v2/drivers/{$driver->id}", $data);
    
    // ASSERT (Verificar)
    $response->assertStatus(200);
    $response->assertJson(['flag' => true]);
    $this->assertEquals('Nuevo Nombre', $driver->fresh()->user->name);
}
```

**Nomenclatura:**
```php
// ✅ CORRECTO: Descripción clara en español
public function puede_crear_conductor_con_datos_validos() {}
public function falla_si_email_duplicado() {}

// ❌ INCORRECTO: Nombres genéricos
public function test1() {}
public function it_works() {}
```

---

### 4. Métricas de Testing

**Estado actual:**
- ✅ 268 tests total
- ✅ 227 pasando (84.7%)
- ❌ 5 failures (1.9%)
- ⏭️ 36 skipped (13.4%)

**Bugs críticos conocidos:**
1. **ScheduledService no se crea** - prevented (bug en TestLabSeeder)
2. Services duplicados en algunos tests
3. Validación de fechas falla en algunos casos

**Cobertura objetivo:**
- 🎯 ≥ 80% cobertura en Actions
- 🎯 ≥ 60% cobertura general
- 🎯 100% tests pasando antes de release

**Ejecutar tests:**
```bash
# Todos los tests
vendor/bin/phpunit

# Tests específicos
vendor/bin/phpunit --filter DriverTest

# Con cobertura
vendor/bin/phpunit --coverage-text --coverage-filter=app/
```

---

## 🚫 RESTRICCIONES Y LIMITACIONES

### 1. API Móvil Inmutable

**⚠️ PROHIBIDO:**
- ❌ Modificar endpoints móviles existentes
- ❌ Cambiar estructura de respuestas móviles
- ❌ Eliminar campos de respuesta
- ❌ Cambiar códigos de respuesta HTTP
- ❌ Modificar nombres de parámetros

**✅ PERMITIDO:**
- ✅ Agregar nuevos endpoints (coordinado)
- ✅ Agregar campos opcionales a respuestas existentes
- ✅ Crear Adapters para traducir V2 → Mobile

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

# ¿Está en MOBILE_REFERENCE.md?
grep "methodName" MOBILE_REFERENCE.md

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

**Ver lista completa:** [MOBILE_REFERENCE.md](MOBILE_REFERENCE.md)

---

### 2. Controladores Legacy Protegidos

**⚠️ NO TOCAR sin Adapter:**
```
app/Http/Controllers/ServiceController.php (legacy)
app/Http/Controllers/DriverController.php (legacy)
app/Http/Controllers/ClientController.php (legacy)
app/Http/Controllers/ApiController.php (base para mobile)
```

**Estrategia:**
1. Crear Action V2
2. Crear Mobile Adapter
3. Mantener Controller legacy intacto
4. Futuro: Eliminar cuando móvil actualice

---

### 3. Limitaciones de Stack EOL

**Laravel 5.8.38 (EOL Agosto 2024):**
- ⚠️ Sin actualizaciones de seguridad
- ⚠️ Vulnerabilidades no parchadas
- ⚠️ Incompatibilidad con paquetes nuevos

**PHP 7.4.33 (EOL Noviembre 2022):**
- ⚠️ Sin soporte de seguridad
- ⚠️ Incompatible con Laravel 9+
- ⚠️ Falta features de PHP 8.x

**Vue 2.6.11 (EOL Diciembre 2023):**
- ⚠️ Sin nuevas features
- ⚠️ Migración a Vue 3 requiere reescritura

**Impacto:**
- 🚨 Alta prioridad migrar stack
- 📊 Estimado: 10-15 semanas de trabajo
- 💰 Costo-beneficio: Crítico para seguridad

---

### 4. Restricciones de Base de Datos

**PostgreSQL sin migraciones mayores:**
- ⚠️ Cambios de schema requieren downtime
- ⚠️ Renombrar columnas puede romper mobile
- ⚠️ Eliminar tablas requiere verificación exhaustiva

**Reglas:**
- ✅ Agregar columnas: OK (nullable)
- ⚠️ Renombrar columnas: Requiere análisis
- ❌ Eliminar columnas: Solo si 0 referencias
- ❌ Cambiar tipos: Alto riesgo

---

## 📊 DEUDA TÉCNICA

### 1. Desglose por Categorías

| Categoría | Módulos | Esfuerzo | Prioridad |
|-----------|---------|----------|-----------|
| **Refactorización V2** | 1 pendiente (Analytics) | 2-3 días | 🟢 Baja |
| **Migración Stack** | Laravel 5.8→10, PHP 7.4→8.2, Vue 2→3 | 10-15 semanas | 🔴 CRÍTICA |
| **Testing** | Arreglar 5 failures, eliminar 36 skipped | 1-2 semanas | 🟡 Media |
| **Mobile API** | Actualizar apps + Eliminar Adapters | 6-12 meses | 🟡 Media |
| **Cleanup** | Eliminar código obsoleto, @deprecated | 2-4 días | 🟢 Baja |

### 2. Estimación Total

**66% del sistema requiere trabajo:**
- ⏱️ **19-25 semanas de trabajo**
- 👥 **1-2 desarrolladores full-time**
- 💰 **Inversión crítica en seguridad**

### 3. Roadmap Sugerido

**Fase 1 (Inmediato - 1 semana):**
1. ✅ Completar Analytics refactorización
2. ✅ Arreglar 5 tests failures
3. ✅ Eliminar código obsoleto

**Fase 2 (Corto plazo - 4-6 semanas):**
1. Migrar PHP 7.4 → 8.2
2. Migrar Laravel 5.8 → 10.x
3. Actualizar dependencias críticas

**Fase 3 (Mediano plazo - 8-10 semanas):**
1. Migrar Vue 2 → Vue 3
2. Actualizar Vuetify 2 → 3
3. Refactorizar componentes frontend

**Fase 4 (Largo plazo - 6-12 meses):**
1. Coordinar actualización apps móviles
2. Migrar de MD5 a bcrypt
3. Eliminar Adapters legacy
4. Migrar de JWT a Sanctum

**Ver roadmap completo:** [docs/REFACTORING_ROADMAP.md](docs/REFACTORING_ROADMAP.md)

---

## 🎯 QUICK REFERENCE

### Comandos Frecuentes

```bash
# Testing
vendor/bin/phpunit                              # Todos los tests
vendor/bin/phpunit --filter DriverTest          # Test específico
vendor/bin/phpunit --coverage-text              # Con cobertura

# PHPStan
vendor/bin/phpstan analyse --level=5            # Análisis estático

# Seeder
php artisan migrate:fresh --seed                # Reset BD + TestLabSeeder
php artisan db:seed --class=TestLabSeeder       # Solo seeder

# Verificación mobile
grep -r "methodName" routes/api.php             # Buscar en rutas API
grep -r "ClassName" app/Http/Controllers/Mobile/ # Buscar en mobile

# Git
git status                                      # Ver cambios
git diff                                        # Ver diferencias
git checkout HEAD~1 -- file.php                 # Revertir archivo
```

---

### Estructura de Archivos Críticos

```
app/
├── Actions/                    # ✅ Refactorización V2
│   ├── BaseAction.php         # Template base
│   ├── Driver/                # 14 módulos completados
│   └── Analytics/             # 🔄 Pendiente
├── Http/Controllers/
│   ├── Web/V2/                # ✅ Controllers V2
│   └── Mobile/                # ⚠️ INTOCABLE
├── Repositories/              # ✅ Acceso a datos
├── Traits/
│   ├── ApiResponseTrait.php   # Respuestas JSON
│   └── ValidationResponseTrait.php # Validaciones mejoradas
└── Models/                    # Eloquent models

routes/
├── api.php                    # Rutas API general
├── web.php                    # Rutas web dashboard
└── api/mobile/                # ⚠️ INTOCABLE - Mobile routes

tests/
├── TestConstants.php          # Constantes de testing
├── Feature/                   # Tests de integración
└── Unit/                      # Tests unitarios

database/seeds/
└── TestLabSeeder.php          # ✅ Datos de prueba realistas
```

---

### Contactos y Referencias

**Documentación adicional:**
- [MOBILE_REFERENCE.md](MOBILE_REFERENCE.md) - API Móvil COMPLETA
- [docs/REFACTORING_ROADMAP.md](docs/REFACTORING_ROADMAP.md) - Roadmap de modernización
- [docs/FIX_ROLES_COHERENCE.md](docs/FIX_ROLES_COHERENCE.md) - Sistema de roles
- [docs/VALIDATION_MESSAGES_USAGE_GUIDE.md](docs/VALIDATION_MESSAGES_USAGE_GUIDE.md) - Validaciones
- [docs/FRONTEND_DESIGN_STANDARDS.md](docs/FRONTEND_DESIGN_STANDARDS.md) - ALIO Standard

**Mantenedor:**
- Alberto Granados + AI Assistant

**Última actualización:** 16 de Enero de 2026

---

## 🎓 GUÍA PARA AI AGENTS

### Cómo usar este documento

**Al recibir una tarea:**
1. 📖 Leer sección relevante de este documento
2. ⚠️ Verificar REGLAS DE NEGOCIO CRÍTICAS
3. 🚫 Verificar RESTRICCIONES (especialmente mobile)
4. 📐 Seguir ESTÁNDARES DE DESARROLLO
5. ✅ Aplicar CHECKLIST PRE-COMMIT

**Antes de modificar código:**
```bash
# 1. ¿Es mobile? → Ver MOBILE_REFERENCE.md
grep -r "methodName" routes/api/mobile/

# 2. ¿Tiene rutas activas?
grep -r "ControllerName" routes/

# 3. ¿Es usado en algún lado?
grep -r "ClassName" app/ --include="*.php"

# 4. ¿Afecta reglas de negocio?
# → Leer secciones críticas arriba
```

**Al crear código nuevo:**
- ✅ Usar templates de este documento
- ✅ Seguir convenciones de nombres
- ✅ Aplicar principios SOLID
- ✅ Crear tests (Patrón AAA)
- ✅ Documentar con PHPDoc

**Al refactorizar:**
- ✅ Seguir [docs/REFACTORING_SAFETY_CHECKLIST.md](docs/REFACTORING_SAFETY_CHECKLIST.md)
- ✅ Probar con TestLabSeeder
- ✅ Mantener formato de respuesta
- ✅ No romper mobile
- ✅ Rollback si dudas

---

**Este documento es la FUENTE ÚNICA DE VERDAD del proyecto.  
Ante cualquier duda, consultar este archivo primero.**

_"Context is king. Esta documentación existe para que ningún AI agent (ni humano) tenga que adivinar cómo funciona el sistema."_ 🚀
