diff --git a/app/Http/Controllers/Api/VehicleController.php b/app/Http/Controllers/Api/VehicleController.php index 1c3aa3b..5310b29 100644 --- a/app/Http/Controllers/Api/VehicleController.php +++ b/app/Http/Controllers/Api/VehicleController.php @@ -21,7 +21,8 @@ public function __construct( ) {} /** - * Consultar y registrar vehículo por PLACA o VIN (Alta de vehículo robado) + * Consultar vehículo por placa/VIN y darlo de alta como robado + * POST /api/vehicles/consultar */ public function consultarVehiculo(Request $request): JsonResponse { @@ -34,37 +35,34 @@ public function consultarVehiculo(Request $request): JsonResponse ]); if ($validator->fails()) { - return ApiResponse::INTERNAL_ERROR->response([ + return ApiResponse::BAD_REQUEST->response([ 'success' => false, 'message' => 'Datos inválidos', 'errors' => $validator->errors() ]); } - $placa = $request->placa; - $vin = $request->vin; + $datosVehiculo = null; - // Buscar vehículo en vehicle_fakes - $vehiculo = VehicleFake::when($vin, function ($query) use ($vin) { - return $query->where('vin', $vin); - }) - ->when($placa, function ($query) use ($placa) { - return $query->orWhere('placa', $placa); - }) - ->first(); + if ($request->vin) { + $datosVehiculo = $this->vehicleService->consultarVehiculoPorTag($request->vin); + } - if (!$vehiculo) { + if (!$datosVehiculo && $request->placa) { + $datosVehiculo = $this->vehicleService->consultarVehiculoPorTag($request->placa); + } + + if (!$datosVehiculo || !isset($datosVehiculo['tag_number'])) { return ApiResponse::NOT_FOUND->response([ 'success' => false, - 'message' => 'No se encontró el vehículo' + 'message' => 'No se encontró el vehículo en el sistema' ]); } - // Generar EPC - $epc = 'E280117000000' . $vehiculo->vin; + $fastId = $datosVehiculo['tag_number']; // Verificar si ya está en Redis - $key = "vehiculo:robado:{$placa}-{$vin}"; + $key = "vehiculo:robado:{$fastId}"; if (Redis::exists($key)) { return ApiResponse::BAD_REQUEST->response([ 'success' => false, @@ -72,50 +70,35 @@ public function consultarVehiculo(Request $request): JsonResponse ]); } - // Guardar en Redis como robado + // Guardar en Redis usando la estructura del VehicleService $datos = [ - 'epc' => $epc, - 'folio_tag' => $vehiculo->folio_tag, - 'tag_number' => $vehiculo->tag_number, - 'vin' => $vehiculo->vin, - 'placa' => $vehiculo->placa, - 'marca' => $vehiculo->marca, - 'modelo' => $vehiculo->modelo, - 'color' => $vehiculo->color, - 'fecha_robo' => now()->format('Y-m-d'), - 'acta' => 'MANUAL-' . now()->format('Ymd-His'), - 'denunciante' => 'SISTEMA', - 'fecha_acta' => now()->format('Y-m-d'), + 'fast_id' => $fastId, + 'vin' => $datosVehiculo['vin'] ?? null, + 'placa' => $datosVehiculo['placa'] ?? null, + 'marca' => $datosVehiculo['marca'] ?? null, + 'modelo' => $datosVehiculo['modelo'] ?? null, + 'color' => $datosVehiculo['color'] ?? null, + 'fecha_robo' => $request->fecha_robo, + 'autoridad' => $request->autoridad, + 'acta' => $request->acta, + 'denunciante' => $request->denunciante, + 'fecha_acta' => $request->fecha_acta, 'primera_deteccion' => now()->toIso8601String(), 'ultima_deteccion' => now()->toIso8601String(), + 'detecciones' => 0 ]; Redis::set($key, json_encode($datos)); - Log::warning('Vehículo dado de alta como robado (MANUAL)', [ - 'epc' => $epc, - 'vin' => $vehiculo->vin, - 'placa' => $vehiculo->placa - ]); - return ApiResponse::OK->response([ 'success' => true, - 'message' => 'Vehículo registrado como robado exitosamente', - 'vehiculo' => [ - 'epc' => $epc, - 'folio_tag' => $vehiculo->folio_tag, - 'tag_number' => $vehiculo->tag_number, - 'vin' => $vehiculo->vin, - 'placa' => $vehiculo->placa, - 'marca' => $vehiculo->marca, - 'modelo' => $vehiculo->modelo, - 'color' => $vehiculo->color - ] + 'message' => 'Vehículo consultado y registrado como robado exitosamente', + 'vehiculo' => $datos ]); } /** - * Dar de baja (registrar como recuperado) un vehículo por PLACA o VIN + * Dar de baja (registrar como recuperado) */ public function recuperarVehiculo(Request $request): JsonResponse { @@ -139,8 +122,6 @@ public function recuperarVehiculo(Request $request): JsonResponse $placa = $request->placa; $vin = $request->vin; - Log::info('Buscando vehículo robado para recuperar', ['placa' => $placa, 'vin' => $vin]); - // 1. Buscar en Redis (vehículos robados activos) $vehiculoEncontrado = $this->buscarEnRedis($vin, $placa); @@ -152,17 +133,10 @@ public function recuperarVehiculo(Request $request): JsonResponse } $datosRedis = $vehiculoEncontrado['datos']; - $epc = $vehiculoEncontrado['epc']; - - Log::info('Vehículo encontrado en Redis', [ - 'epc' => $epc, - 'vin' => $datosRedis['vin'], - 'placa' => $datosRedis['placa'] - ]); // 2. Guardar en MySQL como recuperado $vehiculoRecuperado = Vehicle::create([ - 'epc' => $epc, + 'fast_id' => $datosRedis['fast_id'] ?? null, 'vin' => $datosRedis['vin'] ?? null, 'placa' => $datosRedis['placa'] ?? null, 'fecha_robo' => $datosRedis['fecha_robo'] ?? null, @@ -174,20 +148,15 @@ public function recuperarVehiculo(Request $request): JsonResponse ]); // 3. Eliminar de Redis - Redis::del("vehiculo:robado:{$epc}"); - - Log::info('Vehículo registrado como recuperado', [ - 'id' => $vehiculoRecuperado->id, - 'vin' => $vehiculoRecuperado->vin, - 'placa' => $vehiculoRecuperado->placa - ]); + $fastId = $vehiculoEncontrado['fast_id']; + Redis::del("vehiculo:robado:{$fastId}"); return ApiResponse::OK->response([ 'success' => true, 'message' => 'Vehículo registrado como recuperado exitosamente', 'vehiculo' => [ 'id' => $vehiculoRecuperado->id, - 'epc' => $vehiculoRecuperado->epc, + 'fast_id' => $vehiculoRecuperado->fast_id, 'vin' => $vehiculoRecuperado->vin, 'placa' => $vehiculoRecuperado->placa, 'fecha_robo' => $vehiculoRecuperado->fecha_robo, @@ -211,7 +180,7 @@ public function recuperarVehiculo(Request $request): JsonResponse } /** - * Buscar vehículo en Redis por VIN o Placa + * Buscar vehículo en Redis */ private function buscarEnRedis(?string $vin, ?string $placa): ?array { @@ -227,11 +196,11 @@ private function buscarEnRedis(?string $vin, ?string $placa): ?array // Buscar por VIN o Placa if (($vin && $vehiculo['vin'] === $vin) || ($placa && $vehiculo['placa'] === $placa)) { - // Extraer el EPC del key - $epc = str_replace('vehiculo:robado:', '', $key); + // Extraer el fast_id del key + $fastId = str_replace('vehiculo:robado:', '', $key); return [ - 'epc' => $epc, + 'fast_id' => $fastId, 'datos' => $vehiculo ]; } @@ -298,6 +267,39 @@ public function listarDetecciones() ]); } + /** + * Listar detecciones del día desde Redis + * GET /api/vehicles/detecciones/dia + */ + public function listarDeteccionesDelDia(Request $request) + { + $fecha = $request->input('fecha'); // Formato: Y-m-d (opcional) + + if ($fecha && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $fecha)) { + return ApiResponse::BAD_REQUEST->response([ + 'success' => false, + 'message' => 'Formato de fecha inválido. Use YYYY-MM-DD' + ]); + } + + try { + $detecciones = $this->vehicleService->listarDeteccionesDelDia($fecha); + + return ApiResponse::OK->response([ + 'success' => true, + 'fecha' => $fecha ?? now()->format('Y-m-d'), + 'total' => count($detecciones), + 'detecciones' => $detecciones + ]); + } catch (\Exception $e) { + return ApiResponse::INTERNAL_ERROR->response([ + 'success' => false, + 'message' => 'Error al obtener detecciones del día', + 'error' => $e->getMessage() + ]); + } + } + public function buscarVehiculo(Request $request) { $validated = $request->validate([ @@ -385,18 +387,14 @@ public function buscarPorTag(Request $request) { $validated = $request->validate([ 'fast_id' => 'required|string', - 'epc' => 'nullable|string', + 'antena' => 'nullable|string', 'timestamp' => 'nullable|date' ]); // Obtener el arco autenticado del middleware $arco = $request->get('arco_autenticado'); - // Si no se proporciona EPC, usar el FastID como identificador - $epc = $validated['epc'] ?? $validated['fast_id']; - $resultado = $this->vehicleService->procesarDeteccion( - $epc, $validated['fast_id'], $arco->ip_address, $validated['timestamp'] ?? null diff --git a/app/Models/Detection.php b/app/Models/Detection.php index 8250a76..7bd9fab 100644 --- a/app/Models/Detection.php +++ b/app/Models/Detection.php @@ -18,7 +18,7 @@ class Detection extends Model protected $fillable = [ 'arco_id', - 'epc', + 'fast_id', 'vin', 'placa', 'marca', diff --git a/app/Models/Vehicle.php b/app/Models/Vehicle.php index e3627ee..a1e020e 100644 --- a/app/Models/Vehicle.php +++ b/app/Models/Vehicle.php @@ -10,7 +10,7 @@ class Vehicle extends Model { protected $fillable = [ - 'epc', + 'fast_id', 'vin', 'placa', 'fecha_robo', diff --git a/app/Services/ConsultaRepuveConstancia.php b/app/Services/ConsultaRepuveConstancia.php index da97cff..34fd9dc 100644 --- a/app/Services/ConsultaRepuveConstancia.php +++ b/app/Services/ConsultaRepuveConstancia.php @@ -27,15 +27,15 @@ public function __construct() } /** - * Consultar vehículo por tag_number + * Consultar vehículo por tag_number, placa o VIN * */ - public function consultarVehiculoPorTag(?string $tagNumber = null) + public function consultarVehiculoPorTag(?string $criterio = null) { try { - // solo busca por tag_number - if (empty($tagNumber)) { - Log::warning('ConsultaRepuveConstancia: No se proporcionó tag_number'); + // Validar que se proporcionó algún criterio de búsqueda + if (empty($criterio)) { + Log::warning('ConsultaRepuveConstancia: No se proporcionó criterio de búsqueda'); return null; } @@ -46,19 +46,54 @@ public function consultarVehiculoPorTag(?string $tagNumber = null) return null; } - // Consultar vehículos con filtro tag_number + // Determinar el tipo de búsqueda (intentar primero como tag_number, luego placa, luego VIN) $url = $this->baseUrl . $this->vehiculosEndpoint; Log::info('ConsultaRepuveConstancia: Consultando', [ 'url' => $url, - 'tag_number' => $tagNumber + 'criterio' => $criterio ]); + // Intentar buscar por tag_number primero $response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $token, 'Accept' => 'application/json', ])->timeout(30)->get($url, [ - 'tag_number' => $tagNumber + 'tag_number' => $criterio + ]); + + // Si no lo encuentra por tag_number, intentar por placa + if ($response->successful()) { + $data = $response->json(); + if (isset($data['data']['records']['data']) && !empty($data['data']['records']['data'])) { + $vehiculoEncontrado = $data['data']['records']['data'][0]; + return $this->transformarDatosVehiculo($vehiculoEncontrado); + } + } + + // Intentar búsqueda por placa + $response = Http::withHeaders([ + 'Authorization' => 'Bearer ' . $token, + 'Accept' => 'application/json', + ])->timeout(30)->get($url, [ + 'placa' => $criterio + ]); + + // Si no lo encuentra por placa, intentar por VIN + if ($response->successful()) { + $data = $response->json(); + if (isset($data['data']['records']['data']) && !empty($data['data']['records']['data'])) { + $vehiculoEncontrado = $data['data']['records']['data'][0]; + return $this->transformarDatosVehiculo($vehiculoEncontrado); + } + } + + // Intentar búsqueda por VIN + $response = Http::withHeaders([ + 'Authorization' => 'Bearer ' . $token, + 'Accept' => 'application/json', + ])->timeout(30)->get($url, [ + 'niv' => $criterio ]); if (!$response->successful()) { @@ -84,7 +119,7 @@ public function consultarVehiculoPorTag(?string $tagNumber = null) if (empty($vehiculos)) { Log::info('ConsultaRepuveConstancia: Vehículo no encontrado', [ - 'tag_number' => $tagNumber + 'criterio' => $criterio ]); return null; } @@ -96,7 +131,7 @@ public function consultarVehiculoPorTag(?string $tagNumber = null) } catch (Exception $e) { Log::error('ConsultaRepuveConstancia: Error al consultar vehículo', [ - 'tag_number' => $tagNumber, + 'criterio' => $criterio, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); diff --git a/app/Services/VehicleService.php b/app/Services/VehicleService.php index 8fff7d5..2946dbe 100644 --- a/app/Services/VehicleService.php +++ b/app/Services/VehicleService.php @@ -11,13 +11,15 @@ class VehicleService { public function __construct( - private ReporteRoboService $reporteRobo, private ConsultaRepuveConstancia $consultaRepuveCons ) {} - public function procesarDeteccion(string $epc, string $fastId, string $arcoIp, ?string $timestamp = null): array + /** + * Procesar detección de vehículo por fast_id + */ + public function procesarDeteccion(string $fastId, string $arcoIp): array { - $key = "vehiculo:robado:{$epc}"; + $key = "vehiculo:robado:{$fastId}"; // Buscar arco por IP $arco = Arco::buscarPorIp($arcoIp); @@ -28,171 +30,53 @@ public function procesarDeteccion(string $epc, string $fastId, string $arcoIp, ? if ($enRedis) { // Ya está marcado como robado, verificar si sigue así - $resultado = $this->verificarVehiculoRobado($epc, json_decode($enRedis, true)); - $this->registrarDeteccion($epc, $resultado, $arcoId); + $resultado = $this->verificarVehiculoRobado($fastId, json_decode($enRedis, true)); + $this->registrarDeteccion($fastId, $resultado, $arcoId); return $resultado; } // No está en Redis, consultar servicios - $resultado = $this->consultarNuevoVehiculo($epc, $fastId); - $this->registrarDeteccion($epc, $resultado, $arcoId); + $resultado = $this->consultarNuevoVehiculo($fastId); + $this->registrarDeteccion($fastId, $resultado, $arcoId); return $resultado; } - private function consultarNuevoVehiculo(string $epc, string $fastId): array + /** + * Consultar vehículo por tag_id, placa o VIN + */ + public function consultarVehiculoPorTag(string $fastId) { - // Consultar con FastID (tag_number) - $datosVehiculo = $this->consultaRepuveCons->consultarVehiculoPorTag($fastId); + try { + $vehiculoExterno = $this->consultaRepuveCons->consultarVehiculoPorTag($fastId); - if (!$datosVehiculo || !$datosVehiculo['vin']) { - Log::warning('Vehículo NO encontrado.', [ - 'epc' => $epc, - 'fast_id' => $fastId - ]); + if ($vehiculoExterno) { + Log::info('VehicleService: Vehículo encontrado', [ + 'fast_id' => $fastId, + 'tag_number' => $vehiculoExterno['tag_number'] ?? null, + 'placa' => $vehiculoExterno['placa'] ?? null, + 'vin' => $vehiculoExterno['vin'] ?? null + ]); + } else { + Log::info('VehicleService: Vehículo no encontrado', [ + 'fast_id' => $fastId + ]); + } - return [ - 'success' => false, - 'message' => 'No se encontró información del vehículo.' - ]; - } + return $vehiculoExterno; - // Consultar REPUVE para verificar si está robado - $reporteRobo = $this->reporteRobo->consultarRobado( - $datosVehiculo['vin'], - $datosVehiculo['placa'] - ); - - if ($reporteRobo['tiene_reporte']) { - // Está robado → Guardar en Redis - $this->guardarEnRedis($epc, $datosVehiculo, $reporteRobo['datos']); - - Log::warning('¡VEHÍCULO ROBADO DETECTADO!', [ - 'epc' => $epc, + } catch (\Exception $e) { + Log::error('VehicleService: Error en consulta', [ 'fast_id' => $fastId, - 'vin' => $datosVehiculo['vin'], - 'placa' => $datosVehiculo['placa'] + 'error' => $e->getMessage(), + 'trace' => $e->getTraceAsString() ]); - - return [ - 'success' => true, - 'tiene_reporte_robo' => true, - 'estado' => 'ROBADO', - 'accion' => 'GUARDADO EN BD DE ROBADOS', - 'vehiculo' => array_merge($datosVehiculo, $reporteRobo['datos']) - ]; + return null; } - - // No está robado - vehículo LIBRE - Log::info('Vehículo detectado - LIBRE (sin reporte de robo)', [ - 'epc' => $epc, - 'fast_id' => $fastId, - 'vin' => $datosVehiculo['vin'], - 'placa' => $datosVehiculo['placa'] - ]); - - return [ - 'success' => true, - 'tiene_reporte_robo' => false, - 'estado' => 'LIBRE', - 'vehiculo' => $datosVehiculo - ]; - } - - private function verificarVehiculoRobado(string $epc, array $datosRedis): array - { - // Consultar REPUVE para verificar estado actual - $reporteRobo = $this->reporteRobo->consultarRobado( - $datosRedis['vin'], - $datosRedis['placa'] - ); - - if (!$reporteRobo['tiene_reporte']) { - // No tiene reporte robo - RECUPERADO - $this->registrarRecuperacion($epc, $datosRedis); - - Log::info('¡VEHÍCULO RECUPERADO!', [ - 'epc' => $epc, - 'vin' => $datosRedis['vin'], - 'placa' => $datosRedis['placa'] - ]); - - return [ - 'success' => true, - 'tiene_reporte_robo' => false, - 'estado' => 'RECUPERADO', - 'accion' => 'GUARDADO EN RECUPERADOS Y ELIMINADO DE ROBADOS', - 'vehiculo' => $datosRedis - ]; - } - - // Sigue robado → Actualizar contador en Redis - $this->actualizarDeteccionRedis($epc, $datosRedis); - - Log::warning('Vehículo robado detectado nuevamente', [ - 'epc' => $epc, - 'detecciones' => $datosRedis['detecciones'] + 1 - ]); - - return [ - 'success' => true, - 'tiene_reporte_robo' => true, - 'estado' => 'ROBADO', - 'accion' => 'ACTUALIZADO_EN_REDIS', - 'vehiculo' => $datosRedis - ]; - } - - private function guardarEnRedis(string $epc, array $datosEstatal, array $datosRobo) - { - $key = "vehiculo:robado:{$epc}"; - - $datos = [ - 'epc' => $epc, - 'vin' => $datosEstatal['vin'], - 'placa' => $datosEstatal['placa'], - 'fecha_robo' => $datosRobo['fecha_robo'] ?? null, - 'autoridad' => $datosRobo['autoridad'] ?? null, - 'acta' => $datosRobo['acta'] ?? null, - 'denunciante' => $datosRobo['denunciante'] ?? null, - 'fecha_acta' => $datosRobo['fecha_acta'] ?? null, - 'primera_deteccion' => now()->toIso8601String(), - 'ultima_deteccion' => now()->toIso8601String(), - 'detecciones' => 1 - ]; - - Redis::set($key, json_encode($datos)); - } - - private function actualizarDeteccionRedis(string $epc, array $datosActuales) - { - $key = "vehiculo:robado:{$epc}"; - - $datosActuales['ultima_deteccion'] = now()->toIso8601String(); - $datosActuales['detecciones'] = ($datosActuales['detecciones'] ?? 0) + 1; - - Redis::set($key, json_encode($datosActuales)); - } - - private function registrarRecuperacion(string $epc, array $datosRedis) - { - // Guardar en MySQL - Vehicle::create([ - 'epc' => $epc, - 'vin' => $datosRedis['vin'], - 'placa' => $datosRedis['placa'], - 'fecha_robo' => $datosRedis['fecha_robo'], - 'autoridad_robo' => $datosRedis['autoridad'], - 'acta_robo' => $datosRedis['acta'], - 'denunciante' => $datosRedis['denunciante'], - 'fecha_recuperacion' => now(), - 'fecha_acta' => $datosRedis['fecha_acta'] ?? null, - 'datos_robo_original' => $datosRedis - ]); - - // Eliminar de Redis - Redis::del("vehiculo:robado:{$epc}"); } + /** + * Listar todos los vehículos robados activos en Redis + */ public function listarVehiculosRobados(): array { $keys = Redis::keys('vehiculo:robado:*'); @@ -208,7 +92,128 @@ public function listarVehiculosRobados(): array return $vehiculos; } - private function registrarDeteccion(string $epc, array $resultado, ?int $arcoId = null) + /** + * Listar todas las detecciones del día desde Redis + * @param string|null $fecha Fecha en formato Y-m-d (opcional, por defecto hoy) + * @return array + */ + public function listarDeteccionesDelDia(?string $fecha = null): array + { + $fecha = $fecha ?? now()->format('Y-m-d'); + $pattern = "deteccion:dia:{$fecha}:*"; + $keys = Redis::keys($pattern); + $detecciones = []; + + foreach ($keys as $key) { + $datos = Redis::get($key); + if ($datos) { + $detecciones[] = json_decode($datos, true); + } + } + + // Ordenar por fecha de detección (más reciente primero) + usort($detecciones, function($a, $b) { + return strcmp($b['fecha_deteccion'], $a['fecha_deteccion']); + }); + + return $detecciones; + } + + /** + * Obtener estadísticas de detecciones del día + * @param string|null $fecha Fecha en formato Y-m-d (opcional, por defecto hoy) + * @return array + */ + public function obtenerEstadisticasDelDia(?string $fecha = null): array + { + $detecciones = $this->listarDeteccionesDelDia($fecha); + + $total = count($detecciones); + $robados = collect($detecciones)->where('tiene_reporte_robo', true)->count(); + $libres = collect($detecciones)->where('tiene_reporte_robo', false)->count(); + + return [ + 'fecha' => $fecha ?? now()->format('Y-m-d'), + 'total_detecciones' => $total, + 'vehiculos_robados' => $robados, + 'vehiculos_libres' => $libres, + 'detecciones' => $detecciones + ]; + } + + /** + * Consultar nuevo vehículo (no está en Redis de robados) + */ + private function consultarNuevoVehiculo(string $fastId): array + { + // Consultar con FastID (tag_number) + $datosVehiculo = $this->consultaRepuveCons->consultarVehiculoPorTag($fastId); + + if (!$datosVehiculo || !$datosVehiculo['vin']) { + Log::warning('Vehículo NO encontrado.', [ + 'fast_id' => $fastId + ]); + + return [ + 'success' => false, + 'message' => 'No se encontró información del vehículo.' + ]; + } + + Log::info('Vehículo detectado - LIBRE (no está en Redis de robados)', [ + 'fast_id' => $fastId, + 'vin' => $datosVehiculo['vin'], + 'placa' => $datosVehiculo['placa'] + ]); + + return [ + 'success' => true, + 'tiene_reporte_robo' => false, + 'estado' => 'LIBRE', + 'vehiculo' => $datosVehiculo + ]; + } + + /** + * Verificar vehículo robado (ya está en Redis) + */ + private function verificarVehiculoRobado(string $fastId, array $datosRedis): array + { + $this->actualizarDeteccionRedis($fastId, $datosRedis); + + Log::warning('Vehículo robado detectado nuevamente', [ + 'fast_id' => $fastId, + 'vin' => $datosRedis['vin'] ?? null, + 'placa' => $datosRedis['placa'] ?? null, + 'detecciones' => ($datosRedis['detecciones'] ?? 0) + 1 + ]); + + return [ + 'success' => true, + 'tiene_reporte_robo' => true, + 'estado' => 'ROBADO', + 'accion' => 'ACTUALIZADO_EN_REDIS', + 'vehiculo' => $datosRedis + ]; + } + + /** + * Actualizar contador de detecciones en Redis + */ + private function actualizarDeteccionRedis(string $fastId, array $datosActuales) + { + $key = "vehiculo:robado:{$fastId}"; + + $datosActuales['ultima_deteccion'] = now()->toIso8601String(); + $datosActuales['detecciones'] = ($datosActuales['detecciones'] ?? 0) + 1; + + Redis::set($key, json_encode($datosActuales)); + } + + /** + * Registrar detección en MySQL y Redis (detecciones del día) + */ + private function registrarDeteccion(string $fastId, array $resultado, ?int $arcoId = null) { if (!$resultado['success'] || !isset($resultado['vehiculo'])) { return; @@ -216,9 +221,10 @@ private function registrarDeteccion(string $epc, array $resultado, ?int $arcoId $vehiculo = $resultado['vehiculo']; + // Registrar en MySQL Detection::create([ 'arco_id' => $arcoId, - 'epc' => $epc, + 'fast_id' => $fastId, 'vin' => $vehiculo['vin'] ?? null, 'placa' => $vehiculo['placa'] ?? null, 'marca' => $vehiculo['marca'] ?? null, @@ -226,42 +232,43 @@ private function registrarDeteccion(string $epc, array $resultado, ?int $arcoId 'color' => $vehiculo['color'] ?? null, 'fecha_deteccion' => now() ]); + + // Registrar en Redis (detecciones del día) + $this->registrarDeteccionDelDia($fastId, $vehiculo, $arcoId, $resultado); } /** - * Consultar vehículo por tag_id + * Registrar detección en Redis para el día actual + * Formato de key: deteccion:dia:YYYY-MM-DD:{fastId}:{timestamp} + * Expira automáticamente a las 23:59:59 del día */ - public function consultarVehiculoPorTag(?string $epc = null, ?string $tagId = null) + private function registrarDeteccionDelDia(string $fastId, array $vehiculo, ?int $arcoId, array $resultado) { - try { - // Validar que se proporcionó tag_id - if (empty($tagId)) { - Log::warning('VehicleService: No se proporcionó tag_id'); - return null; - } - $vehiculoExterno = $this->consultaRepuveCons->consultarVehiculoPorTag($tagId); + $fecha = now()->format('Y-m-d'); + $timestamp = now()->timestamp; + $key = "deteccion:dia:{$fecha}:{$fastId}:{$timestamp}"; - if ($vehiculoExterno) { - Log::info('VehicleService: Vehículo encontrado', [ - 'tag_id' => $vehiculoExterno['tag_id'] ?? null, - 'tag_number' => $vehiculoExterno['tag_number'] ?? null, - 'vin' => $vehiculoExterno['vin'] ?? null - ]); - } else { - Log::info('VehicleService: Vehículo no encontrado', [ - 'tag_id' => $tagId - ]); - } + $datosDeteccion = [ + 'fast_id' => $fastId, + 'vin' => $vehiculo['vin'] ?? null, + 'placa' => $vehiculo['placa'] ?? null, + 'marca' => $vehiculo['marca'] ?? null, + 'modelo' => $vehiculo['modelo'] ?? null, + 'color' => $vehiculo['color'] ?? null, + 'arco_id' => $arcoId, + 'estado' => $resultado['estado'] ?? 'LIBRE', + 'tiene_reporte_robo' => $resultado['tiene_reporte_robo'] ?? false, + 'fecha_deteccion' => now()->toIso8601String(), + ]; - return $vehiculoExterno; + // Guardar en Redis + Redis::set($key, json_encode($datosDeteccion)); - } catch (\Exception $e) { - Log::error('VehicleService: Error en consulta', [ - 'tag_id' => $tagId, - 'error' => $e->getMessage(), - 'trace' => $e->getTraceAsString() - ]); - return null; - } + // Calcular segundos hasta el final del día (23:59:59) + $finDelDia = now()->endOfDay(); + $segundosHastaFinDelDia = $finDelDia->timestamp - now()->timestamp; + + // Establecer expiración automática al final del día + Redis::expire($key, $segundosHastaFinDelDia); } } diff --git a/database/migrations/2026_01_08_162600_rename_epc_to_fast_id_in_tables.php b/database/migrations/2026_01_08_162600_rename_epc_to_fast_id_in_tables.php new file mode 100644 index 0000000..3567cc3 --- /dev/null +++ b/database/migrations/2026_01_08_162600_rename_epc_to_fast_id_in_tables.php @@ -0,0 +1,40 @@ +renameColumn('epc', 'fast_id'); + }); + + // Renombrar columna en tabla vehicles + Schema::table('vehicles', function (Blueprint $table) { + $table->renameColumn('epc', 'fast_id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + // Revertir cambio en tabla detections + Schema::table('detections', function (Blueprint $table) { + $table->renameColumn('fast_id', 'epc'); + }); + + // Revertir cambio en tabla vehicles + Schema::table('vehicles', function (Blueprint $table) { + $table->renameColumn('fast_id', 'epc'); + }); + } +}; diff --git a/routes/api.php b/routes/api.php index 9b6b31b..007b742 100644 --- a/routes/api.php +++ b/routes/api.php @@ -33,6 +33,7 @@ Route::get('/vehicles/robados', [VehicleController::class, 'listarRobados']); Route::get('/vehicles', [VehicleController::class, 'listarRecuperados']); Route::get('/vehicles/detecciones', [VehicleController::class, 'listarDetecciones']); + Route::get('/vehicles/detecciones/dia', [VehicleController::class, 'listarDeteccionesDelDia']); Route::get('/vehicles/robado', [VehicleController::class, 'buscarVehiculoRobado']); // Rutas de Arcos RFID