Correciones a Actualizar y Cancelar

This commit is contained in:
Juan Felipe Zapata Moreno 2025-11-21 20:17:26 -06:00
parent 4c6dccf056
commit ef864c4753
3 changed files with 291 additions and 115 deletions

View File

@ -40,7 +40,15 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
]); ]);
} }
// Crear registro en el log de cancelaciones (HISTORIAL) // Validar que el registro no tenga errores previos
if ($record->error_id !== null) {
return ApiResponse::BAD_REQUEST->response([
'message' => 'No se puede cancelar un registro que tiene errores. El vehículo no fue inscrito.',
'error_id' => $record->error_id
]);
}
// Crear registro en el log de cancelaciones
$cancellationLog = VehicleTagLog::create([ $cancellationLog = VehicleTagLog::create([
'vehicle_id' => $vehicle->id, 'vehicle_id' => $vehicle->id,
'tag_id' => $tag->id, 'tag_id' => $tag->id,
@ -50,9 +58,10 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
'cancelled_by' => auth()->id(), 'cancelled_by' => auth()->id(),
]); ]);
// Actualizar estado del tag a 'cancelled' // Actualizar estado del tag a 'cancelled' y desasignar vehículo
$tag->update([ $tag->update([
'status' => 'cancelled', 'status' => 'cancelled',
'vehicle_id' => null,
]); ]);
DB::commit(); DB::commit();
@ -64,7 +73,7 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
'vehicle' => [ 'vehicle' => [
'id' => $vehicle->id, 'id' => $vehicle->id,
'placa' => $vehicle->placa, 'placa' => $vehicle->placa,
'numero_serie' => $vehicle->numero_serie, 'niv' => $vehicle->niv,
], ],
'tag' => [ 'tag' => [
'id' => $tag->id, 'id' => $tag->id,

View File

@ -191,8 +191,8 @@ public function vehicleInscription(VehicleStoreRequest $request)
// Enviar a API Repuve Nacional // Enviar a API Repuve Nacional
$apiResponse = $this->sendToRepuveNacional($niv); $apiResponse = $this->sendToRepuveNacional($niv);
$apiResponse["repuve_response"]["folio_ci"] = $folio; $apiResponse["repuve_response"]["folio_ci"] = $folio; //harcodeado cambiar despues
$apiResponse["repuve_response"]["identificador_ci"] = $tagNumber; $apiResponse["repuve_response"]["identificador_ci"] = $tagNumber; //harcodeado cambiar despues
// Procesar respuesta // Procesar respuesta
if (isset($apiResponse['has_error']) && $apiResponse['has_error']) { if (isset($apiResponse['has_error']) && $apiResponse['has_error']) {

View File

@ -8,15 +8,28 @@
use Notsoweb\ApiResponse\Enums\ApiResponse; use Notsoweb\ApiResponse\Enums\ApiResponse;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Cache;
use App\Models\Record; use App\Models\Record;
use App\Models\File; use App\Models\File;
use App\Models\Owner; use App\Models\Owner;
use App\Models\Error; use App\Models\Error;
use App\Models\CatalogNameImg; use App\Models\CatalogNameImg;
use App\Services\RepuveService;
use App\Services\PadronEstatalService;
use Exception; use Exception;
class UpdateController extends Controller class UpdateController extends Controller
{ {
private RepuveService $repuveService;
private PadronEstatalService $padronEstatalService;
public function __construct(
RepuveService $repuveService,
PadronEstatalService $padronEstatalService
) {
$this->repuveService = $repuveService;
$this->padronEstatalService = $padronEstatalService;
}
public function vehicleData(Request $request) public function vehicleData(Request $request)
{ {
@ -31,7 +44,7 @@ public function vehicleData(Request $request)
$tagNumber = $request->input('tag_number'); $tagNumber = $request->input('tag_number');
$niv = $request->input('niv'); $niv = $request->input('niv');
$isStolen = $this->checkIfStolen($folio); $isStolen = $this->checkIfStolen($niv);
if ($isStolen) { if ($isStolen) {
return ApiResponse::FORBIDDEN->response([ return ApiResponse::FORBIDDEN->response([
@ -80,9 +93,30 @@ public function vehicleData(Request $request)
]); ]);
} }
// Consultar REPUVE Estatal para obtener datos actualizados
$vehicleDataEstatal = $this->getVehicle($niv);
$ownerDataEstatal = $this->getOwner($niv);
// Guardar en caché por 30 minutos
Cache::put("update_vehicle_{$niv}", $vehicleDataEstatal, 1800);
Cache::put("update_owner_{$niv}", $ownerDataEstatal, 1800);
// Detectar si hay cambios entre BD y padrón estatal
$hasVehicleChanges = $this->detectVehicleChanges($vehicle, $vehicleDataEstatal);
$hasOwnerChanges = $this->detectOwnerChanges($vehicle->owner, $ownerDataEstatal);
return ApiResponse::OK->response([ return ApiResponse::OK->response([
'message' => 'Datos del vehículo obtenidos exitosamente', 'message' => 'Datos del vehículo obtenidos exitosamente',
'records' => $record, 'current_data' => $record,
'estatal_data' => [
'vehicle' => $vehicleDataEstatal,
'owner' => $ownerDataEstatal,
],
'has_changes' => $hasVehicleChanges || $hasOwnerChanges,
'changes_detail' => [
'vehicle' => $hasVehicleChanges,
'owner' => $hasOwnerChanges,
],
]); ]);
} catch (Exception $e) { } catch (Exception $e) {
return ApiResponse::BAD_REQUEST->response([ return ApiResponse::BAD_REQUEST->response([
@ -99,7 +133,7 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
$tagNumber = $request->input('tag_number'); $tagNumber = $request->input('tag_number');
$niv = $request->input('niv'); $niv = $request->input('niv');
$isStolen = $this->checkIfStolen($folio); $isStolen = $this->checkIfStolen($niv);
if ($isStolen) { if ($isStolen) {
return ApiResponse::FORBIDDEN->response([ return ApiResponse::FORBIDDEN->response([
@ -137,20 +171,77 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
DB::beginTransaction(); DB::beginTransaction();
$ownerData = $this->getOwner(); // Intentar obtener datos del caché primero
$vehicleData = Cache::get("update_vehicle_{$niv}");
$ownerData = Cache::get("update_owner_{$niv}");
$owner = Owner::updateOrCreate( // Si no hay
['rfc' => $ownerData['rfc']], if (!$vehicleData || !$ownerData) {
[ $vehicleData = $this->getVehicle($niv);
'name' => $ownerData['name'], $ownerData = $this->getOwner($niv);
'paternal' => $ownerData['paternal'], }
'maternal' => $ownerData['maternal'],
'curp' => $ownerData['curp'], // Limpiar caché
'address' => $ownerData['address'], Cache::forget("update_vehicle_{$niv}");
] Cache::forget("update_owner_{$niv}");
);
// Detectar si hay cambios
$hasVehicleChanges = $this->detectVehicleChanges($vehicle, $vehicleData);
$hasOwnerChanges = $this->detectOwnerChanges($vehicle->owner, $ownerData);
// Actualizar propietario solo si hay cambios
$owner = $vehicle->owner;
if ($hasOwnerChanges) {
$owner = Owner::updateOrCreate(
['rfc' => $ownerData['rfc']],
[
'name' => $ownerData['name'],
'paternal' => $ownerData['paternal'],
'maternal' => $ownerData['maternal'],
'curp' => $ownerData['curp'],
'address' => $ownerData['address'],
'tipopers' => $ownerData['tipopers'],
'pasaporte' => $ownerData['pasaporte'],
'licencia' => $ownerData['licencia'],
'ent_fed' => $ownerData['ent_fed'],
'munic' => $ownerData['munic'],
'callep' => $ownerData['callep'],
'num_ext' => $ownerData['num_ext'],
'num_int' => $ownerData['num_int'],
'colonia' => $ownerData['colonia'],
'cp' => $ownerData['cp'],
]
);
}
// Actualizar vehículo solo si hay cambios
if ($hasVehicleChanges) {
$vehicle->update([
'placa' => $vehicleData['placa'],
'marca' => $vehicleData['marca'],
'linea' => $vehicleData['linea'],
'sublinea' => $vehicleData['sublinea'],
'modelo' => $vehicleData['modelo'],
'color' => $vehicleData['color'],
'numero_motor' => $vehicleData['numero_motor'],
'clase_veh' => $vehicleData['clase_veh'],
'tipo_servicio' => $vehicleData['tipo_servicio'],
'rfv' => $vehicleData['rfv'],
'rfc' => $vehicleData['rfc'],
'ofcexpedicion' => $vehicleData['ofcexpedicion'],
'fechaexpedicion' => $vehicleData['fechaexpedicion'],
'tipo_veh' => $vehicleData['tipo_veh'],
'numptas' => $vehicleData['numptas'],
'observac' => $vehicleData['observac'],
'cve_vehi' => $vehicleData['cve_vehi'],
'nrpv' => $vehicleData['nrpv'],
'tipo_mov' => $vehicleData['tipo_mov'],
'owner_id' => $owner->id,
]);
}
$uploadedFiles = []; $uploadedFiles = [];
$replacedFiles = [];
if ($request->hasFile('files')) { if ($request->hasFile('files')) {
$files = $request->file('files'); $files = $request->file('files');
@ -178,13 +269,11 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
]); ]);
} }
// Buscar si ya existe un archivo con este name_id para este record
$existingFile = File::where('record_id', $record->id) $existingFile = File::where('record_id', $record->id)
->where('name_id', $nameId) ->where('name_id', $nameId)
->first(); ->first();
if ($existingFile) { if ($existingFile) {
// Eliminar el archivo físico anterior
Storage::disk('public')->delete($existingFile->path); Storage::disk('public')->delete($existingFile->path);
$replacedFiles[] = [ $replacedFiles[] = [
@ -193,7 +282,6 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
'old_path' => $existingFile->path, 'old_path' => $existingFile->path,
]; ];
// Eliminar el registro de la BD
$existingFile->delete(); $existingFile->delete();
} }
@ -221,58 +309,76 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
} }
} }
//Envio de datos // Solo enviar a REPUVE Nacional si hay cambios
$apiResponse = $this->sendToRepuveNacional($niv); if ($hasVehicleChanges || $hasOwnerChanges || count($uploadedFiles) > 0) {
$apiResponse["repuve_response"]["folio_ci"] = $record->folio; //Envio de datos
$apiResponse["repuve_response"]["identificador_ci"] = $tag->tag_number; $apiResponse = $this->sendToRepuveNacional($niv);
$apiResponse["repuve_response"]["folio_ci"] = $record->folio;
$apiResponse["repuve_response"]["identificador_ci"] = $tag->tag_number;
if (isset($apiResponse['has_error']) && $apiResponse['has_error']) { if (isset($apiResponse['has_error']) && $apiResponse['has_error']) {
$error = Error::where('code', $apiResponse['error_code'])->first(); $error = Error::where('code', $apiResponse['error_code'])->first();
if (!$error) { if (!$error) {
DB::rollBack(); DB::rollBack();
return ApiResponse::INTERNAL_ERROR->response([ return ApiResponse::INTERNAL_ERROR->response([
'message' => 'Código de error no encontrado en el catálogo', 'message' => 'Código de error no encontrado en el catálogo',
'error_code' => $apiResponse['error_code'], 'error_code' => $apiResponse['error_code'],
'error_message' => $apiResponse['error_message'], 'error_message' => $apiResponse['error_message'],
]);
}
$record->update([
'error_id' => $error->id,
'api_response' => $apiResponse,
'error_occurred_at' => now(),
]);
DB::commit();
return ApiResponse::NOT_ACCEPTABLE->response([
'message' => 'Datos guardados con error. Corrija y vuelva a enviar.',
'has_error' => true,
'can_retry' => true,
'error' => [
'code' => $error->code,
'description' => $error->description,
'occurred_at' => $record->error_occurred_at->toDateTimeString(),
],
'record' => [
'id' => $record->id,
'folio' => $record->folio,
],
]); ]);
} }
$record->update([ $record->update([
'error_id' => $error->id, 'error_id' => null,
'api_response' => $apiResponse, 'api_response' => $apiResponse,
'error_occurred_at' => now(), 'error_occurred_at' => null,
]);
DB::commit();
return ApiResponse::NOT_ACCEPTABLE->response([
'message' => 'Datos guardados con error. Corrija y vuelva a enviar.',
'has_error' => true,
'can_retry' => true,
'error' => [
'code' => $error->code,
'description' => $error->description,
'occurred_at' => $record->error_occurred_at->toDateTimeString(),
],
'record' => [
'id' => $record->id,
'folio' => $record->folio,
],
]); ]);
} }
$record->update([
'error_id' => null,
'api_response' => $apiResponse,
'error_occurred_at' => null,
]);
DB::commit(); DB::commit();
$sentToRepuve = $hasVehicleChanges || $hasOwnerChanges || count($uploadedFiles) > 0;
$message = 'Vehículo actualizado exitosamente';
if (!$hasVehicleChanges && !$hasOwnerChanges && empty($uploadedFiles)) {
$message = 'No se detectaron cambios. Los datos ya estaban actualizados.';
} elseif (!$hasVehicleChanges && !$hasOwnerChanges) {
$message = 'Solo se actualizaron archivos. Los datos del vehículo/propietario no cambiaron.';
}
return ApiResponse::OK->response([ return ApiResponse::OK->response([
'message' => 'Vehículo actualizado exitosamente', 'message' => $message,
'has_error' => false, 'has_error' => false,
'sent_to_repuve' => $sentToRepuve,
'changes_made' => [
'vehicle_updated' => $hasVehicleChanges,
'owner_updated' => $hasOwnerChanges,
'files_uploaded' => count($uploadedFiles) > 0,
],
'record' => [ 'record' => [
'id' => $record->id, 'id' => $record->id,
'folio' => $record->folio, 'folio' => $record->folio,
@ -308,76 +414,137 @@ public function vehicleUpdate(VehicleUpdateRequest $request)
} }
} }
private function checkIfStolen(string $folio): bool private function checkIfStolen(string $niv): bool
{ {
// Aquí api servicio de REPUVE Nacional return $this->repuveService->verificarRobo($niv);
// simulamos con random }
return (bool) rand(0, 1);
private function prepararDatosParaInscripcion(string $niv): array
{
$datos = $this->padronEstatalService->getVehiculoByNiv($niv);
return [
'ent_fed' => $datos['ent_fed'] ?? '',
'ofcexp' => $datos['ofcexp'] ?? '',
'fechaexp' => $datos['fechaexp'] ?? '',
'placa' => $datos['placa'] ?? '',
'tarjetacir' => $datos['tarjetacir'] ?? '',
'marca' => $datos['marca'] ?? '',
'submarca' => $datos['submarca'] ?? '',
'version' => $datos['version'] ?? '',
'clase_veh' => $datos['clase_veh'] ?? '',
'tipo_veh' => $datos['tipo_veh'] ?? '',
'tipo_uso' => $datos['tipo_uso'] ?? '',
'modelo' => $datos['modelo'] ?? '',
'color' => $datos['color'] ?? '',
'motor' => $datos['motor'] ?? '',
'niv' => $datos['niv'] ?? '',
'rfv' => $datos['rfv'] ?? '',
'numptas' => $datos['numptas'] ?? '',
'observac' => $datos['observac'] ?? '',
'tipopers' => $datos['tipopers'] ?? '',
'curp' => $datos['curp'] ?? '',
'rfc' => $datos['rfc'] ?? '',
'pasaporte' => $datos['pasaporte'] ?? '',
'licencia' => $datos['licencia'] ?? '',
'nombre' => $datos['nombre'] ?? '',
'ap_paterno' => $datos['ap_paterno'] ?? '',
'ap_materno' => $datos['ap_materno'] ?? '',
'munic' => $datos['munic'] ?? '',
'callep' => $datos['callep'] ?? '',
'num_ext' => $datos['num_ext'] ?? '',
'num_int' => $datos['num_int'] ?? '',
'colonia' => $datos['colonia'] ?? '',
'cp' => $datos['cp'] ?? '',
'cve_vehi' => $datos['cve_vehi'] ?? '',
'nrpv' => $datos['nrpv'] ?? '',
'tipo_mov' => $datos['tipo_mov'] ?? '',
];
} }
private function sendToRepuveNacional(string $niv): array private function sendToRepuveNacional(string $niv): array
{ {
// Enviar datos a API Repuve Nacional $datosCompletos = $this->prepararDatosParaInscripcion($niv);
// Aquí se haría la llamada real a la API de Repuve Nacional return $this->repuveService->inscribirVehiculo($datosCompletos);
// Por ahora simulamos con mock igual que InscriptionController }
// Respuesta exitosa mockup REPUVE private function detectVehicleChanges($vehicle, array $vehicleDataEstatal): bool
$mockResponse = "OK:SIN INFORMACION|OTROS|SIN INFORMACION|10/07/2023|CENTRO|$niv|WSA548B|HR16777934V|2023|BLANCO|ADVANCE|TABASCO|NISSAN|MARCH|PARTICULAR|AUTOMOVIL|ACTIVO|null||null|0|null|0|10337954|E2003412012BB0C130FAD04D|Sin observaciones
"; {
$fieldsToCompare = [
// Parsear la cadena a JSON usando los campos oficiales
$fields = [
'marca',
'submarca',
'tipo_vehiculo',
'fecha_expedicion',
'oficina',
'niv',
'placa', 'placa',
'motor', 'marca',
'linea',
'sublinea',
'modelo', 'modelo',
'color', 'color',
'version', 'numero_motor',
'entidad', 'clase_veh',
'marca_padron', 'tipo_servicio',
'submarca_padron', 'rfv',
'tipo_uso_padron', 'rfc',
'tipo_vehiculo_padron', 'ofcexpedicion',
'estatus_registro', 'tipo_veh',
'aduana', 'numptas',
'nombre_aduana', 'observac',
'patente', 'cve_vehi',
'pedimento', 'nrpv',
'fecha_pedimento', 'tipo_mov'
'clave_importador',
'folio_ci',
'identificador_ci',
'observaciones'
]; ];
$values = explode('|', str_replace('OK:', '', $mockResponse));
$jsonResponse = []; foreach ($fieldsToCompare as $field) {
foreach ($fields as $i => $field) { $bdValue = $vehicle->$field ?? null;
$jsonResponse[$field] = $values[$i] ?? null; $estatalValue = $vehicleDataEstatal[$field] ?? null;
if (strval($bdValue) !== strval($estatalValue)) {
return true;
}
} }
return [ return false;
'has_error' => false,
'error_code' => null,
'error_message' => null,
'timestamp' => now()->toDateTimeString(),
'niv' => $niv,
'repuve_response' => $jsonResponse,
];
} }
private function getOwner(): array private function detectOwnerChanges($owner, array $ownerDataEstatal): bool
{ {
return [ $fieldsToCompare = [
'name' => 'Nicolas', 'name',
'paternal' => 'Hernandez', 'paternal',
'maternal' => 'Castillo', 'maternal',
'rfc' => 'HECN660509HTCRSC01', 'rfc',
'curp' => 'HECN660509HTCRSC01', 'curp',
'address' => 'Fracc Pomoca, Calle Armadillo MZ9 LT28', 'address',
'tipopers',
'pasaporte',
'licencia',
'ent_fed',
'munic',
'callep',
'num_ext',
'num_int',
'colonia',
'cp'
]; ];
foreach ($fieldsToCompare as $field) {
$bdValue = $owner->$field ?? null;
$estatalValue = $ownerDataEstatal[$field] ?? null;
if (strval($bdValue) !== strval($estatalValue)) {
return true;
}
}
return false;
}
private function getVehicle(string $niv): array
{
$datos = $this->padronEstatalService->getVehiculoByNiv($niv);
return $this->padronEstatalService->extraerDatosVehiculo($datos);
}
private function getOwner(string $niv): array
{
$datos = $this->padronEstatalService->getVehiculoByNiv($niv);
return $this->padronEstatalService->extraerDatosPropietario($datos);
} }
} }