feat:개발 승인 메뉴 구현
- 영업관리 하위에 "개발 승인" 메뉴 추가 - 영업/매니저 100% 완료 고객의 개발 진행 상태 관리 - 3분할 레이아웃: 승인대기 / 개발진행중 / 완료 - 7단계 진행 상태: 대기→검토→기획안작성→개발코드작성→개발테스트→개발완료→통합테스트→인계 - 승인/반려/상태변경 기능 구현 - 통계 카드 및 상세 모달 지원 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Sales;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Sales\SalesTenantManagement;
|
||||
use App\Services\Sales\SalesDevelopmentApprovalService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\View\View;
|
||||
|
||||
/**
|
||||
* 개발 승인 관리 컨트롤러
|
||||
*/
|
||||
class SalesDevelopmentApprovalController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private SalesDevelopmentApprovalService $service
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 개발 승인 메인 페이지
|
||||
*/
|
||||
public function index(Request $request): View|Response
|
||||
{
|
||||
// 권한 체크: admin 역할만 접근 가능
|
||||
if (!auth()->user()->isAdmin()) {
|
||||
abort(403, '접근 권한이 없습니다.');
|
||||
}
|
||||
|
||||
if ($request->header('HX-Request')) {
|
||||
return response('', 200)->header('HX-Redirect', route('sales.development.approvals.index'));
|
||||
}
|
||||
|
||||
$search = $request->get('search');
|
||||
|
||||
// 통계
|
||||
$stats = $this->service->getStats();
|
||||
|
||||
// 3개 목록
|
||||
$pendingItems = $this->service->getPendingApprovals($search);
|
||||
$progressItems = $this->service->getInProgressItems($search);
|
||||
$completedItems = $this->service->getCompletedItems($search);
|
||||
|
||||
// 본사 진행 상태 정보 (뷰에서 사용)
|
||||
$hqStatuses = SalesTenantManagement::$hqStatusLabels;
|
||||
$hqStatusOrder = SalesTenantManagement::$hqStatusOrder;
|
||||
|
||||
return view('sales.development.approvals', compact(
|
||||
'stats',
|
||||
'pendingItems',
|
||||
'progressItems',
|
||||
'completedItems',
|
||||
'hqStatuses',
|
||||
'hqStatusOrder'
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* 승인 처리
|
||||
*/
|
||||
public function approve(Request $request, int $id)
|
||||
{
|
||||
// 권한 체크
|
||||
if (!auth()->user()->isAdmin()) {
|
||||
abort(403, '접근 권한이 없습니다.');
|
||||
}
|
||||
|
||||
try {
|
||||
$management = $this->service->approve($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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 반려 처리
|
||||
*/
|
||||
public function reject(Request $request, int $id)
|
||||
{
|
||||
// 권한 체크
|
||||
if (!auth()->user()->isAdmin()) {
|
||||
abort(403, '접근 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'rejection_reason' => 'required|string|max:1000',
|
||||
]);
|
||||
|
||||
try {
|
||||
$management = $this->service->reject($id, $validated['rejection_reason']);
|
||||
$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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 상태 변경
|
||||
*/
|
||||
public function updateStatus(Request $request, int $id)
|
||||
{
|
||||
// 권한 체크
|
||||
if (!auth()->user()->isAdmin()) {
|
||||
abort(403, '접근 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'status' => 'required|string',
|
||||
]);
|
||||
|
||||
try {
|
||||
$management = $this->service->updateHqStatus($id, $validated['status']);
|
||||
$tenantName = $management->tenant?->company_name ?? '알 수 없음';
|
||||
$statusLabel = SalesTenantManagement::$hqStatusLabels[$validated['status']] ?? $validated['status'];
|
||||
|
||||
if ($request->header('HX-Request')) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => "{$tenantName}의 상태가 '{$statusLabel}'(으)로 변경되었습니다.",
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->route('sales.development.approvals.index')
|
||||
->with('success', "{$tenantName}의 상태가 '{$statusLabel}'(으)로 변경되었습니다.");
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
if ($request->header('HX-Request')) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => $e->getMessage(),
|
||||
], 400);
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 상세 정보 모달
|
||||
*/
|
||||
public function detail(int $id): View
|
||||
{
|
||||
// 권한 체크
|
||||
if (!auth()->user()->isAdmin()) {
|
||||
abort(403, '접근 권한이 없습니다.');
|
||||
}
|
||||
|
||||
$management = $this->service->getDetail($id);
|
||||
$hqStatuses = SalesTenantManagement::$hqStatusLabels;
|
||||
$hqStatusOrder = SalesTenantManagement::$hqStatusOrder;
|
||||
|
||||
return view('sales.development.partials.detail-modal', compact(
|
||||
'management',
|
||||
'hqStatuses',
|
||||
'hqStatusOrder'
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user