320 lines
12 KiB
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;
|
|
}
|
|
}
|
|
}
|