404 lines
14 KiB
PHP
404 lines
14 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Events\VehiculoRobadoDetectado;
|
|
use App\Models\AlertaRobo;
|
|
use App\Models\Detection;
|
|
use App\Models\DailyDetection;
|
|
use App\Models\Arco;
|
|
use Illuminate\Support\Facades\Redis;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class VehicleService
|
|
{
|
|
public function __construct(
|
|
private ConsultaRepuveConstancia $consultaRepuveCons,
|
|
private ReporteRoboService $reporteRoboService // Agregar esta dependencia
|
|
) {}
|
|
|
|
/**
|
|
* Procesar detección de vehículo por fast_id
|
|
*/
|
|
public function procesarDeteccion(string $fastId, int $arcoId, ?string $antena = null): array
|
|
{
|
|
$key = "vehiculo:robado:{$fastId}";
|
|
|
|
// 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), $arcoId, $antena);
|
|
$this->registrarDeteccion($fastId, $resultado, $arcoId, $antena);
|
|
return $resultado;
|
|
}
|
|
|
|
// No está en Redis, consultar servicios
|
|
$resultado = $this->consultarNuevoVehiculo($fastId);
|
|
$this->registrarDeteccion($fastId, $resultado, $arcoId, $antena);
|
|
return $resultado;
|
|
}
|
|
|
|
/**
|
|
* Consultar vehículo por tag_id, placa o VIN
|
|
*/
|
|
public function consultarVehiculoPorTag(string $fastId)
|
|
{
|
|
try {
|
|
//Intentar con REPUVE Constancia primero
|
|
$vehiculoExterno = $this->consultaRepuveCons->consultarVehiculoPorTag($fastId);
|
|
|
|
if ($vehiculoExterno) {
|
|
Log::info('VehicleService: Vehículo encontrado en REPUVE Constancia', [
|
|
'fast_id' => $fastId,
|
|
'tag_number' => $vehiculoExterno['tag_number'] ?? null,
|
|
'placa' => $vehiculoExterno['placa'] ?? null,
|
|
'vin' => $vehiculoExterno['vin'] ?? null
|
|
]);
|
|
return $vehiculoExterno;
|
|
}
|
|
|
|
// Si no se encuentra, intentar con REPUVE Nacional
|
|
Log::info('VehicleService: Intentando consulta en REPUVE Nacional', [
|
|
'fast_id' => $fastId
|
|
]);
|
|
|
|
$resultadoNacional = $this->reporteRoboService->consultarVehiculo($fastId);
|
|
|
|
if ($resultadoNacional['success'] && !empty($resultadoNacional['datos'])) {
|
|
Log::info('VehicleService: Vehículo encontrado en REPUVE Nacional', [
|
|
'fast_id' => $fastId,
|
|
'datos' => $resultadoNacional['datos']
|
|
]);
|
|
|
|
// Adaptar formato de REPUVE Nacional al formato esperado
|
|
$datos = $resultadoNacional['datos'];
|
|
return [
|
|
'tag_number' => $fastId,
|
|
'vin' => $datos['vin'] ?? null,
|
|
'placa' => $datos['placa'] ?? null,
|
|
'marca' => $datos['marca'] ?? null,
|
|
'modelo' => $datos['modelo'] ?? null,
|
|
'color' => $datos['color'] ?? null,
|
|
'origen' => 'REPUVE_NACIONAL'
|
|
];
|
|
}
|
|
|
|
Log::info('VehicleService: Vehículo no encontrado en ningún servicio', [
|
|
'fast_id' => $fastId
|
|
]);
|
|
return null;
|
|
} 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 detecciones del día desde MySQL
|
|
*/
|
|
public function listarDeteccionesDelDia(?string $fecha = null, ?int $arcoId = null, int $segundos = 10): array
|
|
{
|
|
$fecha = $fecha ?? now()->format('Y-m-d');
|
|
|
|
// Calcular timestamp hace N segundos
|
|
$tiempoLimite = now()->subSeconds($segundos);
|
|
|
|
$query = DailyDetection::delDia($fecha)
|
|
->where('fecha_deteccion', '>=', $tiempoLimite);
|
|
|
|
// Filtrar por arco si se especifica
|
|
if ($arcoId !== null) {
|
|
$query->porArco($arcoId);
|
|
}
|
|
|
|
$detecciones = $query
|
|
->orderBy('fecha_deteccion', 'desc')
|
|
->get()
|
|
->map(function ($deteccion) {
|
|
return [
|
|
'id' => $deteccion->id,
|
|
'fast_id' => $deteccion->fast_id,
|
|
'vin' => $deteccion->vin,
|
|
'placa' => $deteccion->placa,
|
|
'marca' => $deteccion->marca,
|
|
'modelo' => $deteccion->modelo,
|
|
'color' => $deteccion->color,
|
|
'arco_id' => $deteccion->arco_id,
|
|
'arco_nombre' => $deteccion->arco_nombre,
|
|
'antena' => $deteccion->antena,
|
|
'estado' => $deteccion->estado,
|
|
'tiene_reporte_robo' => $deteccion->tiene_reporte_robo,
|
|
'fecha_deteccion' => $deteccion->fecha_deteccion->toIso8601String(),
|
|
];
|
|
})
|
|
->toArray();
|
|
|
|
return $detecciones;
|
|
}
|
|
|
|
/**
|
|
* Listar detecciones del día de un arco específico
|
|
*/
|
|
public function listarDeteccionesDelDiaPorArco(int $arcoId, ?string $fecha = null): array
|
|
{
|
|
return $this->listarDeteccionesDelDia($fecha, $arcoId);
|
|
}
|
|
|
|
/**
|
|
* Obtener estadísticas de detecciones del día
|
|
*/
|
|
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
|
|
{
|
|
$datosVehiculo = $this->consultaRepuveCons->consultarVehiculoPorTag($fastId);
|
|
|
|
if ($datosVehiculo && isset($datosVehiculo['vin'])) {
|
|
Log::info('Vehículo encontrado en RepuveConstancia - LIBRE', [
|
|
'fast_id' => $fastId,
|
|
'vin' => $datosVehiculo['vin'],
|
|
'placa' => $datosVehiculo['placa'] ?? null,
|
|
'fuente' => 'RepuveConstancia'
|
|
]);
|
|
|
|
return [
|
|
'success' => true,
|
|
'tiene_reporte_robo' => false,
|
|
'estado' => 'LIBRE',
|
|
'vehiculo' => [
|
|
'vin' => $datosVehiculo['vin'] ?? null,
|
|
'placa' => $datosVehiculo['placa'] ?? null,
|
|
'marca' => $datosVehiculo['marca'] ?? null,
|
|
'modelo' => $datosVehiculo['modelo'] ?? null,
|
|
'color' => $datosVehiculo['color'] ?? null,
|
|
],
|
|
'fuente' => 'RepuveConstancia'
|
|
];
|
|
}
|
|
$resultadoNacional = $this->reporteRoboService->consultarVehiculo($fastId, null);
|
|
|
|
if ($resultadoNacional['success'] && !empty($resultadoNacional['datos'])) {
|
|
$datos = $resultadoNacional['datos'];
|
|
|
|
Log::info('Vehículo encontrado en RepuveNacional - LIBRE', [
|
|
'fast_id' => $fastId,
|
|
'vin' => $datos['vin'] ?? null,
|
|
'placa' => $datos['placa'] ?? null,
|
|
'fuente' => 'RepuveNacional'
|
|
]);
|
|
|
|
return [
|
|
'success' => true,
|
|
'tiene_reporte_robo' => false,
|
|
'estado' => 'LIBRE',
|
|
'vehiculo' => [
|
|
'vin' => $datos['vin'] ?? null,
|
|
'placa' => $datos['placa'] ?? null,
|
|
'marca' => $datos['marca'] ?? null,
|
|
'modelo' => $datos['modelo'] ?? null,
|
|
'color' => $datos['color'] ?? null,
|
|
],
|
|
'fuente' => 'RepuveNacional'
|
|
];
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'message' => 'No se encontró información del vehículo en ningún servicio',
|
|
'fuente' => 'ninguno'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Verificar vehículo robado (si ya está en Redis)
|
|
*/
|
|
private function verificarVehiculoRobado(string $fastId, array $datosRedis, ?int $arcoId = null, ?string $antena = null): array
|
|
{
|
|
// Actualizar contador de detecciones
|
|
$this->actualizarDeteccionRedis($fastId, $datosRedis);
|
|
|
|
Log::warning('¡VEHÍCULO ROBADO DETECTADO!', [
|
|
'fast_id' => $fastId,
|
|
'vin' => $datosRedis['vin'] ?? null,
|
|
'placa' => $datosRedis['placa'] ?? null
|
|
]);
|
|
|
|
// Crear alerta en la base de datos
|
|
$this->crearAlertaRobo($fastId, $datosRedis, $arcoId, $antena);
|
|
|
|
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, ?string $antena = null)
|
|
{
|
|
// Datos mínimos que siempre tenemos
|
|
$datosMinimos = [
|
|
'arco_id' => $arcoId,
|
|
'antena' => $antena,
|
|
'fast_id' => $fastId,
|
|
'fecha_deteccion' => now()
|
|
];
|
|
|
|
// Si encontramos el vehículo, agregamos datos completos
|
|
if ($resultado['success'] && isset($resultado['vehiculo'])) {
|
|
$vehiculo = $resultado['vehiculo'];
|
|
Detection::create(array_merge($datosMinimos, [
|
|
'vin' => $vehiculo['vin'] ?? null,
|
|
'placa' => $vehiculo['placa'] ?? null,
|
|
'marca' => $vehiculo['marca'] ?? null,
|
|
'modelo' => $vehiculo['modelo'] ?? null,
|
|
'color' => $vehiculo['color'] ?? null,
|
|
]));
|
|
|
|
// También registrar en Redis (detecciones del día)
|
|
$this->registrarDeteccionDelDia($fastId, $vehiculo, $arcoId, $resultado, $antena);
|
|
} else {
|
|
// No encontrado: guardar solo datos mínimos
|
|
Detection::create(array_merge($datosMinimos, [
|
|
'vin' => null,
|
|
'placa' => null,
|
|
'marca' => null,
|
|
'modelo' => null,
|
|
'color' => null,
|
|
]));
|
|
|
|
// Registrar en Redis con datos incompletos
|
|
$this->registrarDeteccionDelDia($fastId, [], $arcoId, [
|
|
'estado' => 'DESCONOCIDO',
|
|
'tiene_reporte_robo' => false
|
|
], $antena);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Registrar detección en MySQL para el día actual
|
|
*/
|
|
private function registrarDeteccionDelDia(string $fastId, array $vehiculo, ?int $arcoId, array $resultado, ?string $antena = null)
|
|
{
|
|
// Obtener nombre del arco
|
|
$arcoNombre = $arcoId ? Arco::find($arcoId)?->nombre : null;
|
|
|
|
// Crear la nueva detección
|
|
$nuevaDeteccion = DailyDetection::create([
|
|
'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,
|
|
'arco_nombre' => $arcoNombre,
|
|
'antena' => $antena,
|
|
'estado' => $resultado['estado'] ?? 'LIBRE',
|
|
'tiene_reporte_robo' => $resultado['tiene_reporte_robo'] ?? false,
|
|
'fecha_deteccion' => now(),
|
|
]);
|
|
|
|
Log::info('Detección del día registrada en MySQL', [
|
|
'id' => $nuevaDeteccion->id,
|
|
'fast_id' => $fastId,
|
|
'arco_id' => $arcoId,
|
|
'estado' => $nuevaDeteccion->estado
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Crear alerta de vehículo robado y disparar evento
|
|
*/
|
|
private function crearAlertaRobo(string $fastId, array $datosVehiculo, ?int $arcoId, ?string $antena): void
|
|
{
|
|
// Obtener nombre del arco
|
|
$arcoNombre = $arcoId ? Arco::find($arcoId)?->nombre : 'Desconocido';
|
|
|
|
// Crear alerta en la base de datos
|
|
$alerta = AlertaRobo::create([
|
|
'fast_id' => $fastId,
|
|
'vin' => $datosVehiculo['vin'] ?? null,
|
|
'placa' => $datosVehiculo['placa'] ?? null,
|
|
'marca' => $datosVehiculo['marca'] ?? null,
|
|
'modelo' => $datosVehiculo['modelo'] ?? null,
|
|
'color' => $datosVehiculo['color'] ?? null,
|
|
'arco_id' => $arcoId,
|
|
'arco_nombre' => $arcoNombre,
|
|
'antena' => $antena,
|
|
'fecha_deteccion' => now(),
|
|
'visto' => false,
|
|
]);
|
|
|
|
// Disparar evento para Laravel Reverb (WebSocket)
|
|
event(new VehiculoRobadoDetectado($alerta));
|
|
|
|
Log::info('Alerta de vehículo robado creada y evento disparado', [
|
|
'alerta_id' => $alerta->id,
|
|
'fast_id' => $fastId,
|
|
'placa' => $alerta->placa,
|
|
'arco' => $arcoNombre
|
|
]);
|
|
}
|
|
}
|