Correción servicio repuve, endpoint stolen

This commit is contained in:
Juan Felipe Zapata Moreno 2025-12-06 10:05:31 -06:00
parent baf3961036
commit 118f5ef868
5 changed files with 151 additions and 51 deletions

View File

@ -437,4 +437,48 @@ public function searchRecord(Request $request)
'records' => $paginatedRecords
]);
}
public function stolen(Request $request)
{
$request->validate([
'vin' => 'nullable|string|min:17|max:17',
'placa' => 'nullable|string',
], [
'vin.required_without' => 'Debe proporcionar al menos VIN o PLACA.',
'placa.required_without' => 'Debe proporcionar al menos VIN o PLACA.',
]);
// Validar que al menos uno esté presente
if (!$request->filled('vin') && !$request->filled('placa')) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Debe proporcionar al menos VIN o PLACA.',
]);
}
try {
$vin = $request->input('vin');
$placa = $request->input('placa');
// Verificar robo usando el servicio
$resultado = $this->repuveService->verificarRobo($vin, $placa);
$isStolen = $resultado['is_robado'] ?? false;
return ApiResponse::OK->response([
'vin' => $vin ?: null,
'placa' => $placa ?: null,
'robado' => $isStolen,
'estatus' => $isStolen ? 'REPORTADO COMO ROBADO' : 'SIN REPORTE DE ROBO',
'message' => $isStolen
? 'El vehículo tiene reporte de robo en REPUVE.'
: 'El vehículo no tiene reporte de robo.',
'fecha' => now()->toDateTimeString(),
'detalle_repuve' => $resultado,
]);
} catch (\Exception $e) {
return ApiResponse::INTERNAL_ERROR->response([
'message' => 'Error al consultar el estado de robo del vehículo.',
'error' => $e->getMessage(),
]);
}
}
}

View File

