add: colas y correción de detección
This commit is contained in:
parent
c2171c1247
commit
0487421758
@ -194,7 +194,7 @@ public function deteccionesDelDia(Request $request, int $id)
|
||||
// Filtrar solo VIN, placa, antena y si es robado
|
||||
$deteccionesFiltradas = array_map(function($deteccion) {
|
||||
return [
|
||||
'vin' => $deteccion['fast_id'] ?? null,
|
||||
'vin' => $deteccion['vin'] ?? null,
|
||||
'placa' => $deteccion['placa'] ?? null,
|
||||
'antena' => $deteccion['antena'] ?? null,
|
||||
'robado' => $deteccion['tiene_reporte_robo'] ?? false,
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\ProcesarDeteccionVehiculo;
|
||||
use App\Models\Vehicle;
|
||||
use App\Models\Detection;
|
||||
use App\Services\VehicleService;
|
||||
@ -396,22 +397,20 @@ public function buscarPorTag(Request $request)
|
||||
// Obtener el arco autenticado del middleware
|
||||
$arco = $request->get('arco_autenticado');
|
||||
|
||||
$resultado = $this->vehicleService->procesarDeteccion(
|
||||
$validated['fast_id'],
|
||||
$arco->ip_address,
|
||||
$validated['antena'] ?? null
|
||||
);
|
||||
|
||||
if (!$resultado['success']) {
|
||||
return ApiResponse::OK->response([
|
||||
'success' => false,
|
||||
'message' => 'Error, NO se encontró el vehiculo'
|
||||
]);
|
||||
}
|
||||
ProcesarDeteccionVehiculo::dispatch(
|
||||
$validated['fast_id'],
|
||||
$arco->id,
|
||||
$validated['antena'] ?? null
|
||||
);
|
||||
|
||||
return ApiResponse::OK->response([
|
||||
'success' => true,
|
||||
'message' => 'Vehiculo registrado exitosamente'
|
||||
'message' => 'Detección recibida y en proceso',
|
||||
'fast_id' => $validated['fast_id'],
|
||||
'arco' => [
|
||||
'id' => $arco->id,
|
||||
'nombre' => $arco->nombre
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,25 +38,6 @@ public function handle(Request $request, Closure $next): Response
|
||||
]);
|
||||
}
|
||||
|
||||
// Validación de IP deshabilitada para desarrollo
|
||||
// PROBLEMA: En Docker, $request->ip() retorna la IP del gateway (172.x.x.x), no la IP real del cliente
|
||||
// SOLUCIÓN PRODUCCIÓN: Usar un proxy inverso externo (nginx/traefik) que pase X-Forwarded-For correctamente
|
||||
// Para desarrollo, la validación de token es suficiente
|
||||
/*
|
||||
$requestIp = $request->ip();
|
||||
if ($arco->ip_address !== $requestIp) {
|
||||
return ApiResponse::FORBIDDEN->response([
|
||||
'message' => 'Token no autorizado para esta IP',
|
||||
'detail' => [
|
||||
'ip_registrada_arco' => $arco->ip_address,
|
||||
'ip_del_request' => $requestIp,
|
||||
'arco_nombre' => $arco->nombre
|
||||
]
|
||||
]);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
// Agregar el arco al request para uso posterior
|
||||
$request->merge(['arco_autenticado' => $arco]);
|
||||
|
||||
|
||||
70
app/Jobs/ProcesarDeteccionVehiculo.php
Normal file
70
app/Jobs/ProcesarDeteccionVehiculo.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php namespace App\Jobs;
|
||||
|
||||
use App\Services\VehicleService;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ProcesarDeteccionVehiculo implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Número de intentos antes de marcar como fallido
|
||||
*/
|
||||
public $tries = 3;
|
||||
|
||||
/**
|
||||
* Timeout en segundos (2 minutos)
|
||||
*/
|
||||
public $timeout = 120;
|
||||
|
||||
/**
|
||||
* Tiempo entre reintentos en segundos
|
||||
*/
|
||||
public $backoff = 10;
|
||||
|
||||
/**
|
||||
* Constructor del Job
|
||||
*/
|
||||
public function __construct(
|
||||
public string $fastId,
|
||||
public int $arcoId,
|
||||
public ?string $antena = null
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Ejecutar el job
|
||||
*/
|
||||
public function handle(VehicleService $vehicleService): void
|
||||
{
|
||||
try {
|
||||
// Procesar la detección usando el servicio
|
||||
$vehicleService->procesarDeteccion(
|
||||
$this->fastId,
|
||||
$this->arcoId,
|
||||
$this->antena
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
// Re-lanzar la excepción para que Laravel reintente el job
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manejar fallo del job después de todos los reintentos
|
||||
*/
|
||||
public function failed(\Throwable $exception): void
|
||||
{
|
||||
Log::error('ProcesarDeteccionVehiculo: FALLIDO después de todos los intentos', [
|
||||
'fast_id' => $this->fastId,
|
||||
'arco_id' => $this->arcoId,
|
||||
'antena' => $this->antena,
|
||||
'error' => $exception->getMessage(),
|
||||
'intentos_realizados' => $this->tries
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -179,4 +179,192 @@ private function parseRoboResponse(string $soapResponse, string $valor)
|
||||
'error' => 'Formato de respuesta no reconocido'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Consultar datos del vehículo (sin reporte de robo)
|
||||
*/
|
||||
public function consultarVehiculo(?string $niv = null, ?string $placa = null): array
|
||||
{
|
||||
try {
|
||||
if (empty($niv) && empty($placa)) {
|
||||
Log::warning('ReporteRoboService: consultarVehiculo sin NIV ni PLACA');
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => true,
|
||||
'error_message' => 'Debe proporcionar al menos NIV o PLACA',
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
|
||||
$url = $this->baseUrl . '/jaxws-consultarpv/ConsultaRpv';
|
||||
|
||||
// Construir arg2
|
||||
if ($placa) {
|
||||
$arg2 = ($niv ?? '') . '|' . $placa . str_repeat('|', 5);
|
||||
} else {
|
||||
$arg2 = ($niv ?? '') . str_repeat('|', 7);
|
||||
}
|
||||
|
||||
$soapBody = <<<XML
|
||||
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://consultaRpv.org/wsdl">
|
||||
<soapenv:Header/>
|
||||
<soapenv:Body>
|
||||
<wsdl:doConsRPV>
|
||||
<arg0>{$this->username}</arg0>
|
||||
<arg1>{$this->password}</arg1>
|
||||
<arg2>{$arg2}</arg2>
|
||||
</wsdl:doConsRPV>
|
||||
</soapenv:Body>
|
||||
</soapenv:Envelope>
|
||||
XML;
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $soapBody);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: text/xml; charset=utf-8',
|
||||
'SOAPAction: "doConsRPV"',
|
||||
'Content-Length: ' . strlen($soapBody),
|
||||
]);
|
||||
|
||||
try {
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$error = curl_error($ch);
|
||||
|
||||
if ($error) {
|
||||
Log::error('ReporteRoboService: consultarVehiculo - Error de conexión', [
|
||||
'error' => $error,
|
||||
'niv' => $niv,
|
||||
'placa' => $placa
|
||||
]);
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => true,
|
||||
'error_message' => 'Error de conexión',
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
|
||||
if ($httpCode !== 200) {
|
||||
Log::error('ReporteRoboService: consultarVehiculo - HTTP error', [
|
||||
'http_code' => $httpCode,
|
||||
'niv' => $niv,
|
||||
'placa' => $placa
|
||||
]);
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => true,
|
||||
'error_message' => "Error HTTP {$httpCode}",
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
|
||||
return $this->parseConsultaVehiculoResponse($response);
|
||||
|
||||
} finally {
|
||||
unset($ch);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::error('ReporteRoboService: consultarVehiculo - Excepción', [
|
||||
'niv' => $niv,
|
||||
'placa' => $placa,
|
||||
'exception' => $e->getMessage()
|
||||
]);
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => true,
|
||||
'error_message' => $e->getMessage(),
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parsear respuesta de consulta de vehículo
|
||||
* Extrae solo: VIN, placa, marca, modelo y color
|
||||
*/
|
||||
private function parseConsultaVehiculoResponse(string $soapResponse): array
|
||||
{
|
||||
// Extraer contenido del tag <return>
|
||||
preg_match('/<return>(.*?)<\/return>/s', $soapResponse, $matches);
|
||||
|
||||
if (!isset($matches[1])) {
|
||||
Log::error('ReporteRoboService: parseConsultaVehiculoResponse - Respuesta inválida');
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => true,
|
||||
'error_message' => 'Respuesta inválida del servicio',
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
|
||||
$contenido = trim($matches[1]);
|
||||
|
||||
// Verificar si hay error
|
||||
if (preg_match('/(ERR|ERROR):(-?\d+)/i', $contenido, $errorMatch)) {
|
||||
$errorCode = $errorMatch[2];
|
||||
Log::warning('ReporteRoboService: parseConsultaVehiculoResponse - Error del servicio', [
|
||||
'error_code' => $errorCode
|
||||
]);
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => true,
|
||||
'error_message' => "Error REPUVE código {$errorCode}",
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
|
||||
// Si empieza con OK:, parsear los datos
|
||||
if (str_starts_with($contenido, 'OK:')) {
|
||||
$datos = str_replace('OK:', '', $contenido);
|
||||
$valores = explode('|', $datos);
|
||||
|
||||
// Estructura esperada del REPUVE Nacional
|
||||
// Posiciones aproximadas basadas en el servicio
|
||||
$datosVehiculo = [
|
||||
'vin' => $valores[0] ?? null,
|
||||
'placa' => $valores[1] ?? null,
|
||||
'marca' => $valores[2] ?? null,
|
||||
'modelo' => $valores[3] ?? null,
|
||||
'color' => $valores[4] ?? null,
|
||||
];
|
||||
|
||||
// Filtrar valores vacíos
|
||||
$datosVehiculo = array_filter($datosVehiculo, fn($v) => !empty($v));
|
||||
|
||||
if (empty($datosVehiculo)) {
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => false,
|
||||
'error_message' => 'No se encontró información del vehículo',
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
|
||||
Log::info('ReporteRoboService: Vehículo encontrado en REPUVE Nacional', [
|
||||
'vin' => $datosVehiculo['vin'] ?? null,
|
||||
'placa' => $datosVehiculo['placa'] ?? null
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'has_error' => false,
|
||||
'datos' => $datosVehiculo
|
||||
];
|
||||
}
|
||||
|
||||
Log::error('ReporteRoboService: parseConsultaVehiculoResponse - Formato no reconocido', [
|
||||
'contenido' => $contenido
|
||||
]);
|
||||
return [
|
||||
'success' => false,
|
||||
'has_error' => true,
|
||||
'error_message' => 'Formato de respuesta no reconocido',
|
||||
'datos' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,20 +11,17 @@
|
||||
class VehicleService
|
||||
{
|
||||
public function __construct(
|
||||
private ConsultaRepuveConstancia $consultaRepuveCons
|
||||
private ConsultaRepuveConstancia $consultaRepuveCons,
|
||||
private ReporteRoboService $reporteRoboService // Agregar esta dependencia
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Procesar detección de vehículo por fast_id
|
||||
*/
|
||||
public function procesarDeteccion(string $fastId, string $arcoIp, ?string $antena = null): array
|
||||
public function procesarDeteccion(string $fastId, int $arcoId, ?string $antena = null): 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);
|
||||
|
||||
@ -47,22 +44,49 @@ public function procesarDeteccion(string $fastId, string $arcoIp, ?string $anten
|
||||
public function consultarVehiculoPorTag(string $fastId)
|
||||
{
|
||||
try {
|
||||
//Intentar con REPUVE Constancia primero
|
||||
$vehiculoExterno = $this->consultaRepuveCons->consultarVehiculoPorTag($fastId);
|
||||
|
||||
if ($vehiculoExterno) {
|
||||
Log::info('VehicleService: Vehículo encontrado', [
|
||||
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
|
||||
]);
|
||||
} else {
|
||||
Log::info('VehicleService: Vehículo no encontrado', [
|
||||
'fast_id' => $fastId
|
||||
]);
|
||||
return $vehiculoExterno;
|
||||
}
|
||||
|
||||
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', [
|
||||
@ -162,31 +186,61 @@ public function listarDeteccionesDelDiaPorArco(int $arcoId, ?string $fecha = nul
|
||||
*/
|
||||
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
|
||||
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' => false,
|
||||
'message' => 'No se encontró información del vehículo.'
|
||||
'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'
|
||||
];
|
||||
}
|
||||
|
||||
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
|
||||
'success' => false,
|
||||
'message' => 'No se encontró información del vehículo en ningún servicio',
|
||||
'fuente' => 'ninguno'
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ services:
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||
MYSQL_USER: ${DB_USERNAME}
|
||||
ports:
|
||||
- ${DB_PORT}:${DB_PORT}
|
||||
- ${DB_PORT}:3306
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
networks:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user