2025-10-21 17:23:54 -06:00

461 lines
17 KiB
PHP

<?php
namespace App\Http\Controllers\Repuve;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Notsoweb\ApiResponse\Enums\ApiResponse;
use App\Http\Requests\Repuve\VehicleStoreRequest;
use App\Http\Requests\Repuve\VehicleUpdateRequest;
use App\Models\Vehicle;
use App\Models\Record;
use App\Models\Owner;
use App\Models\File;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class RepuveController extends Controller
{
/* ===========================================================
* Inscripción de vehículo al REPUVE
* ===========================================================
*/
public function inscripcionVehiculo(VehicleStoreRequest $request)
{
try {
// Validar folio
$folio = $request->input('folio');
// Simular consulta de robo
$isStolen = $this->checkIfStolen($folio);
// Si está robado, detener el flujo
if ($isStolen) {
return ApiResponse::FORBIDDEN->response([
'folio' => $folio,
'stolen' => true,
'message' => 'El vehículo reporta robo. No se puede continuar con la inscripción.',
]);
}
// Iniciar transacción
DB::beginTransaction();
// Obtener datos del vehículo y propietario
$vehicleData = $this->getVehicle();
$ownerData = $this->getOwner();
//Crear propietario
$owner = Owner::updateOrCreate(
['rfc' => $ownerData['rfc']],
[
'name' => $ownerData['name'],
'paternal' => $ownerData['paternal'],
'maternal' => $ownerData['maternal'],
'curp' => $ownerData['curp'],
'address' => $ownerData['address'],
]
);
//Crear o actualizar vehículo
$vehicle = Vehicle::updateOrCreate(
['placa' => $vehicleData['PLACA']],
[
'anio_placa' => $vehicleData['ANIO_PLACA'],
'placa' => $vehicleData['PLACA'],
'numero_serie' => $vehicleData['NO_SERIE'],
'rfc' => $vehicleData['RFC'],
'folio' => $vehicleData['FOLIO'],
'vigencia' => $vehicleData['VIGENCIA'],
'fecha_impresion' => $vehicleData['FECHA_IMPRESION'],
'qr_hash' => $vehicleData['QR_HASH'],
'valido' => $vehicleData['VALIDO'],
'foliotemp' => $vehicleData['FOLIOTEMP'],
'nombre' => $vehicleData['NOMBRE'],
'nombre2' => $vehicleData['NOMBRE2'],
'municipio' => $vehicleData['MUNICIPIO'],
'localidad' => $vehicleData['LOCALIDAD'],
'calle' => $vehicleData['CALLE'],
'calle2' => $vehicleData['CALLE2'],
'tipo' => $vehicleData['TIPO'],
'tipo_servicio' => $vehicleData['TIPO_SERVICIO'],
'marca' => $vehicleData['MARCA'],
'linea' => $vehicleData['LINEA'],
'sublinea' => $vehicleData['SUBLINEA'],
'modelo' => $vehicleData['MODELO'],
'numero_motor' => $vehicleData['NUMERO_MOTOR'],
'descripcion_origen' => $vehicleData['DESCRIPCION_ORIGEN'],
'color' => $vehicleData['COLOR'],
'codigo_postal' => $vehicleData['CODIGO_POSTAL'],
'serie_folio' => $vehicleData['SERIE_FOLIO'],
'sfolio' => $vehicleData['SFOLIO'],
'nrpv' => $vehicleData['NUMERO_SERIE'],
'owner_id' => $owner->id,
]
);
//Crear registro (expediente)
$record = Record::create([
'folio' => $folio,
'vehicle_id' => $vehicle->id,
'user_id' => auth()->id(),
]);
//Procesar y guardar archivos si existen
$uploadedFiles = [];
if ($request->hasFile('files')) {
$files = $request->file('files');
$fileNames = $request->input('names', []);
foreach ($files as $index => $file) {
// Generar nombre único
$fileName = uniqid() . '_' . time() . '_' . $file->getClientOriginalName();
// Guardar archivos
$path = $file->storeAs('records', $fileName, 'public');
// Calcular MD5
$md5 = md5_file($file->getRealPath());
// Crear registro en BD
$fileRecord = File::create([
'name' => $fileNames[$index] ?? "Archivo " . ($index + 1),
'path' => $path,
'md5' => $md5,
'record_id' => $record->id,
]);
$uploadedFiles[] = [
'id' => $fileRecord->id,
'name' => $fileRecord->name,
'path' => $fileRecord->path,
'url' => $fileRecord->url,
];
}
}
// Confirmar transacción
DB::commit();
// Responder con éxito
return ApiResponse::OK->response([
'folio' => $folio,
'stolen' => false,
'message' => 'Vehículo inscrito exitosamente',
'record' => [
'id' => $record->id,
'folio' => $record->folio,
'vehicle_id' => $vehicle->id,
'user_id' => $record->user_id,
'created_at' => $record->created_at->toDateTimeString(),
],
'vehicle' => [
'id' => $vehicle->id,
'placa' => $vehicle->placa,
'numero_serie' => $vehicle->numero_serie,
'marca' => $vehicle->marca,
'modelo' => $vehicle->modelo,
'color' => $vehicle->color,
],
'owner' => [
'id' => $owner->id,
'full_name' => $owner->full_name,
'rfc' => $owner->rfc,
],
'files' => $uploadedFiles,
'total_files' => count($uploadedFiles),
]);
} catch (\Exception $e) {
// Revertir transacción en caso de error
DB::rollBack();
// Log del error
Log::error('Error en inscripcionVehiculo: ' . $e->getMessage(), [
'folio' => $folio ?? null,
'trace' => $e->getTraceAsString()
]);
return ApiResponse::BAD_REQUEST->response([
'message' => 'Error al procesar la inscripción del vehículo',
'error' => $e->getMessage(),
]);
}
}
private function checkIfStolen(string $folio): bool
{
// Aquí api servicio de REPUVE
// simulamos con random
return (bool) rand(0, 1);
}
public function consultaExpediente(Request $request)
{
$request->validate([
'folio' => 'nullable|string',
'placa' => 'nullable|string',
'niv' => 'nullable|string',
], [
'required_without_all' => 'Debe proporcionar al menos uno de los siguientes: folio, placa o NIV.'
]);
if (!$request->filled('folio') && !$request->filled('placa') && !$request->filled('niv')) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'Debe proporcionar al menos uno de los siguientes parámetros: folio, placa o niv.'
]);
}
$query = Record::with(['vehicle.owner', 'vehicle.tag', 'files', 'user']);
if ($request->filled('folio')) {
$query->where('folio', $request->input('folio'));
} elseif ($request->filled('placa')) {
$query->whereHas('vehicle', function ($q) use ($request) {
$q->where('placa', $request->input('placa'));
});
} elseif ($request->filled('niv')) {
$query->whereHas('vehicle', function ($q) use ($request) {
$q->where('numero_serie', $request->input('niv'));
});
}
$record = $query->first();
if (!$record) {
return ApiResponse::NOT_FOUND->response([
'message' => 'No se encontró ningún expediente con el folio proporcionado.'
]);
}
return ApiResponse::OK->response([
'record' => [
'id' => $record->id,
'folio' => $record->folio,
'vehicle' => $record->vehicle,
'owner' => $record->vehicle->owner,
'tag' => $record->vehicle->tag,
'files' => $record->files,
'user' => $record->user,
'created_at' => $record->created_at->toDateTimeString(),
]
]);
}
public function actualizarVehiculo(VehicleUpdateRequest $request, $recordId)
{
try {
// Buscar el registro existente
$record = Record::with(['vehicle.owner'])->findOrFail($recordId);
// Iniciar transacción
DB::beginTransaction();
$vehicleData = $this->getVehicle2();
$ownerData = $this->getOwner();
// Actualizar propietario
$owner = Owner::updateOrCreate(
['rfc' => $ownerData['rfc']],
[
'name' => $ownerData['name'],
'paternal' => $ownerData['paternal'],
'maternal' => $ownerData['maternal'],
'curp' => $ownerData['curp'],
'address' => $ownerData['address'],
]
);
// Actualizar vehículo
$record->vehicle->update([
'anio_placa' => $vehicleData['ANIO_PLACA'],
'placa' => $vehicleData['PLACA'],
'numero_serie' => $vehicleData['NO_SERIE'],
'rfc' => $vehicleData['RFC'],
'folio' => $vehicleData['FOLIO'],
'vigencia' => $vehicleData['VIGENCIA'],
'fecha_impresion' => $vehicleData['FECHA_IMPRESION'],
'qr_hash' => $vehicleData['QR_HASH'],
'valido' => $vehicleData['VALIDO'],
'foliotemp' => $vehicleData['FOLIOTEMP'],
'nombre' => $vehicleData['NOMBRE'],
'nombre2' => $vehicleData['NOMBRE2'],
'municipio' => $vehicleData['MUNICIPIO'],
'localidad' => $vehicleData['LOCALIDAD'],
'calle' => $vehicleData['CALLE'],
'calle2' => $vehicleData['CALLE2'],
'tipo' => $vehicleData['TIPO'],
'tipo_servicio' => $vehicleData['TIPO_SERVICIO'],
'marca' => $vehicleData['MARCA'],
'linea' => $vehicleData['LINEA'],
'sublinea' => $vehicleData['SUBLINEA'],
'modelo' => $vehicleData['MODELO'],
'numero_motor' => $vehicleData['NUMERO_MOTOR'],
'descripcion_origen' => $vehicleData['DESCRIPCION_ORIGEN'],
'color' => $vehicleData['COLOR'],
'codigo_postal' => $vehicleData['CODIGO_POSTAL'],
'serie_folio' => $vehicleData['SERIE_FOLIO'],
'sfolio' => $vehicleData['SFOLIO'],
'nrpv' => $vehicleData['NUMERO_SERIE'],
'owner_id' => $owner->id,
]);
// Procesar nuevos archivos si existen
$uploadedFiles = [];
if ($request->hasFile('files')) {
$files = $request->file('files');
$fileNames = $request->input('names', []);
foreach ($files as $index => $file) {
// Generar nombre
$fileName = uniqid() . '_' . time() . '_' . $file->getClientOriginalName();
// Guardar archivos
$path = $file->storeAs('records', $fileName, 'public');
// Calcular MD5
$md5 = md5_file($file->getRealPath());
// Crear registro en BD
$fileRecord = File::create([
'name' => $fileNames[$index] ?? "Archivo " . ($index + 1),
'path' => $path,
'md5' => $md5,
'record_id' => $record->id,
]);
$uploadedFiles[] = [
'id' => $fileRecord->id,
'name' => $fileRecord->name,
'path' => $fileRecord->path,
'url' => $fileRecord->url,
];
}
}
// Confirmar transacción
DB::commit();
// Responder con éxito
return ApiResponse::OK->response([
'message' => 'Vehículo actualizado exitosamente',
'record' => [
'id' => $record->id,
'folio' => $record->folio,
'vehicle_id' => $record->vehicle->id,
'updated_at' => $record->updated_at->toDateTimeString(),
],
'vehicle' => [
'id' => $record->vehicle->id,
'placa' => $record->vehicle->placa,
'numero_serie' => $record->vehicle->numero_serie,
'marca' => $record->vehicle->marca,
'modelo' => $record->vehicle->modelo,
],
'owner' => [
'id' => $owner->id,
'full_name' => $owner->full_name,
'rfc' => $owner->rfc,
],
'new_files' => $uploadedFiles,
'total_new_files' => count($uploadedFiles),
]);
} catch (\Exception $e) {
DB::rollBack();
Log::error('Error en actualizarVehiculo: ' . $e->getMessage(), [
'record_id' => $recordId ?? null,
'trace' => $e->getTraceAsString()
]);
return ApiResponse::BAD_REQUEST->response([
'message' => 'Error al actualizar el vehículo',
'error' => $e->getMessage(),
]);
}
}
private function getVehicle(): array
{
return [
"ANIO_PLACA" => "2020",
"PLACA" => "WNU700B",
"NO_SERIE" => "LSGHD52H0ND032457",
"RFC" => "GME111116GJA",
"FOLIO" => "EXP-2025-201030",
"VIGENCIA" => "2025",
"FECHA_IMPRESION" => "10-01-2025",
"QR_HASH" => "Vu5TF4kYsbbltzjDdGQyenKfZoIk2wro34a5Gkh9JVh0CFxfPlrd92YEWK21JF.nLjQNyzKmqRvWYuPiS.kU7A--",
"VALIDO" => true,
"FOLIOTEMP" => false,
"NOMBRE" => "GOLSYSTEMS DE MEXICO S DE RL DE CV",
"NOMBRE2" => "GOLS*MS DXICOE RL*CV",
"MUNICIPIO" => "CENTRO",
"LOCALIDAD" => "VILLAHERMOSA",
"CALLE" => "C BUGAMBILIAS 118 ",
"CALLE2" => "C BU*ILIA*18 ",
"TIPO" => "SEDAN",
"TIPO_SERVICIO" => "PARTICULAR",
"MARCA" => "CHEVROLET G.M.C.",
"LINEA" => "AVEO",
"SUBLINEA" => "PAQ. \"A\" LS",
"MODELO" => 2022,
"NUMERO_SERIE" => "LSGHD52H0ND032457",
"NUMERO_MOTOR" => "H. EN WUHANLL,SGM",
"DESCRIPCION_ORIGEN" => "IMPORTADO",
"COLOR" => "BLANCO",
"CODIGO_POSTAL" => "86179",
"SERIE_FOLIO" => "D3962243",
"SFOLIO" => "3962243"
];
}
private function getVehicle2(): array
{
return [
"ANIO_PLACA" => "2027",
"PLACA" => "WNU700Z",
"NO_SERIE" => "EXP-2025-201030",
"RFC" => "GME111116GJA",
"FOLIO" => "EXP-2025-201030",
"VIGENCIA" => "2026",
"FECHA_IMPRESION" => "10-01-2025",
"QR_HASH" => "Vu5TF4kYsbbltzjDdGQyenKfZoIk2wro34a5Gkh9JVh0CFxfPlrd92YEWK21JF.nLjQNyzKmqRvWYuPiS.kU7A--",
"VALIDO" => true,
"FOLIOTEMP" => false,
"NOMBRE" => "GOLSYSTEMS DE MEXICO S DE RL DE CV",
"NOMBRE2" => "GOLS*MS DXICOE RL*CV",
"MUNICIPIO" => "CENTRO",
"LOCALIDAD" => "VILLAHERMOSA",
"CALLE" => "C BUGAMBILIAS 119 ",
"CALLE2" => "C BU*ILIA*18 ",
"TIPO" => "SEDAN",
"TIPO_SERVICIO" => "PARTICULAR",
"MARCA" => "CHEVROLET G.M.C.",
"LINEA" => "AVEO",
"SUBLINEA" => "PAQ. \"A\" LS",
"MODELO" => 2023,
"NUMERO_SERIE" => "EXP-2025-201030",
"NUMERO_MOTOR" => "H. EN WUHANLL,SGM",
"DESCRIPCION_ORIGEN" => "IMPORTADO",
"COLOR" => "AZUL",
"CODIGO_POSTAL" => "86181",
"SERIE_FOLIO" => "D3962242",
"SFOLIO" => "EXP-2025-201030"
];
}
private function getOwner(): array
{
return [
'name' => 'Nicolas',
'paternal' => 'Hernandez',
'maternal' => 'Castillo',
'rfc' => 'HECN660509HTCRSC01',
'curp' => 'HECN660509HTCRSC01',
'address' => 'Fracc Pomoca, Calle Armadillo MZ9 LT28',
];
}
}