latest('id') ->limit(20) ->get(['id', 'reason_code', 'reason', 'status', 'admin_note', 'resolved_at', 'resolved_by', 'created_at']); return response()->json(['error' => false, 'data' => $requests]); } public function resolve(Request $request, int $id, int $requestId): JsonResponse { $data = $request->validate([ 'action' => 'required|in:approve,reject', 'note' => 'required_if:action,reject|nullable|string|max:1000', ]); $approve = $data['action'] === 'approve'; $result = DB::transaction(function () use ($id, $requestId, $data, $approve, $request) { $cancellation = ServiceCancellationRequest::where('service_id', $id)->lockForUpdate()->findOrFail($requestId); if ($cancellation->status !== ServiceCancellationRequest::STATUS_PENDING) { return null; } $admin = $request->user(); $cancellation->update([ 'status' => $approve ? ServiceCancellationRequest::STATUS_APPROVED : ServiceCancellationRequest::STATUS_REJECTED, 'admin_note' => filled($data['note'] ?? null) ? trim($data['note']) : null, 'resolved_at' => now(), 'resolved_by' => (string) ($admin?->fullname ?: $admin?->username ?: 'admin'), ]); $outcome = $approve ? ServiceCancellation::approve(Service::with('orderItem')->findOrFail($id)) : null; return [$cancellation, $outcome]; }); [$result, $outcome] = $result ?? [null, null]; if ($result === null) { return response()->json(['error' => true, 'message' => 'Yêu cầu này đã được xử lý.'], 422); } $this->notifyCustomer($result, $approve, $outcome); $message = match (true) { ! $approve => 'Đã từ chối yêu cầu hủy.', $outcome === ServiceCancellation::SCHEDULED => 'Đã duyệt: dịch vụ dùng tới hết hạn rồi tự hủy.', default => 'Đã duyệt và hủy dịch vụ.', }; return response()->json(['error' => false, 'message' => $message, 'data' => $result]); } private function notifyCustomer(ServiceCancellationRequest $cancellation, bool $approve, ?string $outcome): void { $cancellation->loadMissing(['customer', 'service']); if (! $cancellation->customer) { return; } $name = $cancellation->service->server_name ?: 'dịch vụ của bạn'; $expiresAt = $cancellation->service->expires_at?->format('d/m/Y'); $approvedBody = $outcome === ServiceCancellation::SCHEDULED ? "Dịch vụ {$name} sẽ không gia hạn nữa và vẫn sử dụng được đến hết {$expiresAt}." : "Dịch vụ {$name} đã được hủy theo yêu cầu của bạn."; $reason = $cancellation->admin_note ? " Ghi chú: {$cancellation->admin_note}" : ''; Notification::notifyCustomer($cancellation->customer, [ 'type' => 'service_cancellation_resolved', 'title' => $approve ? 'Yêu cầu hủy dịch vụ đã được duyệt' : 'Yêu cầu hủy dịch vụ bị từ chối', 'body' => ($approve ? $approvedBody : "Yêu cầu hủy dịch vụ {$name} chưa được chấp nhận.") . $reason, 'link' => '/dich-vu', ]); } }