# Ejecución - Vigilante: Cámara opcional + Viajes por Ticket (UUID)

## Objetivo
Implementar el flujo de **Vigilante** para sucursal `venta_almacen` donde:
1. Al escanear o generar el ticket/QR, el vigilante controla el acceso por **UUID (ticket)**.
2. El número de **viajes** se pregunta **una sola vez por ticket** (UUID) y no por producto.
3. Para **cada viaje/entrada** registrada se debe capturar **una foto**.
4. La foto se intenta tomar desde la **cámara del navegador** (`getUserMedia`).
5. Si el navegador/PC no detecta cámara o falla permisos (solo para pruebas), la foto se vuelve **no obligatoria**.

## Archivos principales a tocar
- Backend:
  - `app/Http/Controllers/EntregaController.php`
  - `app/Http/Controllers/VentaController.php`
  - (posible) nuevas rutas en `routes/api.php`
- Frontend:
  - `resources/js/src/views/entregas/VigilanteAcceso.vue`
  - (posible) nuevos repositorios si agregas endpoint de “consulta/definir viajes”

---

## Paso 0 - Confirmaciones rápidas (antes de editar)
1. Confirma que el equipo es sucursal `venta_almacen` (Macuspana) y que el módulo de caseta está activo.
2. Verifica que el modelo `entregas` ya soporta foto por viaje:
   - `entregas.foto_path`, `entregas.uuid_qr`, `entregas.numero_viaje`
3. Identifica que el límite de viajes hoy está mezclado entre:
   - `ventas.viajes_*` / `vigilante_qrs.viajes_*` (ticket)
   - y un cálculo legacy basado en `cant` y `Entrega` (legacy)

---

## Paso 1 (Backend) - Hacer FOTO opcional cuando no hay cámara
1. Abre `app/Http/Controllers/EntregaController.php`.
2. En el método `validarYRegistrarAcceso()`:
   - Cambia la validación `foto` de `required` a `nullable`.
   - Agrega un campo boolean `foto_requerida` (opcional, default `true`).
3. Regla de negocio a aplicar:
   - Si `foto_requerida = true` y no viene `foto`, retornar `422` con error de foto.
   - Si `foto_requerida = false`, permitir continuar aunque no venga `foto`.
4. Mantén el guardado de foto condicionado:
   - solo almacenar `foto_path` si `request->hasFile('foto')`.

Entregable del Paso 1:
- El backend ya no bloquea el registro por foto cuando el front indique que la cámara no está disponible.

---

## Paso 2 (Backend) - Viajes deben ser por Ticket/UUID (no por producto)
1. En `app/Http/Controllers/EntregaController.php` dentro de `validarYRegistrarAcceso()`:
   - Busca el registro del ticket: `VigilanteQr::where('uuid', $uuid)->first()`.
2. Modifica el cálculo/validación de viajes para que SIEMPRE (si existe `VigilanteQr`) use:
   - `vigilante_qrs.viajes_permitidos`
   - `vigilante_qrs.viajes_usados`
3. Comportamiento esperado:
   - Si `viajes_usados >= viajes_permitidos` => bloquear (marcar `agotado` si aplica).
   - Si aún hay viajes =>:
     - crear una fila en `entregas` por viaje (como ya se hace)
     - asignar `numero_viaje` = `viajes_usados + 1`
     - incrementar `viajes_usados` en `vigilante_qrs`
4. Remueve/evita el “legacy” que contaba viajes por `Entrega::where('uuid_qr', $uuid)->sum/count` cuando ya existe `VigilanteQr`.

Entregable del Paso 2:
- Límite de viajes queda 100% atado al UUID (ticket), no al `cant` ni a productos.

---

## Paso 3 (Backend) - Permitir definir “número de viajes” para tickets externos/importados
Necesidad:
- Cuando llega un QR externo/importado, hoy `vigilante_qrs` puede crearse con `viajes_permitidos = 1`.
- Requerimos que el vigilante indique “¿Cuántos viajes?” por ticket y se guarde como límite general.

Opción recomendada (para UX correcta):
1. Agregar endpoint “consulta” (sin modificar contadores) para obtener `viajes_permitidos` / `viajes_usados` por `uuid`.
2. Agregar endpoint “definir viajes” (sin registrar un viaje) para setear `viajes_permitidos`.
3. Registrar viaje (con foto) solo después de que el vigilante confirme el número.

Implementación (alto nivel):
1. En `routes/api.php`, agrega:
   - `POST /vigilante/consultar-uuid` (o similar)
   - `POST /vigilante/definir-viajes` (o similar)
