find($expenseId); if (! $expense) { throw new RuntimeException('Expense not found.'); } if (! empty($expense->reimbursement_id)) { throw new RuntimeException('Expense is already tied to a reimbursement.'); } $now = now(); DB::beginTransaction(); try { ReimbursementBatchItem::query() ->where('expense_id', $expenseId) ->whereNull('unassigned_at') ->update(['unassigned_at' => $now]); $expense->update([ 'category' => 'Donation', 'status' => 'approved', 'status_reason' => 'Marked as Donation (non-reimbursable).', 'approved_by' => $userId ?: null, 'updated_by' => $userId ?: null, 'reimbursement_id' => null, ]); DB::commit(); } catch (\Throwable $e) { DB::rollBack(); Log::error('Failed to mark donation: '.$e->getMessage(), ['expense_id' => $expenseId]); throw new RuntimeException('Unable to mark donation right now.'); } } }