- 영업관리 대시보드: 수당 현황, 테넌트 진행률, 파트너 활동 - 파트너관리: 영업파트너 CRUD, 역할 관리, 서류 관리 - 영업파트너승인: 신규 파트너 신청 승인/반려 워크플로우 - 상품관리: 카테고리별 상품, 가격/수당률 설정 - 고객관리(관리자): 전사 고객 현황, 본사 진행상태 8단계 - 영업파트너 고객관리: 명함등록 기반 영업권, 테넌트 전환 - 인터뷰 시나리오: 질문 템플릿, 세션 기반 인터뷰 기록 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
282 lines
9.7 KiB
Markdown
282 lines
9.7 KiB
Markdown
# 인터뷰 시나리오
|
|
|
|
## 개요
|
|
|
|
인터뷰 시나리오는 영업 상담 시 사용할 질문 템플릿을 관리하고,
|
|
인터뷰 세션을 진행/기록하는 기능입니다.
|
|
카테고리별 질문 구조, 체크리스트/텍스트 답변, MD 일괄 가져오기를 지원합니다.
|
|
|
|
- **라우트**: `GET /sales/interviews`
|
|
- **미들웨어**: `auth`, `hq.member`
|
|
- **UI 기술**: Blade + React/JavaScript (API 기반, 1,076줄)
|
|
|
|
## 파일 구조
|
|
|
|
```
|
|
mng/
|
|
├── app/Http/Controllers/Sales/
|
|
│ └── InterviewScenarioController.php # 메인 컨트롤러 (16개 메서드)
|
|
├── app/Services/Sales/
|
|
│ └── InterviewScenarioService.php # 비즈니스 로직 서비스
|
|
├── app/Models/Interview/
|
|
│ ├── InterviewCategory.php # 카테고리
|
|
│ ├── InterviewTemplate.php # 템플릿 (항목)
|
|
│ ├── InterviewQuestion.php # 질문
|
|
│ ├── InterviewSession.php # 인터뷰 세션
|
|
│ └── InterviewAnswer.php # 답변
|
|
└── resources/views/sales/interviews/
|
|
└── index.blade.php # 메인 페이지 (1,076줄)
|
|
|
|
api/
|
|
└── database/migrations/
|
|
├── 2026_02_06_100000_create_interview_categories_table.php
|
|
├── 2026_02_06_100001_create_interview_templates_table.php
|
|
├── 2026_02_06_100002_create_interview_questions_table.php
|
|
├── 2026_02_06_100003_create_interview_sessions_table.php
|
|
└── 2026_02_06_100004_create_interview_answers_table.php
|
|
```
|
|
|
|
## 라우트
|
|
|
|
```php
|
|
// routes/web.php (sales/interviews prefix 그룹 내)
|
|
|
|
// 페이지
|
|
GET /interviews → index() 메인 페이지
|
|
|
|
// 카테고리 API
|
|
GET /interviews/api/categories → categories() 카테고리 목록
|
|
POST /interviews/api/categories → storeCategory() 카테고리 생성
|
|
PUT /interviews/api/categories/{id} → updateCategory() 카테고리 수정
|
|
DELETE /interviews/api/categories/{id} → destroyCategory() 카테고리 삭제
|
|
|
|
// 트리 API
|
|
GET /interviews/api/tree → tree() 전체 계층 구조
|
|
|
|
// 템플릿(항목) API
|
|
POST /interviews/api/templates → storeTemplate() 템플릿 생성
|
|
PUT /interviews/api/templates/{id} → updateTemplate() 템플릿 수정
|
|
DELETE /interviews/api/templates/{id} → destroyTemplate() 템플릿 삭제
|
|
|
|
// 질문 API
|
|
POST /interviews/api/questions → storeQuestion() 질문 생성
|
|
PUT /interviews/api/questions/{id} → updateQuestion() 질문 수정
|
|
DELETE /interviews/api/questions/{id} → destroyQuestion() 질문 삭제
|
|
|
|
// 일괄 가져오기
|
|
POST /interviews/api/bulk-import → bulkImport() MD 파일에서 가져오기
|
|
|
|
// 세션(인터뷰) API
|
|
GET /interviews/api/sessions → sessions() 세션 목록 (필터)
|
|
POST /interviews/api/sessions → storeSession() 인터뷰 시작
|
|
GET /interviews/api/sessions/{id} → showSession() 세션 상세
|
|
POST /interviews/api/sessions/toggle-answer → toggleAnswer() 답변 토글
|
|
POST /interviews/api/sessions/{id}/complete → completeSession() 인터뷰 완료
|
|
```
|
|
|
|
## 컨트롤러
|
|
|
|
### InterviewScenarioController
|
|
|
|
| 메서드 | HTTP | 설명 |
|
|
|--------|------|------|
|
|
| `index()` | GET | 메인 페이지 |
|
|
| `categories()` | GET | 카테고리 목록 |
|
|
| `storeCategory()` | POST | 카테고리 생성 |
|
|
| `updateCategory()` | PUT | 카테고리 수정 |
|
|
| `destroyCategory()` | DELETE | 카테고리 삭제 |
|
|
| `tree()` | GET | 전체 계층 구조 (카테고리→템플릿→질문) |
|
|
| `storeTemplate()` | POST | 템플릿 생성 |
|
|
| `updateTemplate()` | PUT | 템플릿 수정 |
|
|
| `destroyTemplate()` | DELETE | 템플릿 삭제 |
|
|
| `storeQuestion()` | POST | 질문 생성 |
|
|
| `updateQuestion()` | PUT | 질문 수정 |
|
|
| `destroyQuestion()` | DELETE | 질문 삭제 |
|
|
| `bulkImport()` | POST | MD 파일에서 일괄 가져오기 |
|
|
| `sessions()` | GET | 인터뷰 세션 목록 |
|
|
| `storeSession()` | POST | 인터뷰 시작 |
|
|
| `showSession()` | GET | 세션 상세 |
|
|
| `toggleAnswer()` | POST | 답변 토글/기록 |
|
|
| `completeSession()` | POST | 인터뷰 완료 |
|
|
|
|
### InterviewScenarioService
|
|
|
|
| 메서드 | 설명 |
|
|
|--------|------|
|
|
| `getCategories()` | 카테고리 목록 |
|
|
| `createCategory()` | 카테고리 생성 |
|
|
| `updateCategory()` | 카테고리 수정 |
|
|
| `deleteCategory()` | 카테고리 삭제 |
|
|
| `getTree()` | 전체 계층 구조 조회 |
|
|
| `createTemplate()` | 템플릿 생성 |
|
|
| `updateTemplate()` | 템플릿 수정 |
|
|
| `deleteTemplate()` | 템플릿 삭제 |
|
|
| `createQuestion()` | 질문 생성 |
|
|
| `updateQuestion()` | 질문 수정 |
|
|
| `deleteQuestion()` | 질문 삭제 |
|
|
| `bulkImport()` | MD에서 일괄 가져오기 |
|
|
| `getSessions()` | 세션 목록 (필터) |
|
|
| `startSession()` | 인터뷰 시작 |
|
|
| `getSessionDetail()` | 세션 상세 |
|
|
| `toggleAnswer()` | 답변 토글 |
|
|
| `completeSession()` | 인터뷰 완료 |
|
|
|
|
## 모델
|
|
|
|
### 데이터 계층 구조
|
|
|
|
```
|
|
InterviewCategory (카테고리)
|
|
└── InterviewTemplate (템플릿/항목)
|
|
└── InterviewQuestion (질문)
|
|
|
|
InterviewSession (인터뷰 세션)
|
|
└── InterviewAnswer (답변)
|
|
```
|
|
|
|
### InterviewCategory
|
|
|
|
**테이블**: `interview_categories`
|
|
|
|
| 필드 | 타입 | 설명 |
|
|
|------|------|------|
|
|
| `tenant_id` | bigint | 테넌트 ID |
|
|
| `name` | string | 카테고리명 (예: 제조-방화셔터) |
|
|
| `description` | text | 설명 |
|
|
| `sort_order` | int | 정렬 순서 |
|
|
| `is_active` | boolean | 활성 여부 |
|
|
| `created_by` | bigint | 등록자 |
|
|
|
|
- SoftDeletes 적용
|
|
- 관계: `templates()`, `sessions()`
|
|
|
|
### InterviewTemplate
|
|
|
|
**테이블**: `interview_templates`
|
|
|
|
| 필드 | 타입 | 설명 |
|
|
|------|------|------|
|
|
| `tenant_id` | bigint | 테넌트 ID |
|
|
| `interview_category_id` | bigint (FK) | 카테고리 ID |
|
|
| `name` | string | 항목명 (예: 견적서 제작) |
|
|
| `description` | text | 설명 |
|
|
| `sort_order` | int | 정렬 순서 |
|
|
| `is_active` | boolean | 활성 여부 |
|
|
|
|
- SoftDeletes 적용
|
|
- 관계: `category()`, `questions()`
|
|
|
|
### InterviewQuestion
|
|
|
|
**테이블**: `interview_questions`
|
|
|
|
| 필드 | 타입 | 설명 |
|
|
|------|------|------|
|
|
| `tenant_id` | bigint | 테넌트 ID |
|
|
| `interview_template_id` | bigint (FK) | 템플릿 ID |
|
|
| `question_text` | string(500) | 질문 텍스트 |
|
|
| `question_type` | string | **checkbox** / **text** |
|
|
| `options` | json | 선택지 (배열) |
|
|
| `is_required` | boolean | 필수 여부 |
|
|
| `sort_order` | int | 정렬 순서 |
|
|
| `is_active` | boolean | 활성 여부 |
|
|
|
|
- SoftDeletes 적용
|
|
- 관계: `template()`
|
|
|
|
#### 질문 타입
|
|
|
|
| 타입 | 설명 | 답변 방식 |
|
|
|------|------|----------|
|
|
| `checkbox` | 체크 질문 | is_checked 토글 |
|
|
| `text` | 서술형 질문 | answer_text 입력 |
|
|
|
|
### InterviewSession
|
|
|
|
**테이블**: `interview_sessions`
|
|
|
|
| 필드 | 타입 | 설명 |
|
|
|------|------|------|
|
|
| `tenant_id` | bigint | 테넌트 ID |
|
|
| `interview_category_id` | bigint (FK) | 사용한 카테고리 ID |
|
|
| `interviewer_id` | bigint (FK) | 면담자(매니저) ID |
|
|
| `interviewee_name` | string(100) | 면담 상대 이름 |
|
|
| `interviewee_company` | string(200) | 면담 상대 회사 |
|
|
| `interview_date` | date | 면담 일자 |
|
|
| `status` | string | **in_progress** / **completed** |
|
|
| `total_questions` | int | 총 질문 수 |
|
|
| `answered_questions` | int | 답변 완료 수 |
|
|
| `memo` | text | 메모 |
|
|
| `completed_at` | timestamp | 완료 일시 |
|
|
|
|
- SoftDeletes 적용
|
|
- 관계: `category()`, `interviewer()`, `answers()`
|
|
|
|
### InterviewAnswer
|
|
|
|
**테이블**: `interview_answers`
|
|
|
|
| 필드 | 타입 | 설명 |
|
|
|------|------|------|
|
|
| `tenant_id` | bigint | 테넌트 ID |
|
|
| `interview_session_id` | bigint (FK) | 세션 ID |
|
|
| `interview_question_id` | bigint (FK) | 질문 ID |
|
|
| `interview_template_id` | bigint (FK) | 템플릿 ID |
|
|
| `is_checked` | boolean | 체크 여부 (checkbox 유형) |
|
|
| `answer_text` | text | 답변 텍스트 (text 유형) |
|
|
| `memo` | text | 메모 |
|
|
|
|
### 인터뷰 진행 흐름
|
|
|
|
```
|
|
1. 카테고리 선택 + 면담 상대 정보 입력
|
|
→ storeSession() → 세션 생성 (status: in_progress)
|
|
→ 해당 카테고리의 모든 질문에 대해 빈 Answer 생성
|
|
|
|
2. 질문별 답변 기록
|
|
→ toggleAnswer() → is_checked 토글 / answer_text 저장
|
|
→ answered_questions 카운트 갱신
|
|
|
|
3. 인터뷰 완료
|
|
→ completeSession() → status: completed, completed_at 기록
|
|
```
|
|
|
|
## 뷰 구성
|
|
|
|
### index.blade.php
|
|
|
|
```
|
|
┌─ 페이지 헤더 ──────────────────────
|
|
│ 제목: "인터뷰 시나리오"
|
|
│ [카테고리 추가] [일괄 가져오기] 버튼
|
|
│
|
|
├─ 좌측 사이드바 ───────────────────
|
|
│ 카테고리 트리
|
|
│ ├── 카테고리 A
|
|
│ │ ├── 템플릿 1 (질문 3개)
|
|
│ │ └── 템플릿 2 (질문 5개)
|
|
│ └── 카테고리 B
|
|
│ └── 템플릿 3 (질문 2개)
|
|
│
|
|
├─ 우측 메인 영역 ──────────────────
|
|
│ ├─ 템플릿 편집 모드
|
|
│ │ 질문 목록 + 추가/수정/삭제
|
|
│ │ 질문 타입(checkbox/text) + 옵션
|
|
│ │
|
|
│ └─ 인터뷰 세션 모드
|
|
│ 면담 상대 정보 + 날짜
|
|
│ 질문별 체크/답변 기록
|
|
│ 진행률 표시
|
|
│ [완료] 버튼
|
|
│
|
|
└─ 세션 목록 ───────────────────────
|
|
과거 인터뷰 기록 (필터: 카테고리, 날짜)
|
|
면담자 | 상대방 | 회사 | 날짜 | 완료율 | 상태
|
|
```
|
|
|
|
## HTMX 호환성
|
|
|
|
- JavaScript/React 기반 페이지이므로 **HX-Redirect 필요**
|
|
- API 호출로 동적 CRUD 관리
|
|
- `@push('scripts')` 블록에 스크립트 포함
|