fix: pasar redis a mysql

This commit is contained in:
Juan Felipe Zapata Moreno 2026-01-10 10:31:27 -06:00
parent 1b4eba2c6c
commit 1d53c00cfb
5 changed files with 157 additions and 52 deletions

View File

@ -0,0 +1,53 @@
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class DailyDetection extends Model
{
public $timestamps = false;
protected $fillable = [
'arco_id',
'arco_nombre',
'antena',
'fast_id',
'vin',
'placa',
'marca',
'modelo',
'color',
'estado',
'tiene_reporte_robo',
'fecha_deteccion'
];
protected $casts = [
'fecha_deteccion' => 'datetime:Y-m-d H:i:s',
'tiene_reporte_robo' => 'boolean',
];
/**
* Relación con el modelo Arco
*/
public function arco()
{
return $this->belongsTo(Arco::class, 'arco_id');
}
/**
* Scope para filtrar por fecha del día
*/
public function scopeDelDia($query, ?string $fecha = null)
{
$fecha = $fecha ?? now()->format('Y-m-d');
return $query->whereDate('fecha_deteccion', $fecha);
}
/**
* Scope para filtrar por arco
*/
public function scopePorArco($query, int $arcoId)
{
return $query->where('arco_id', $arcoId);
}
}

View File

@ -5,6 +5,7 @@
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;
@ -117,30 +118,54 @@ public function listarVehiculosRobados(): array
}
/**
* Listar todas las detecciones del día desde Redis
* Listar detecciones del día desde MySQL
* Muestra solo los últimos 10 registros por arco
*/
public function listarDeteccionesDelDia(?string $fecha = null): array
public function listarDeteccionesDelDia(?string $fecha = null, ?int $arcoId = null, int $limit = 10): 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);
}
$query = DailyDetection::delDia($fecha);
// Filtrar por arco si se especifica
if ($arcoId !== null) {
$query->porArco($arcoId);
}
// Ordenar por fecha de detección (más reciente primero)
usort($detecciones, function ($a, $b) {
return strcmp($b['fecha_deteccion'], $a['fecha_deteccion']);
});
$detecciones = $query
->orderBy('fecha_deteccion', 'desc')
->limit($limit)
->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
*/
@ -161,22 +186,6 @@ public function obtenerEstadisticasDelDia(?string $fecha = null): array
];
}
/**
* Listar detecciones del día de un arco específico
*/
public function listarDeteccionesDelDiaPorArco(int $arcoId, ?string $fecha = null): array
{
$todasDetecciones = $this->listarDeteccionesDelDia($fecha);
// Filtrar solo las detecciones de este arco
$deteccionesArco = collect($todasDetecciones)
->where('arco_id', $arcoId)
->values()
->all();
return $deteccionesArco;
}
/**
* Consultar nuevo vehículo (no está en Redis de robados)
*/
@ -325,20 +334,15 @@ private function registrarDeteccion(string $fastId, array $resultado, ?int $arco
}
/**
* 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
* Registrar detección en MySQL para el día actual
*/
private function registrarDeteccionDelDia(string $fastId, array $vehiculo, ?int $arcoId, array $resultado, ?string $antena = null)
{
$fecha = now()->format('Y-m-d');
$timestamp = now()->timestamp;
$key = "deteccion:dia:{$fecha}:{$fastId}:{$timestamp}";
// Obtener nombre del arco
$arcoNombre = $arcoId ? Arco::find($arcoId)?->nombre : null;
$datosDeteccion = [
// Crear la nueva detección
$nuevaDeteccion = DailyDetection::create([
'fast_id' => $fastId,
'vin' => $vehiculo['vin'] ?? null,
'placa' => $vehiculo['placa'] ?? null,
@ -350,18 +354,15 @@ private function registrarDeteccionDelDia(string $fastId, array $vehiculo, ?int
'antena' => $antena,
'estado' => $resultado['estado'] ?? 'LIBRE',
'tiene_reporte_robo' => $resultado['tiene_reporte_robo'] ?? false,
'fecha_deteccion' => now()->toIso8601String(),
];
'fecha_deteccion' => now(),
]);
// 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);
Log::info('Detección del día registrada en MySQL', [
'id' => $nuevaDeteccion->id,
'fast_id' => $fastId,
'arco_id' => $arcoId,
'estado' => $nuevaDeteccion->estado
]);
}
/**

View File

@ -0,0 +1,53 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('daily_detections', function (Blueprint $table) {
$table->id();
// Información del arco y antena
$table->foreignId('arco_id')->nullable()->constrained('arcos')->onDelete('cascade');
$table->string('arco_nombre')->nullable();
$table->string('antena')->nullable();
// Datos del vehículo detectado
$table->string('fast_id');
$table->string('vin')->nullable();
$table->string('placa')->nullable();
$table->string('marca')->nullable();
$table->string('modelo')->nullable();
$table->string('color')->nullable();
// Estado de la detección
$table->enum('estado', ['LIBRE', 'ROBADO', 'DESCONOCIDO'])->default('DESCONOCIDO');
$table->boolean('tiene_reporte_robo')->default(false);
// Fecha de la detección
$table->timestamp('fecha_deteccion')->useCurrent();
$table->date('fecha_dia')->storedAs('DATE(fecha_deteccion)');
// Índices para optimizar consultas
$table->index('arco_id');
$table->index('fecha_dia');
$table->index(['arco_id', 'fecha_dia']);
$table->index('fast_id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('daily_detections');
}
};

View File

@ -13,8 +13,6 @@ services:
- DB_PASSWORD=${DB_PASSWORD}
- DB_DATABASE=${DB_DATABASE}
- DB_PORT=${DB_PORT}
ports:
- "8080:8080"
volumes:
- ./:/var/www/arcos-backend
- ./vendor:/var/www/arcos/vendor

2
package-lock.json generated
View File

@ -1,5 +1,5 @@
{
"name": "holos.backend",
"name": "arcos-backend",
"lockfileVersion": 3,
"requires": true,
"packages": {