@ -164,15 +164,12 @@ private function parseVehicleResponse(string $soapResponse, string $niv)
];
}
/**
* Verifica si un vehículo está reportado como robado
*/
public function verificarRobo(string $niv): bool
public function verificarRobo(?string $niv = null, ?string $placa = null): array
{
try {
$url = $this->baseUrl . $this->roboEndpoint;
$arg2 = $niv . str_repeat('|', 8);
$arg2 = ($niv ?? '') . '|' . ($placa ?? '') . str_repeat('|', 7);
$soapBody = <<<XML
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://consultaRpv.org/wsdl">
@ -202,45 +199,61 @@ public function verificarRobo(string $niv): bool
$error = curl_error($ch);
curl_close($ch);
// Si hay error de conexión, asumir que NO está robado
// Si hay error de conexión, retornar error
if ($error) {
logger()->error('REPUVE verificarRobo: Error de conexión', [
'error' => $error,
'niv' => $niv,
'placa' => $placa,
]);
return false;
return [
'is_robado' => false,
'has_error' => true,
'error_message' => 'Error de conexión con el servicio REPUVE',
];
}
// Si hay error HTTP, asumir que NO está robado
// Si hay error HTTP, retornar error
if ($httpCode !== 200) {
logger()->error('REPUVE verificarRobo: HTTP error', [
'http_code' => $httpCode,
'niv' => $niv,
'placa' => $placa,
]);
return false;
return [
'is_robado' => false,
'has_error' => true,
'error_message' => "Error HTTP {$httpCode} del servicio REPUVE",
];
}
// Parsear respuesta
$resultado = $this->parseRoboResponse($response, $niv);
$valorBuscado = $niv ?: $placa ?: 'N/A';
$resultado = $this->parseRoboResponse($response, $valorBuscado);
// Si hubo error al parsear, asumir que NO está robado
if ($resultado['has_error'] ?? true) {
// Si hubo error al parsear, loguear pero retornar el resultado completo
if ($resultado['has_error'] ?? false) {
logger()->warning('REPUVE verificarRobo: Error al parsear respuesta', [
'niv' => $niv,
'placa' => $placa,
'error' => $resultado['error_message'] ?? 'Desconocido',
]);
return false;
}
// Retornar si está robado o no
return $resultado['is_robado'] ?? false;
// Retornar el array completo con toda la información
return $resultado;
} catch (Exception $e) {
logger()->error('REPUVE verificarRobo: Excepción capturada', [
'niv' => $niv,
'placa' => $placa,
'exception' => $e->getMessage(),
]);
return false;
return [
'is_robado' => false,
'has_error' => true,
'error_message' => 'Excepción capturada: ' . $e->getMessage(),
];
}
}

View File

@ -12,7 +12,20 @@
*/
public function up()
{
// 1. Agregar columnas necesarias a packages (si no existen)
Schema::table('packages', function (Blueprint $table) {
if (!Schema::hasColumn('packages', 'box_number')) {
$table->integer('box_number')->after('lot');
}
if (!Schema::hasColumn('packages', 'starting_page')) {
$table->integer('starting_page')->after('box_number');
}
if (!Schema::hasColumn('packages', 'ending_page')) {
$table->integer('ending_page')->after('starting_page');
}
});
// 2. Migrar datos de boxes a packages
DB::table('boxes')->orderBy('id')->chunk(100, function($boxes) {
foreach ($boxes as $box) {
$parentPackage = DB::table('packages')->find($box->package_id);
@ -33,7 +46,14 @@ public function up()
}
});
// 3. Agregar constraint único después de migrar datos (si no existe)
if (!$this->constraintExists('packages', 'packages_lot_box_unique')) {
Schema::table('packages', function (Blueprint $table) {
$table->unique(['lot', 'box_number'], 'packages_lot_box_unique');
});
}
// 4. Actualizar referencias en tags
Schema::table('tags', function (Blueprint $table) {
$table->dropForeign(['box_id']);
});
@ -46,7 +66,7 @@ public function up()
$table->foreign('package_id')->references('id')->on('packages')->onDelete('cascade');
});
// eliminar tabla boxes
// 5. Eliminar tabla boxes
Schema::dropIfExists('boxes');
// 6. Eliminar columnas de packages que ya no se usan
@ -60,11 +80,66 @@ public function up()
});
}
/**
* Verificar si existe un constraint/índice
*/
private function constraintExists(string $table, string $name): bool
{
$indexes = DB::select("SHOW INDEX FROM {$table}");
foreach ($indexes as $index) {
if ($index->Key_name === $name) {
return true;
}
}
return false;
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
// Revertir cambios en orden inverso
// 1. Restaurar columnas de packages
Schema::table('packages', function (Blueprint $table) {
$table->integer('total_boxes')->nullable();
$table->text('description')->nullable();
});
// 2. Recrear tabla boxes
Schema::create('boxes', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('package_id');
$table->string('box_number');
$table->integer('starting_page');
$table->integer('ending_page');
$table->timestamps();
$table->foreign('package_id')->references('id')->on('packages')->onDelete('cascade');
});
// 3. Revertir columna package_id a box_id en tags
Schema::table('tags', function (Blueprint $table) {
$table->dropForeign(['package_id']);
});
Schema::table('tags', function (Blueprint $table) {
$table->renameColumn('package_id', 'box_id');
});
Schema::table('tags', function (Blueprint $table) {
$table->foreign('box_id')->references('id')->on('boxes')->onDelete('cascade');
});
// 4. Eliminar constraint único de packages
Schema::table('packages', function (Blueprint $table) {
$table->dropUnique('packages_lot_box_unique');
});
// 5. Eliminar columnas agregadas a packages
Schema::table('packages', function (Blueprint $table) {
$table->dropColumn(['box_number', 'starting_page', 'ending_page']);
});
}
};

View File

@ -1,32 +0,0 @@
<?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::table('packages', function (Blueprint $table) {
$table->integer('box_number')->after('lot');
$table->integer('starting_page')->after('box_number');
$table->integer('ending_page')->after('starting_page');
$table->unique(['lot', 'box_number'], 'packages_lot_box_unique');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('packages', function (Blueprint $table) {
$table->dropUnique('packages_lot_box_unique');
$table->dropColumn(['box_number', 'starting_page', 'ending_page']);
});
}
};

View File

@ -34,7 +34,7 @@
// Rutas de inscripción de vehículos
Route::post('inscripcion', [InscriptionController::class, 'vehicleInscription']);
Route::get('consultaV', [InscriptionController::class, 'searchRecord']);
Route::post('stolen', [InscriptionController::class, 'stolen']);
Route::post('reporte-robado', [InscriptionController::class, 'stolen']);
// Rutas de expedientes y documentos
Route::get('expediente/{id}/pdf', [RecordController::class, 'generatePdf']);