Buscar en la documentación

Cumplimiento de la prueba técnica

Cada punto de la prueba, dónde se cumple y cómo comprobarlo.

8 min de lecturaVer en GitHub

Recorre la prueba en su mismo orden. Cada fila dice dónde se cumple y cómo verlo funcionando. Lo que se hizo de más está en mejoras aplicadas y lo que se propone a futuro, en mejoras propuestas.

Tecnologías mínimas

PedidoCumplimiento
PHP 8+PHP 8.4 (ADR-0038)
Laravel 10+Laravel 13
MySQL o MariaDBMySQL 8.4 LTS (ADR-0007)
Vue.js 3Vue 3 con TypeScript (ADR-0004)
Quasar o VuetifyQuasar como plugin de Vite, confinado a la presentación (ADR-0005, ADR-0039)
DockerTodo el sistema corre con docker compose up -d (ADR-0025)

Backend

1. Autenticación

PedidoDóndeCómo comprobarlo
LoginPOST /api/v1/auth/login en AuthControllerIngresar en /ingresar con una credencial de prueba
LogoutPOST /api/v1/auth/logout (revoca el token)Círculo con las iniciales, al final del menú de abajo → Cerrar sesión
Protección de rutasMiddleware auth:sanctum en cada módulo (rutas de Auth) y guarda del front (authGuard)Abrir /incidentes sin sesión lleva al login; la API responde 401 UNAUTHENTICATED
Sugerencia: SanctumLaravel Sanctum con tokens de API (ADR-0015)LoginTest, SessionTest

2. CRUD de incidentes

Campo pedidoColumna en incidents (diccionario)
idid (clave interna) y ulid (identificador público en la API, ADR-0010)
títulotitle
descripcióndescription
prioridadpriority_id, FK al catálogo priorities (ADR-0008)
estadostatus_id, FK al catálogo statuses, con transiciones permitidas
usuario creadorcreated_by, FK obligatoria a users
usuario asignadoassigned_to, FK opcional a users
fecha de vencimientodue_date (si no se indica, se calcula con el tiempo de la prioridad)
timestampscreated_at, updated_at, además de resolved_at y deleted_at

Endpoints en IncidentController e IncidentWorkflowController; detalle en el módulo Incidents. Pruebas: CreateIncidentTest e IncidentLifecycleTest.

3. Listado avanzado

PedidoCumplimiento
Paginaciónpage y per_page (máximo 100, impuesto por el back)
Ordenamientosort con lista blanca de campos y desempate por id
Búsqueda por textosearch con índice FULLTEXT y búsqueda por código TZ-26-0142 (ADR-0013)
Filtro por prioridadfilter[priority]
Filtro por estadofilter[status]
Filtro por usuario asignadofilter[assignee] (también “sin asignar”)
Filtro por rango de fechasSobre la creación y sobre el vencimiento; además, solo vencidos

Consulta en EloquentIncidentList e IncidentFilters; decisiones en ADR-0044. Pruebas: ListIncidentsTest y SearchIncidentsTest.

4. Dashboard

PedidoCumplimiento
Total de incidentes“Total” en el pulso de la operación (también el widget “Total de incidentes”)
Incidentes por estado“Flujo de estados”: cada estado con su cantidad, Cancelado como salida (también el gráfico “Por estado”)
Incidentes vencidosEn la frase del pulso y en la columna “Vencido” del mapa de riesgo (también el widget “Vencidos”)
Incidentes por prioridadColumna “Total” del mapa de riesgo: todos los de cada prioridad, en cualquier estado (también el gráfico “Por prioridad”, con porcentaje)

Todo eso está en el diseño original del inicio, centrado en el riesgo (ADR-0081). Cada cifra respeta lo que la persona puede ver y lleva al listado ya filtrado. Además: cumplimiento del plazo, mapa de riesgo por vencimiento, balance del backlog, próximos a vencer, asignados a mí y carga por agente; y en “Agregar widget”, los indicadores y gráficos clásicos, sin asignar y creados contra resueltos. Consultas en EloquentDashboardQueries, con caché (ADR-0047). Pruebas: DashboardMetricsTest.

5. Rendimiento

PedidoCumplimiento
Eager loadingwith() con columnas acotadas en el listado y el detalle de incidentes, el historial y los usuarios; los eventos del sistema y la auditoría usan JOIN directo
Optimización de consultasLecturas pesadas por query services propios (ADR-0002); conteos del dashboard en una sola pasada
Evitar N+1Fuera de producción, leer una relación sin with() lanza una excepción, así que la suite completa detecta cualquier N+1 nuevo (carga diferida estricta). Además, pruebas que comparan el número de consultas con 5 y con 40 registros (ListIncidentsTest, ListQueriesTest)
Índices SQLÍndices por FK, únicos, compuestos y FULLTEXT, validados con EXPLAIN sobre 100.000 incidentes (rendimiento)
Estructura limpia de endpointsREST versionado en /api/v1, recursos en plural, errores RFC 9457 (convenciones, OpenAPI)