2. Backend:
   - endpoint consultar retorna:
     - `exists`, `origen`, `viajes_permitidos`, `viajes_usados`, `estatus`
   - endpoint definir-viajes valida:
     - `numero_viajes` entero >= 1
     - solo permitir modificar si `viajes_usados == 0` o si no existe registro
3. Persistencia:
   - actualizar `vigilante_qrs.viajes_permitidos`

Alternativa (menos limpia pero más rápida):
- En `validarYRegistrarAcceso()`, aceptar `numero_viajes` y si `vigilante_qrs` es nuevo o `viajes_usados==0`, setear `viajes_permitidos` antes de incrementar.

Entregable del Paso 3:
- El número de viajes queda guardado una sola vez por UUID (ticket).

---

## Paso 4 (Frontend) - Captura de foto desde Cámara con getUserMedia (sin input file)
1. Abre `resources/js/src/views/entregas/VigilanteAcceso.vue`.
2. Elimina el uso de inputs:
   - quitar `<input type="file" ... @change="onFotoGenerarChange">` (generar)
   - quitar `<input type="file" ... @change="onFotoAccesoChange">` (escanear)
3. Agrega utilidades de cámara:
   - `navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } })`
   - `video` para preview
   - `canvas` para capturar frame
   - convertir a `Blob` y crear `File` JPEG (ideal: comprimir para no exceder `max:10240` del backend)
4. Control de disponibilidad:
   - Maneja `cameraAvailable=false` si:
     - falla permisos
     - o no hay dispositivo / timeout
   - Cuando `cameraAvailable=false`:
     - UI permite continuar sin foto (para pruebas)
5. Para registrar:
   - En `FormData` agrega `foto_requerida`:
     - `true` si `cameraAvailable` y el usuario tomó foto
     - `false` si `cameraAvailable=false`
   - Si `cameraAvailable=true`, exige que haya foto antes de habilitar “Registrar acceso”.

Entregable del Paso 4:
- Foto por viaje viene de la cámara del dispositivo y solo es obligatoria si realmente hay cámara.

---

## Paso 5 (Frontend) - Preguntar número de viajes SOLO por Ticket/UUID
1. En `VigilanteAcceso.vue`, dentro de `onScanEnter()` (o inmediatamente después de parsear el payload):
   - identifica el `uuid` del payload
2. Flujo recomendado:
   1. Llamar a endpoint `consultar-uuid` para obtener `viajes_permitidos/viajes_usados`.
   2. Si el ticket es nuevo o `viajes_usados==0` y `viajes_permitidos` es el valor por defecto (por ejemplo 1):
      - mostrar un modal/input: “¿Cuántos viajes realizará este ticket?”
      - guardar con endpoint `definir-viajes`
3. Luego habilitar captura de foto y botón “Registrar acceso”.

Alternativa (si decides no agregar endpoint):
- Pide número de viajes siempre en el primer escaneo y envíalo junto con `registrar-acceso`.

Entregable del Paso 5:
- El número de viajes se define una sola vez por UUID y se respeta en cada foto/registro.

---

## Paso 6 - Asegurar que cada viaje toma 1 foto (por escaneo)
1. Verifica que `registrarAcceso()` (llamada a `VigilanteAccesoRepository.registrarAcceso`) ocurre:
   - una vez por cada escaneo aceptado (viaje)
2. Asegura que:
   - `numero_viaje` se calcula por ticket (desde backend)
   - `foto_path` se guarda por `entrega` (ya existe estructura)

Entregable del Paso 6:
- Evidencia por viaje: 1 foto por cada entrada registrada.

---

## Paso 7 - Pruebas y checklist final
1. Prueba con cámara funcionando:
   - generar QR local -> capturar foto -> registrar varios viajes hasta agotarse
   - verificar que el límite de viajes es el del ticket/uuid
   - verificar que se guardan fotos en `entregas.foto_path`
2. Prueba sin cámara (o negando permisos):
   - el sistema no debe bloquear por falta de foto
   - debe registrar viajes y agotar el ticket igual
3. Prueba con QR externo/importado:
   - al primer escaneo se pregunta “¿Cuántos viajes?”
   - el número se guarda y se respeta en escaneos subsecuentes
4. Revisión de errores comunes:
   - timeout de cámara
   - tamaño de imagen excede `max:10240` (ajustar compresión)
   - permisos de cámara en http/https (si aplica)

---

## Notas
- Este documento propone el camino “limpio” con endpoints de consultar/definir para evitar inconsistencias en contadores.
- Si prefieres la alternativa rápida (enviar `numero_viajes` en el mismo `registrar-acceso`), ajusta el Paso 3 y el Paso 5.

