275 lines
8.6 KiB
PHP
275 lines
8.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Vehicle;
|
|
use App\Models\Detection;
|
|
use App\Models\Arco;
|
|
use Illuminate\Support\Facades\Redis;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class VehicleService
|
|
{
|
|
public function __construct(
|
|
private ConsultaRepuveConstancia $consultaRepuveCons
|
|
) {}
|
|
|
|
/**
|
|
* Procesar detección de vehículo por fast_id
|
|
*/
|
|
public function procesarDeteccion(string $fastId, string $arcoIp): array
|
|
{
|
|
$key = "vehiculo:robado:{$fastId}";
|
|
|
|
// Buscar arco por IP
|
|
$arco = Arco::buscarPorIp($arcoIp);
|
|
$arcoId = $arco?->id;
|
|
|
|
// Verificar si está en Redis
|
|
$enRedis = Redis::get($key);
|
|
|
|
if ($enRedis) {
|
|
// Ya está marcado como robado, verificar si sigue así
|
|
$resultado = $this->verificarVehiculoRobado($fastId, json_decode($enRedis, true));
|
|
$this->registrarDeteccion($fastId, $resultado, $arcoId);
|
|
return $resultado;
|
|
}
|
|
|
|
// No está en Redis, consultar servicios
|
|
$resultado = $this->consultarNuevoVehiculo($fastId);
|
|
$this->registrarDeteccion($fastId, $resultado, $arcoId);
|
|
return $resultado;
|
|
}
|
|
|
|
/**
|
|
* Consultar vehículo por tag_id, placa o VIN
|
|
*/
|
|
public function consultarVehiculoPorTag(string $fastId)
|
|
{
|
|
try {
|
|
$vehiculoExterno = $this->consultaRepuveCons->consultarVehiculoPorTag($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 $vehiculoExterno;
|
|
|
|
} catch (\Exception $e) {
|
|
Log::error('VehicleService: Error en consulta', [
|
|
'fast_id' => $fastId,
|
|
'error' => $e->getMessage(),
|
|
'trace' => $e->getTraceAsString()
|
|
]);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Listar todos los vehículos robados activos en Redis
|
|
*/
|
|
public function listarVehiculosRobados(): array
|
|
{
|
|
$keys = Redis::keys('vehiculo:robado:*');
|
|
$vehiculos = [];
|
|
|
|
foreach ($keys as $key) {
|
|
$datos = Redis::get($key);
|
|
if ($datos) {
|
|
$vehiculos[] = json_decode($datos, true);
|
|
}
|
|
}
|
|
|
|
return $vehiculos;
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
$vehiculo = $resultado['vehiculo'];
|
|
|
|
// Registrar en MySQL
|
|
Detection::create([
|
|
'arco_id' => $arcoId,
|
|
'fast_id' => $fastId,
|
|
'vin' => $vehiculo['vin'] ?? null,
|
|
'placa' => $vehiculo['placa'] ?? null,
|
|
'marca' => $vehiculo['marca'] ?? null,
|
|
'modelo' => $vehiculo['modelo'] ?? null,
|
|
'color' => $vehiculo['color'] ?? null,
|
|
'fecha_deteccion' => now()
|
|
]);
|
|
|
|
// Registrar en Redis (detecciones del día)
|
|
$this->registrarDeteccionDelDia($fastId, $vehiculo, $arcoId, $resultado);
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
private function registrarDeteccionDelDia(string $fastId, array $vehiculo, ?int $arcoId, array $resultado)
|
|
{
|
|
$fecha = now()->format('Y-m-d');
|
|
$timestamp = now()->timestamp;
|
|
$key = "deteccion:dia:{$fecha}:{$fastId}:{$timestamp}";
|
|
|
|
$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(),
|
|
];
|
|
|
|
// Guardar en Redis
|
|
Redis::set($key, json_encode($datosDeteccion));
|
|
|
|
// 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);
|
|
}
|
|
}
|