From 28f129393dddfd95d83d117ae314c49b903b5d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Sat, 31 Jan 2026 20:33:44 +0900 Subject: [PATCH] =?UTF-8?q?feat:=EA=B0=9C=EB=B0=9C=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=EC=A4=91=20=E2=86=92=20=EC=8A=B9=EC=9D=B8=EB=8C=80=EA=B8=B0?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - revertToPending 서비스 메서드 추가 - revertToPending 컨트롤러 액션 추가 - /approvals/{id}/revert-pending 라우트 추가 - progress-list에 "승인대기로" 버튼 추가 - JavaScript revertToPending 함수 추가 Co-Authored-By: Claude Opus 4.5 --- .../SalesDevelopmentApprovalController.php | 35 +++++++++++++++++++ .../Sales/SalesDevelopmentApprovalService.php | 24 +++++++++++++ .../sales/development/approvals.blade.php | 32 +++++++++++++++++ .../partials/progress-list.blade.php | 9 +++-- routes/web.php | 2 ++ 5 files changed, 100 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php b/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php index 821bfa21..ed2c8e05 100644 --- a/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php +++ b/app/Http/Controllers/Sales/SalesDevelopmentApprovalController.php @@ -170,6 +170,41 @@ public function updateStatus(Request $request, int $id) } } + /** + * 승인대기로 되돌리기 + */ + public function revertToPending(Request $request, int $id) + { + // 권한 체크 + if (!auth()->user()->isAdmin()) { + abort(403, '접근 권한이 없습니다.'); + } + + try { + $management = $this->service->revertToPending($id); + $tenantName = $management->tenant?->company_name ?? '알 수 없음'; + + if ($request->header('HX-Request')) { + return response()->json([ + 'success' => true, + 'message' => "{$tenantName}이(가) 승인대기로 이동되었습니다.", + ]); + } + + return redirect()->route('sales.development.approvals.index') + ->with('success', "{$tenantName}이(가) 승인대기로 이동되었습니다."); + } catch (\InvalidArgumentException $e) { + if ($request->header('HX-Request')) { + return response()->json([ + 'success' => false, + 'message' => $e->getMessage(), + ], 400); + } + + return redirect()->back()->with('error', $e->getMessage()); + } + } + /** * 상세 정보 모달 */ diff --git a/app/Services/Sales/SalesDevelopmentApprovalService.php b/app/Services/Sales/SalesDevelopmentApprovalService.php index 33aa7098..bad33a04 100644 --- a/app/Services/Sales/SalesDevelopmentApprovalService.php +++ b/app/Services/Sales/SalesDevelopmentApprovalService.php @@ -202,6 +202,30 @@ public function updateHqStatus(int $id, string $status): SalesTenantManagement return $management->fresh(); } + /** + * 승인대기로 되돌리기 (진행중 → pending) + */ + public function revertToPending(int $id): SalesTenantManagement + { + $management = SalesTenantManagement::findOrFail($id); + + // 이미 pending 상태인 경우 + if ($management->hq_status === SalesTenantManagement::HQ_STATUS_PENDING) { + throw new \InvalidArgumentException('이미 승인대기 상태입니다.'); + } + + // handover(인계) 상태에서는 되돌리기 불가 + if ($management->hq_status === SalesTenantManagement::HQ_STATUS_HANDOVER) { + throw new \InvalidArgumentException('인계 완료된 항목은 되돌릴 수 없습니다.'); + } + + $management->update([ + 'hq_status' => SalesTenantManagement::HQ_STATUS_PENDING, + ]); + + return $management->fresh(); + } + /** * 상세 정보 조회 */ diff --git a/resources/views/sales/development/approvals.blade.php b/resources/views/sales/development/approvals.blade.php index 43de16e2..998c1c09 100644 --- a/resources/views/sales/development/approvals.blade.php +++ b/resources/views/sales/development/approvals.blade.php @@ -198,6 +198,38 @@ function updateStatus(id, name) { ); } +// 승인대기로 되돌리기 +function revertToPending(id, name) { + showConfirm( + `${name}을(를) 승인대기 상태로 되돌리시겠습니까?
개발 진행 상태가 초기화됩니다.`, + () => { + fetch(`/sales/development/approvals/${id}/revert-pending`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRF-TOKEN': '{{ csrf_token() }}', + 'Accept': 'application/json', + 'HX-Request': 'true' + } + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + showToast(data.message, 'success'); + window.location.reload(); + } else { + showToast(data.message || '되돌리기에 실패했습니다.', 'error'); + } + }) + .catch(error => { + showToast('서버 오류가 발생했습니다.', 'error'); + console.error(error); + }); + }, + { title: '승인대기로 이동', icon: 'warning', confirmText: '이동' } + ); +} + // 상세 모달 열기 function openDetailModal(id) { document.getElementById('detailModal').classList.remove('hidden'); diff --git a/resources/views/sales/development/partials/progress-list.blade.php b/resources/views/sales/development/partials/progress-list.blade.php index 81f8d5cd..d0684d57 100644 --- a/resources/views/sales/development/partials/progress-list.blade.php +++ b/resources/views/sales/development/partials/progress-list.blade.php @@ -81,8 +81,13 @@ class="px-2 py-1 bg-purple-500 hover:bg-purple-600 text-white text-xs font-mediu - {{-- 상세 버튼 --}} -
+ {{-- 버튼 --}} +
+