Frontend

PedidoDónde
LoginLoginPage en /ingresar
DashboardDashboardPage, página de inicio
Listado de incidentesIncidentListPage en /incidentes
Crear/editar incidenteIncidentFormPage, un solo formulario para los dos casos
Vista detalleIncidentDetailPage, con historial
Manejo centralizado de peticionesUn único cliente HTTP en shared/http/client.ts; las vistas nunca llaman a la API directamente
InterceptoresToken, X-Request-Id, reintento de GET ante fallas de red, sesión vencida y mantenimiento (http y errores)
Manejo de tokentokenStore; se borra solo ante UNAUTHENTICATED

Pruebas de extremo a extremo de cada pantalla en las cuatro vistas: frontend/e2e.

Docker (obligatorio)

PedidoServicio en docker-compose.yml
docker-compose.ymlBase común, más docker-compose.override.yml para local (Mailpit) y docker-compose.dev.yml para desarrollar (dos modos)
Contenedor para Laravelapp (PHP-FPM); la misma imagen para worker, scheduler y reverb
Nginx/Apachegateway (Nginx, único puerto publicado) y frontend (Nginx con el build de Vue)
MySQL/MariaDBmysql 8.4, en una red interna sin salida
Frontend Vuefrontend
docker compose up -dUn solo comando: init corre migraciones y seeders de forma idempotente (Docker)

Idealmente

PedidoCumplimiento
WebSockets o tiempo realLaravel Reverb por canales privados (ADR-0057)
Tests con PHPUnit o PestPest con MySQL real: unitarias, de API, de arquitectura y de N+1; cobertura exigida de 90 % en dominio y aplicación (estrategia)
Roles y permisos5 roles sobre permisos granulares, con excepciones por persona (ADR-0053)
Exportación a Excel/CSVCSV para Excel con los filtros del listado (ADR-0058)
Logs o auditoríaHistorial por incidente, auditoría global y eventos del sistema (ADR-0056, ADR-0059)

Entregables

PedidoCumplimiento
Repositorio GitMonorepo con flujo de ramas feature/* → dev → stage → main (ADR-0033)
README: instalaciónInstalación
README: variables de entornoVariables de entorno
README: migracionesMigraciones
README: seedersSeeders
README: credenciales de pruebaCredenciales de prueba

Datos de prueba

PedidoCumplimiento
Mínimo 500 incidentes600 por defecto (SEED_INCIDENTS), con historial completo y coherente
Múltiples usuarios9 cuentas de demostración, una o más por rol
Diferentes estados y prioridadesLos 6 estados y las 4 prioridades, con ~40 % de pendientes vencidos

Lo verifica DemoDataTest; detalle en seeders.

Criterios de evaluación

CriterioCómo se atiende
Responsive Front/BackCuatro vistas (celular, tablet, portátil y monitor) con breakpoints como tokens; las E2E corren en las cuatro. El back entrega lo mismo a todas y pagina con un máximo
Validaciones visuales Front/BackEl back valida todo y responde un código por regla y por campo; el front valida antes de enviar y muestra cada error junto a su campo
Manejo de errores Front/BackRFC 9457 con código propio y trace_id; el front traduce cada código a un mensaje claro (catálogo de errores)
Lo idealmente requerido en DockerTodo lo de la sección “Idealmente” corre dentro del mismo docker compose up -d
EjecutableVerificado desde un clon limpio, sin pasos adicionales (verificación)
Mayoría de criteriosSe cumplen todos los obligatorios y todos los ideales

Verificación desde cero

Se clonó el repositorio en una carpeta nueva, sin .env ni volúmenes previos, y se siguió el README tal cual. Las imágenes se construyeron sin caché para simular un equipo que nunca ha corrido el proyecto.

PasoResultado
Construcción de imágenes (sin caché)Unos 3 minutos
docker compose up -dUnos 3 minutos; todos los servicios sanos e init terminado con código 0
Datos sembrados600 incidentes, 9 usuarios, 6 estados, 4 prioridades y unas 3.100 entradas de historial
APILogin, sesión, dashboard, listado con filtros y búsqueda, catálogos y logout (después, 401)
InterfazLogin, verificación en dos pasos pospuesta, dashboard, listado y formulario de creación
Pruebas del backendcomposer check dentro del stack: Pint, Larastan y 350 pruebas de Pest sin fallas

Hallazgos que quedaron corregidos en el README:

  • Rutas largas en Windows. Clonar dentro de una carpeta muy profunda supera el límite de 260 caracteres de Windows y Git no termina el checkout.
  • Actualizar con dependencias nuevas del front. node_modules vive en un volumen anónimo que Compose reutiliza al recrear el contenedor, así que una imagen reconstruida no basta.