validate([ 'board_id' => ['required', 'integer', Rule::exists('helpdesk_kanban_boards', 'id')], 'return_to_board_id' => ['nullable', 'integer', Rule::exists('helpdesk_kanban_boards', 'id')], ]); $targetBoardId = (int) $validated['board_id']; $targetBoard = KanbanBoard::query() ->with(['statuses' => fn ($query) => $query->orderBy('helpdesk_kanban_board_statuses.sort_order')->orderBy('helpdesk_statuses.sort_order')->orderBy('helpdesk_statuses.name')]) ->findOrFail($targetBoardId); if ($targetBoard->statuses->isEmpty()) { $this->ensureBoardHasStatuses($targetBoardId); $targetBoard->load(['statuses' => fn ($query) => $query->orderBy('helpdesk_kanban_board_statuses.sort_order')->orderBy('helpdesk_statuses.sort_order')->orderBy('helpdesk_statuses.name')]); } $fresh = DB::transaction(function () use ($ticket, $targetBoard): Ticket { $lockedTicket = Ticket::query() ->visibleTo(Auth::user()) ->lockForUpdate() ->findOrFail($ticket->id); $targetStatus = $targetBoard->statuses->firstWhere('id', (int) $lockedTicket->status_id) ?: $targetBoard->statuses->first(); if ($targetStatus === null) { $targetStatus = Status::query()->orderBy('sort_order')->orderBy('name')->firstOrFail(); $this->addStatusToBoard($targetBoard->id, $targetStatus->id); } $updates = [ 'board_id' => $targetBoard->id, 'status_id' => $targetStatus->id, 'completed_at' => $targetStatus->is_closed ? now() : null, 'last_activity_at' => now(), ]; if (DB::getSchemaBuilder()->hasColumn('helpdesk_tickets', 'updated_at')) { $updates['updated_at'] = now(); } $affected = DB::table('helpdesk_tickets') ->where('id', $lockedTicket->id) ->update($updates); if ($affected < 1) { throw new TicketPersistenceException('Ticket board update did not persist.'); } return Ticket::query() ->with(['status', 'priority', 'category', 'project', 'team', 'product', 'tags', 'checklistItems', 'board']) ->findOrFail($lockedTicket->id); }); $workflow->dispatch($fresh, 'ticket.updated', Auth::user()); return redirect() ->route('helpdesk.kanban', ['board_id' => $targetBoardId]) ->with('success', 'Ticket ' . $fresh->reference . ' moved to ' . $targetBoard->name . '.'); } private function ensureBoardHasStatuses(int $boardId): void { Status::query() ->orderBy('sort_order') ->orderBy('name') ->get(['id']) ->values() ->each(function (Status $status, int $index) use ($boardId): void { $this->addStatusToBoard($boardId, (int) $status->id, ($index + 1) * 10); }); } private function addStatusToBoard(int $boardId, int $statusId, int $sortOrder = 999): void { DB::table('helpdesk_kanban_board_statuses')->updateOrInsert( ['board_id' => $boardId, 'status_id' => $statusId], ['sort_order' => $sortOrder, 'updated_at' => now(), 'created_at' => now()], ); } }