feat: actualizar método de cancelación de constancias para incluir validaciones y soporte de sustitución
This commit is contained in:
parent
908ba8aaf1
commit
44ef2f9306
@ -22,13 +22,21 @@ class CancellationController extends Controller
|
||||
/**
|
||||
* Cancelar la constancia/tag
|
||||
*/
|
||||
public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
public function cancelarConstancia(CancelConstanciaRequest $request, $recordId)
|
||||
{
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
// Buscar el expediente con sus relaciones
|
||||
$record = Record::with('vehicle.tag.status')->findOrFail($request->record_id);
|
||||
$record = Record::with('vehicle.tag.status')->find($recordId);
|
||||
|
||||
if (!$record) {
|
||||
return ApiResponse::NOT_FOUND->response([
|
||||
'message' => 'El expediente no existe.',
|
||||
'record_id' => $recordId,
|
||||
]);
|
||||
}
|
||||
|
||||
$vehicle = $record->vehicle;
|
||||
$tag = $vehicle->tag;
|
||||
|
||||
@ -39,18 +47,41 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
]);
|
||||
}
|
||||
|
||||
// Validar que el tag está en estado activo
|
||||
if (!$tag->isAssigned()) {
|
||||
// Validar que el tag está en estado activo O cancelado (para permitir sustitución posterior)
|
||||
if (!$tag->isAssigned() && !$tag->isCancelled()) {
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'El tag ya no está activo. Status actual: ' . $tag->status->name
|
||||
'message' => 'El tag debe estar asignado o cancelado. Status actual: ' . $tag->status->name
|
||||
]);
|
||||
}
|
||||
|
||||
// Validar que se proporcionen los datos de sustitución
|
||||
if (!$request->filled('new_folio') || !$request->filled('new_tag_number')) {
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'Para cancelar la constancia, debe proporcionar: nuevo folio y numero de constancia.',
|
||||
'provided' => [
|
||||
'new_folio' => $request->filled('new_folio'),
|
||||
'new_tag_number' => $request->filled('new_tag_number'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
// Validar que el tag_number tenga exactamente 17 caracteres
|
||||
if (strlen($request->new_tag_number) !== 32) {
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'El tag_number debe tener exactamente 32 caracteres',
|
||||
'provided_tag_number' => $request->new_tag_number,
|
||||
'length' => strlen($request->new_tag_number),
|
||||
]);
|
||||
}
|
||||
|
||||
$isSubstitution = true;
|
||||
|
||||
// Guardar información del tag anterior ANTES de cancelarlo
|
||||
$oldTagNumber = $tag->tag_number;
|
||||
$oldFolio = $tag->folio;
|
||||
|
||||
// Crear registro en el log de vehiculos
|
||||
// Crear registro en el log de vehículos
|
||||
if ($tag->isAssigned()) {
|
||||
$cancellationLog = VehicleTagLog::create([
|
||||
'vehicle_id' => $vehicle->id,
|
||||
'tag_id' => $tag->id,
|
||||
@ -62,21 +93,29 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
'performed_by' => Auth::id(),
|
||||
]);
|
||||
|
||||
// Actualizar estado del tag a 'cancelled' y desasignar vehículo
|
||||
// Actualizar estado del tag a 'cancelled'
|
||||
$tag->markAsCancelled();
|
||||
} else {
|
||||
// Si ya estaba cancelado, buscar el último log de cancelación
|
||||
$cancellationLog = VehicleTagLog::where('vehicle_id', $vehicle->id)
|
||||
->where('tag_id', $tag->id)
|
||||
->where('action_type', 'cancelacion')
|
||||
->latest()
|
||||
->first();
|
||||
}
|
||||
|
||||
$newTag = null;
|
||||
$substitutionLog = null;
|
||||
$isSubstitution = $request->filled('new_folio') && $request->filled('new_tag_number');
|
||||
|
||||
if ($isSubstitution) {
|
||||
// Buscar el nuevo tag por folio
|
||||
$newTag = Tag::where('folio', $request->new_folio)->first();
|
||||
|
||||
if (!$newTag) {
|
||||
DB::rollBack();
|
||||
return ApiResponse::NOT_FOUND->response([
|
||||
'message' => 'El nuevo tag proporcionado no existe.',
|
||||
'new_tag_number' => $request->new_tag_number,
|
||||
'message' => 'El tag con el folio proporcionado no existe.',
|
||||
'new_folio' => $request->new_folio,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -84,17 +123,22 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
DB::rollBack();
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'El nuevo tag no está disponible para asignación',
|
||||
'new_tag_number' => $request->new_tag_number,
|
||||
'new_folio' => $request->new_folio,
|
||||
'current_status' => $newTag->status->name,
|
||||
]);
|
||||
}
|
||||
|
||||
// Asignar tag_number al nuevo tag si no lo tiene
|
||||
if (!$newTag->tag_number) {
|
||||
$existingTag = Tag::where('tag_number', $request->new_tag_number)->first();
|
||||
if ($existingTag && $existingTag->id !== $newTag->id) {
|
||||
// Validar que el tag_number no esté usado por otro tag
|
||||
$existingTag = Tag::where('tag_number', $request->new_tag_number)
|
||||
->where('id', '!=', $newTag->id)
|
||||
->first();
|
||||
|
||||
if ($existingTag) {
|
||||
DB::rollBack();
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'El nuevo tag_number ya está asignado a otro folio.',
|
||||
'message' => 'El tag_number ya está asignado a otro tag.',
|
||||
'new_tag_number' => $request->new_tag_number,
|
||||
'folio_existente' => $existingTag->folio,
|
||||
]);
|
||||
@ -105,15 +149,19 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
} elseif ($newTag->tag_number !== $request->new_tag_number) {
|
||||
DB::rollBack();
|
||||
return ApiResponse::BAD_REQUEST->response([
|
||||
'message' => 'El nuevo tag ya tiene un tag_number diferente asignado.',
|
||||
'message' => 'El tag ya tiene un tag_number diferente asignado.',
|
||||
'assigned_tag_number' => $newTag->tag_number,
|
||||
'provided_tag_number' => $request->new_tag_number,
|
||||
]);
|
||||
}
|
||||
|
||||
// Usar el folio del request
|
||||
$newTag->markAsAssigned($vehicle->id, $request->folio);
|
||||
// Desasignar el tag viejo para evitar conflicto de unique constraint
|
||||
$tag->update(['vehicle_id' => null]);
|
||||
|
||||
// Asignar el nuevo tag al vehículo (usa el folio del tag encontrado)
|
||||
$newTag->markAsAssigned($vehicle->id, $newTag->folio);
|
||||
|
||||
// Crear log de sustitución
|
||||
$substitutionLog = VehicleTagLog::create([
|
||||
'vehicle_id' => $vehicle->id,
|
||||
'tag_id' => $newTag->id,
|
||||
@ -123,7 +171,8 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
'performed_by' => Auth::id(),
|
||||
]);
|
||||
|
||||
$record->update(['folio' => $request->folio]);
|
||||
// Actualizar el folio del expediente con el folio del nuevo tag
|
||||
$record->update(['folio' => $newTag->folio]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
@ -132,9 +181,22 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
? 'Tag cancelado y sustituido exitosamente'
|
||||
: 'Constancia cancelada exitosamente';
|
||||
|
||||
// Agregar alerta si NO hay sustitución
|
||||
$alert = null;
|
||||
if (!$isSubstitution) {
|
||||
$alert = [
|
||||
'type' => 'warning',
|
||||
'message' => 'El tag ha sido cancelado y necesita sustitución',
|
||||
'requires_action' => true,
|
||||
'cancellation_date' => $cancellationLog->cancellation_at->format('d/m/Y H:i:s'),
|
||||
'cancellation_reason' => $cancellationLog->cancellationReason->name,
|
||||
];
|
||||
}
|
||||
|
||||
return ApiResponse::OK->response([
|
||||
'message' => $message,
|
||||
'is_substitution' => $isSubstitution,
|
||||
'alert' => $alert,
|
||||
'cancellation' => [
|
||||
'id' => $cancellationLog->id,
|
||||
'vehicle' => [
|
||||
@ -144,8 +206,8 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
],
|
||||
'old_tag' => [
|
||||
'id' => $tag->id,
|
||||
'folio' => $tag->folio,
|
||||
'tag_number' => $tag->tag_number,
|
||||
'folio' => $oldFolio,
|
||||
'tag_number' => $oldTagNumber,
|
||||
'new_status' => 'Cancelado',
|
||||
],
|
||||
'new_tag' => $newTag ? [
|
||||
@ -154,7 +216,7 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
'tag_number' => $newTag->tag_number,
|
||||
'status' => $newTag->status->name,
|
||||
] : null,
|
||||
'cancellation_reason_id' => $cancellationLog->cancellationReason->name,
|
||||
'cancellation_reason' => $cancellationLog->cancellationReason->name,
|
||||
'cancellation_observations' => $request->cancellation_observations,
|
||||
'cancelled_at' => $cancellationLog->cancellation_at->toDateTimeString(),
|
||||
'cancelled_by' => Auth::user()->name,
|
||||
@ -164,7 +226,7 @@ public function cancelarConstancia(CancelConstanciaRequest $request)
|
||||
DB::rollBack();
|
||||
|
||||
Log::error('Error en cancelarConstancia: ' . $e->getMessage(), [
|
||||
'record_id' => $request->record_id ?? null,
|
||||
'record_id' => $recordId ?? null,
|
||||
'cancellation_reason' => $request->cancellation_reason ?? null,
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
@ -20,8 +20,7 @@ public function authorize(): bool
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'record_id' => 'nullable|exists:records,id',
|
||||
'folio' => 'required|string',
|
||||
'new_folio' => 'required|string',
|
||||
'cancellation_reason_id' => 'required|exists:catalog_cancellation_reasons,id',
|
||||
'cancellation_observations' => 'nullable|string',
|
||||
'new_tag_number' => 'nullable|exists:tags,tag_number',
|
||||
@ -34,8 +33,6 @@ public function rules(): array
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'record_id.required' => 'El id del expediente es obligatorio.',
|
||||
'record_id.integer' => 'El id del expediente debe ser un número entero.',
|
||||
'record_id.exists' => 'El expediente especificado no existe.',
|
||||
|
||||
'cancellation_reason_id.required' => 'El motivo de cancelación es obligatorio.',
|
||||
|
||||
@ -55,7 +55,7 @@
|
||||
|
||||
// Rutas de cancelación de constancias
|
||||
Route::resource('/razones-cancelacion', CatalogController::class);
|
||||
Route::delete('cancelacion', [CancellationController::class, 'cancelarConstancia']);
|
||||
Route::post('{recordId}/cancelacion', [CancellationController::class, 'cancelarConstancia']);
|
||||
Route::post('tags/cancelar', [CancellationController::class, 'cancelarTagNoAsignado']);
|
||||
Route::get('excel/constancias-sustituidas', [ExcelController::class, 'constanciasSustituidas']);
|
||||
Route::get('excel/constancias-canceladas', [ExcelController::class, 'constanciasCanceladas']);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user