'vision', 'category_label' => '비전 & 전략', 'icon' => 'ri-lightbulb-line', 'color' => 'indigo', 'items' => [ [ 'slug' => 'ai-automation-vision', 'title' => 'SAM AI 자동화 비전', 'description' => 'SAM의 장기 비전과 AI 자동화 전략. 영업에서 출고까지 End-to-End 자동화 로드맵.', 'path' => 'system/ai-automation-vision.md', 'date' => '2026-03-02', 'badge' => '설계 확정', ], [ 'slug' => 'scaling-roadmap', 'title' => '10,000 테넌트 스케일링 로드맵', 'description' => '현재 아키텍처 진단부터 5단계 스케일링 계획까지. 세계 수준 엔지니어링 시나리오.', 'path' => 'system/scaling-roadmap.md', 'date' => '2026-02-22', 'badge' => '가상 시나리오', ], ], ], [ 'category' => 'launch', 'category_label' => '프로젝트 런칭', 'icon' => 'ri-rocket-line', 'color' => 'blue', 'items' => [ [ 'slug' => 'project-launch-roadmap', 'title' => 'SAM 프로젝트 런칭 로드맵', 'description' => '전체 시스템 구성, MVP 범위, 마일스톤(MS1~MS3), 개발 완료율 현황.', 'path' => 'guides/project-launch-roadmap.md', 'date' => '2025-12-02', 'badge' => '진행중', ], [ 'slug' => 'production-deployment-plan', 'title' => '운영 환경 배포 계획서', 'description' => 'MS3 정식 런칭 배포 계획. 무중단 전환, 롤백, Jenkins CI/CD 자동화.', 'path' => 'plans/production-deployment-plan.md', 'date' => '2026-02-22', 'badge' => '계획 수립', ], ], ], [ 'category' => 'product', 'category_label' => '제품 설계', 'icon' => 'ri-draft-line', 'color' => 'green', 'items' => [ [ 'slug' => 'erp-storyboard', 'title' => 'SAM ERP 스토리보드 D1.4', 'description' => '전체 ERP 메뉴 구조와 화면 설계. 대시보드, MES, HR, 전자결재, 회계, 구독 관리.', 'path' => 'plans/SAM_ERP_Storyboard_D1.4.md', 'date' => '2026-01-16', 'badge' => 'D1.4', ], [ 'slug' => 'erp-accounting-storyboard', 'title' => 'SAM ERP 회계관리 스토리보드 D1.6', 'description' => '세금계산서, 계좌 입출금, OCR, 일일 보고서, 건설/생산 대시보드.', 'path' => 'plans/SAM_ERP_회계관리_Storyboard_D1.6.md', 'date' => '2026-02-20', 'badge' => 'D1.6', ], [ 'slug' => 'integrated-master-plan', 'title' => '통합 개선 마스터 플랜', 'description' => '제품코드 추적성 + 검사 단위 구조 통합 개선. 7단계 Phase 로드맵.', 'path' => 'plans/integrated-master-plan.md', 'date' => '2026-02-27', 'badge' => 'Phase 0~3 완료', ], [ 'slug' => 'ai-quotation-engine-plan', 'title' => 'AI 견적서 자동생성 엔진 개발 계획', 'description' => '인터뷰 내용을 AI가 분석하여 SAM 표준 견적서로 자동 변환하는 엔진. Claude API 기반.', 'path' => 'plans/ai-quotation-engine-plan.md', 'date' => '2026-03-02', 'badge' => '기획 초안', ], ], ], [ 'category' => 'system', 'category_label' => '시스템 개요', 'icon' => 'ri-server-line', 'color' => 'gray', 'items' => [ [ 'slug' => 'system-overview', 'title' => 'SAM 시스템 개요', 'description' => '프로젝트 아키텍처, 기술 스택, 멀티테넌시, 레거시 마이그레이션 현황.', 'path' => 'system/overview.md', 'date' => '2026-02-27', 'badge' => '최신', ], ], ], ]; public function __construct( private readonly RoadmapPlanService $planService ) {} public function index(): View { $summary = $this->planService->getDashboardSummary(); $statuses = AdminRoadmapPlan::getStatuses(); $categories = AdminRoadmapPlan::getCategories(); $priorities = AdminRoadmapPlan::getPriorities(); $phases = AdminRoadmapPlan::getPhases(); return view('roadmap.index', compact( 'summary', 'statuses', 'categories', 'priorities', 'phases' )); } public function plans(): View { $statuses = AdminRoadmapPlan::getStatuses(); $categories = AdminRoadmapPlan::getCategories(); $priorities = AdminRoadmapPlan::getPriorities(); $phases = AdminRoadmapPlan::getPhases(); return view('roadmap.plans.index', compact('statuses', 'categories', 'priorities', 'phases')); } public function createPlan(): View { $statuses = AdminRoadmapPlan::getStatuses(); $categories = AdminRoadmapPlan::getCategories(); $priorities = AdminRoadmapPlan::getPriorities(); $phases = AdminRoadmapPlan::getPhases(); return view('roadmap.plans.create', compact('statuses', 'categories', 'priorities', 'phases')); } public function showPlan(int $id): View { $plan = $this->planService->getPlanById($id, true); if (! $plan) { abort(404, '계획을 찾을 수 없습니다.'); } $statuses = AdminRoadmapPlan::getStatuses(); $categories = AdminRoadmapPlan::getCategories(); $priorities = AdminRoadmapPlan::getPriorities(); $phases = AdminRoadmapPlan::getPhases(); return view('roadmap.plans.show', compact( 'plan', 'statuses', 'categories', 'priorities', 'phases' )); } public function editPlan(int $id): View { $plan = $this->planService->getPlanById($id, true); if (! $plan) { abort(404, '계획을 찾을 수 없습니다.'); } $statuses = AdminRoadmapPlan::getStatuses(); $categories = AdminRoadmapPlan::getCategories(); $priorities = AdminRoadmapPlan::getPriorities(); $phases = AdminRoadmapPlan::getPhases(); return view('roadmap.plans.edit', compact( 'plan', 'statuses', 'categories', 'priorities', 'phases' )); } public function documents(): View { $registry = self::DOCUMENT_REGISTRY; // 각 문서의 파일 존재 여부 확인 $docsBase = realpath(self::DOCS_BASE) ?: self::DOCS_BASE; foreach ($registry as &$group) { foreach ($group['items'] as &$item) { $item['exists'] = file_exists($docsBase.'/'.$item['path']); } } return view('roadmap.documents.index', compact('registry')); } public function showDocument(string $slug): View { $document = null; foreach (self::DOCUMENT_REGISTRY as $group) { foreach ($group['items'] as $item) { if ($item['slug'] === $slug) { $document = $item; $document['category_label'] = $group['category_label']; $document['color'] = $group['color']; break 2; } } } if (! $document) { abort(404, '문서를 찾을 수 없습니다.'); } $docsBase = realpath(self::DOCS_BASE) ?: self::DOCS_BASE; $filePath = $docsBase.'/'.$document['path']; $content = null; if (file_exists($filePath)) { $markdown = file_get_contents($filePath); $content = Str::markdown($markdown); } return view('roadmap.documents.show', compact('document', 'content')); } }