repuve-backend-v1/app/Http/Controllers/Repuve/CancellationController.php

320 lines
12 KiB
PHP

<?php
namespace App\Http\Controllers\Repuve;
use App\Http\Controllers\Controller;
use App\Http\Requests\Repuve\ConsultaVehiculoRequest;
use App\Http\Requests\Repuve\CancelConstanciaRequest;
use App\Models\Vehicle;
use App\Models\Tag;
use App\Models\VehicleTagLog;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Notsoweb\ApiResponse\Enums\ApiResponse;
class CancellationController extends Controller
{
/* ===========================================================
* PASO 1: Buscar vehículo para cancelar
* Muestra la tabla con los datos del vehículo encontrado
* ===========================================================
*/
public function searchToCancel(ConsultaVehiculoRequest $request)
{
try {
$searchType = $request->input('search_type');
$searchValue = $request->input('search_value');
// Simulación: consulta a base de datos REPUVE hardcodeada
$vehicleData = $this->getVehicleDataFromRepuve($searchType, $searchValue);
if (!$vehicleData) {
return ApiResponse::NOT_FOUND->response([
'message' => 'No se encontró ningún vehículo con los datos proporcionados en REPUVE.',
'search_type' => $searchType,
'search_value' => $searchValue,
]);
}
// Buscar vehículo en nuestra base de datos local
$vehicle = Vehicle::where('numero_serie', $vehicleData['NO_SERIE'])
->with(['owner'])
->first();
if (!$vehicle) {
return ApiResponse::NOT_FOUND->response([
'message' => 'El vehículo existe en REPUVE pero no está registrado localmente.',
'repuve_data' => $vehicleData,
]);
}
// Buscar tag asignado al vehículo (solo assigned)
$tag = Tag::where('vehicle_id', $vehicle->id)
->where('status', 'assigned')
->first();
// Verificar si ya tiene cancelaciones previas
$cancelaciones = VehicleTagLog::where('vehicle_id', $vehicle->id)
->whereNotNull('cancellation_at')
->count();
$canCancel = !is_null($tag) && $tag->status === 'assigned';
return ApiResponse::OK->response([
'vehicle' => [
'id' => $vehicle->id,
'estatus' => $tag ? $tag->status : 'sin_tag',
'folio' => $vehicle->folio,
'tag' => $tag ? $tag->folio : null,
'niv' => $vehicle->numero_serie,
'tipo' => $vehicle->tipo,
'registro' => $vehicle->created_at->format('d/m/Y'),
'placa' => $vehicle->placa,
'marca' => $vehicle->marca,
'modelo' => $vehicle->modelo,
'color' => $vehicle->color,
],
'tag' => $tag ? [
'id' => $tag->id,
'folio' => $tag->folio,
'status' => $tag->status,
] : null,
'can_cancel' => $canCancel,
'total_cancelaciones_previas' => $cancelaciones,
'message' => $canCancel
? 'Vehículo encontrado. Puede proceder con la cancelación.'
: 'Vehículo encontrado pero no tiene tag asignado o ya está cancelado.',
]);
} catch (\Exception $e) {
Log::error('Error en buscarVehiculoParaCancelar: ' . $e->getMessage(), [
'search_type' => $searchType ?? null,
'search_value' => $searchValue ?? null,
'trace' => $e->getTraceAsString()
]);
return ApiResponse::INTERNAL_SERVER_ERROR->response([
'message' => 'Error al buscar el vehículo',
'error' => $e->getMessage(),
]);
}
}
/* ===========================================================
* Cancelar constancia
* ===========================================================
*/
public function cancelarConstancia(CancelConstanciaRequest $request)
{
// Iniciar transacción
DB::beginTransaction();
try {
$vehicleId = $request->input('vehicle_id');
$tagId = $request->input('tag_id');
$reason = $request->input('cancellation_reason');
$observations = $request->input('cancellation_observations');
// Validar que el vehículo existe
$vehicle = Vehicle::findOrFail($vehicleId);
// Validar que el tag existe
$tag = Tag::findOrFail($tagId);
// Validar que el tag pertenece al vehículo
if ($tag->vehicle_id !== $vehicle->id) {
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => 'El tag no está asignado al vehículo especificado',
]);
}
// Validar que el tag esté en estado 'assigned'
if ($tag->status !== 'assigned') {
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => "El tag no puede ser cancelado. Estado actual: {$tag->status}",
'current_status' => $tag->status,
]);
}
// Verificar que no exista ya un registro de cancelación para este tag
$existingCancellation = VehicleTagLog::where('tag_id', $tagId)
->whereNotNull('cancellation_at')
->first();
if ($existingCancellation) {
DB::rollBack();
return ApiResponse::BAD_REQUEST->response([
'message' => 'Este tag ya tiene un registro de cancelación',
'cancellation_date' => $existingCancellation->cancellation_at->toDateTimeString(),
]);
}
// Crear registro de cancelación en vehicle_tags_logs
$cancellationLog = VehicleTagLog::create([
'vehicle_id' => $vehicleId,
'tag_id' => $tagId,
'cancellation_at' => now(),
'cancellation_reason' => $reason,
'cancellation_observations' => $observations,
'cancelled_by' => auth()->id(),
]);
// Actualizar estado del tag a 'cancelled'
$tag->update(['status' => 'cancelled']);
// Confirmar transacción
DB::commit();
// Recargar vehículo con tag actualizado
$vehicle->load('owner');
$tag->refresh();
return ApiResponse::OK->response([
'success' => true,
'message' => 'Constancia de inscripción cancelada exitosamente',
'vehicle' => [
'id' => $vehicle->id,
'estatus' => 'cancelada',
'folio' => $vehicle->folio,
'tag' => $tag->folio,
'niv' => $vehicle->numero_serie,
'tipo' => $vehicle->tipo,
'registro' => $vehicle->created_at->format('d/m/Y'),
],
'cancellation' => [
'id' => $cancellationLog->id,
'motivo' => $cancellationLog->cancellation_reason,
'observaciones' => $cancellationLog->cancellation_observations,
'fecha_cancelacion' => $cancellationLog->cancellation_at->format('d/m/Y H:i:s'),
'cancelado_por' => auth()->user()->name ?? 'Sistema',
],
]);
} catch (\Exception $e) {
// Revertir transacción en caso de error
DB::rollBack();
Log::error('Error en cancelarConstancia: ' . $e->getMessage(), [
'vehicle_id' => $request->input('vehicle_id'),
'tag_id' => $request->input('tag_id'),
'trace' => $e->getTraceAsString()
]);
return ApiResponse::INTERNAL_SERVER_ERROR->response([
'message' => 'Error al cancelar la constancia de inscripción',
'error' => $e->getMessage(),
]);
}
}
/**
* Obtiene historial de cancelaciones de un vehículo
*/
public function historialCancelaciones($vehicleId)
{
try {
$vehicle = Vehicle::findOrFail($vehicleId);
$cancelaciones = VehicleTagLog::where('vehicle_id', $vehicleId)
->whereNotNull('cancellation_at')
->with(['tag', 'cancelledBy'])
->orderBy('cancellation_at', 'desc')
->get();
return ApiResponse::OK->response([
'vehicle' => [
'id' => $vehicle->id,
'placa' => $vehicle->placa,
'numero_serie' => $vehicle->numero_serie,
],
'total_cancelaciones' => $cancelaciones->count(),
'cancelaciones' => $cancelaciones->map(function ($log) {
return [
'id' => $log->id,
'tag_folio' => $log->tag->folio ?? 'N/A',
'cancellation_at' => $log->cancellation_at->toDateTimeString(),
'cancellation_reason' => $log->cancellation_reason,
'cancellation_observations' => $log->cancellation_observations,
'cancelled_by' => $log->cancelledBy ? [
'id' => $log->cancelledBy->id,
'name' => $log->cancelledBy->name,
] : null,
];
}),
]);
} catch (\Exception $e) {
Log::error('Error en historialCancelaciones: ' . $e->getMessage(), [
'vehicle_id' => $vehicleId ?? null,
'trace' => $e->getTraceAsString()
]);
return ApiResponse::INTERNAL_SERVER_ERROR->response([
'message' => 'Error al obtener el historial de cancelaciones',
'error' => $e->getMessage(),
]);
}
}
/**
* Simula consulta a base de datos REPUVE
*
*/
private function getVehicleDataFromRepuve(string $searchType, string $searchValue): ?array
{
// Datos hardcodeados del vehículo de ejemplo
$vehicleData = [
"ANIO_PLACA" => "2020",
"PLACA" => "WNU700B",
"NO_SERIE" => "LSGHD52H0ND032457",
"RFC" => "GME111116GJA",
"FOLIO" => "3962243",
"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"
];
// Normalizar el valor de búsqueda (trim y uppercase)
$searchValue = trim(strtoupper($searchValue));
// Simular búsqueda por tipo
switch ($searchType) {
case 'folio':
return (strtoupper($vehicleData['FOLIO']) === $searchValue) ? $vehicleData : null;
case 'vin':
return (strtoupper($vehicleData['NO_SERIE']) === $searchValue) ? $vehicleData : null;
case 'fecha':
// Para fecha, comparar sin case sensitivity
return (strtoupper($vehicleData['FECHA_IMPRESION']) === $searchValue) ? $vehicleData : null;
default:
return null;
}
}
}