# MNG 근태현황 개발 계획서

> **작성일**: 2026-02-26
> **상태**: 계획 수립

---

## 1. 개요

### 1.1 목적

MNG 인사관리 > 근태현황 기능을 완성한다. 현재 기본 CRUD가 구현되어 있으나, 미완성 기능과 알려진 버그를 해결하고 실무에 필요한 추가 기능을 구현한다.

### 1.2 현재 상태 분석

#### 구현 완료

| 항목 | 상태 | 파일 |
|------|------|------|
| 근태 목록 조회 (HTMX 테이블) | ✅ | `index.blade.php`, `table.blade.php` |
| 월간 통계 카드 (5종) | ✅ | `index.blade.php` |
| 필터 (이름, 부서, 상태, 날짜) | ✅ | `index.blade.php` |
| 등록/수정 모달 | ✅ | `index.blade.php` |
| CRUD API (목록/등록/수정/삭제) | ✅ | `AttendanceController.php` (API) |
| AttendanceService | ✅ | `AttendanceService.php` |
| Attendance 모델 (8개 상태) | ✅ | `Attendance.php` |
| Soft Delete | ✅ | 모델 + 서비스 |

#### 알려진 문제 (E2E 테스트 결과)

| 문제 | 심각도 | 설명 |
|------|--------|------|
| 엑셀 다운로드 미구현 | 🟡 중요 | 버튼 없음, API 미연결 |
| 근태 등록 서버 에러 | 🔴 필수 | 모달 submit 시 500 에러 발생 가능 |

#### 미구현 기능 (API 대비)

| 기능 | API 지원 | MNG 상태 |
|------|---------|---------|
| 엑셀 내보내기 | ✅ `/v1/attendances/export` | ❌ 미구현 |
| 일괄 삭제 | ✅ `/v1/attendances/bulk-delete` | ❌ 미구현 |
| 개인별 근태 상세 | ✅ `/v1/attendances/{id}` | ❌ 미구현 |
| 월간 요약 통계 | ✅ `/v1/attendances/monthly-stats` | ⚠️ 기본만 구현 |
| 출퇴근 설정 관리 | ✅ `attendance_settings` 테이블 | ❌ 미구현 |

---

## 2. 구현 범위

### 2.1 Phase 1: 버그 수정 + 핵심 기능 (우선)

| # | 작업 | 난이도 | 설명 |
|---|------|--------|------|
| 1-1 | 근태 등록/수정 버그 수정 | 🟢 낮음 | store/update API 요청 오류 점검 및 수정 |
| 1-2 | 엑셀 다운로드 | 🟢 낮음 | API `/v1/attendances/export` 연동, 다운로드 버튼 추가 |
| 1-3 | 일괄 삭제 | 🟡 보통 | 체크박스 선택 → 일괄 삭제 버튼 |
| 1-4 | 월간 통계 기간 선택 | 🟢 낮음 | 현재 당월 고정 → 연/월 선택 가능하게 |

### 2.2 Phase 2: 확장 기능

| # | 작업 | 난이도 | 설명 |
|---|------|--------|------|
| 2-1 | 개인별 근태 상세 페이지 | 🟡 보통 | 사원 클릭 → 월간 달력 + 출퇴근 이력 |
| 2-2 | 출퇴근 설정 관리 | 🟡 보통 | 표준 출근시간, GPS 사용여부, 허용반경 설정 |
| 2-3 | 월간/주간 요약 뷰 | 🟡 보통 | 부서별/사원별 근태 요약 테이블 |
| 2-4 | 근태 일괄 등록 | 🔴 높음 | 날짜 범위 + 대상 사원 → 일괄 근태 등록 |

---

## 3. 상세 설계

### 3.1 Phase 1-1: 근태 등록/수정 버그 수정

**점검 항목**:
- MNG `AttendanceController::store()` validation 규칙과 실제 폼 데이터 일치 여부
- `check_in`, `check_out` 포맷 (HH:MM vs HH:MM:SS) 불일치 가능성
- `user_id` 전달 누락 여부
- HTMX `hx-headers` CSRF 토큰 전달 확인

**수정 대상 파일**:
- `mng/app/Http/Controllers/Api/Admin/HR/AttendanceController.php`
- `mng/resources/views/hr/attendances/index.blade.php` (JS `submitAttendance()`)

---

### 3.2 Phase 1-2: 엑셀 다운로드

**방식**: MNG에서 직접 엑셀 생성 (API 서버 미경유)

**구현**:
1. `AttendanceService::getExportData()` 메서드 추가
2. `AttendanceController::export()` 메서드 추가
3. 라우트: `GET /api/admin/hr/attendances/export`
4. 인덱스 페이지에 다운로드 버튼 추가

**엑셀 컬럼**:

| 컬럼 | 값 |
|------|-----|
| 날짜 | `base_date` |
| 사원명 | `user.name` |
| 부서 | `department.name` |
| 상태 | `status_label` |
| 출근 | `check_in` |
| 퇴근 | `check_out` |
| 비고 | `remarks` |

**수정 대상 파일**:
- `mng/app/Services/HR/AttendanceService.php`
- `mng/app/Http/Controllers/Api/Admin/HR/AttendanceController.php`
- `mng/routes/api.php`
- `mng/resources/views/hr/attendances/index.blade.php`

---

### 3.3 Phase 1-3: 일괄 삭제

**UI**: 테이블 각 행에 체크박스 추가, 헤더에 전체선택, 상단에 "선택 삭제" 버튼

**구현**:
1. `table.blade.php`에 체크박스 컬럼 추가
2. Alpine.js 컴포넌트로 선택 상태 관리
3. `AttendanceController::bulkDestroy()` 메서드 추가
4. 라우트: `POST /api/admin/hr/attendances/bulk-delete`

**수정 대상 파일**:
- `mng/resources/views/hr/attendances/partials/table.blade.php`
- `mng/resources/views/hr/attendances/index.blade.php`
- `mng/app/Http/Controllers/Api/Admin/HR/AttendanceController.php`
- `mng/app/Services/HR/AttendanceService.php`
- `mng/routes/api.php`

---

### 3.4 Phase 1-4: 월간 통계 기간 선택

**현재**: 당월 통계만 표시 (하드코딩)
**변경**: 연/월 드롭다운 추가 → 선택 시 통계 카드 HTMX 갱신

**구현**:
1. 통계 카드 영역을 별도 partial로 분리 (`partials/stats.blade.php`)
2. 연/월 선택 UI 추가
3. `hx-get` + `hx-vals`로 선택된 연/월 전달
4. `stats()` API가 `year`, `month` 파라미터 이미 지원

**수정 대상 파일**:
- `mng/resources/views/hr/attendances/index.blade.php`
- `mng/resources/views/hr/attendances/partials/stats.blade.php` (신규)

---

### 3.5 Phase 2-1: 개인별 근태 상세 페이지

**URL**: `/hr/attendances/{userId}`

**페이지 구성**:
1. **사원 프로필 카드**: 이름, 부서, 직급, 재직상태
2. **월간 달력**: 날짜별 근태 상태를 색상 도트로 표시
3. **월간 통계**: 정시출근 N일, 지각 N일, 결근 N일 등
4. **출퇴근 이력 테이블**: 해당 월의 상세 출퇴근 기록

**수정 대상 파일**:
- `mng/routes/web.php` (라우트 추가)
- `mng/app/Http/Controllers/HR/AttendanceController.php` (`show()` 추가)
- `mng/app/Services/HR/AttendanceService.php` (`getUserMonthlyAttendances()` 추가)
- `mng/resources/views/hr/attendances/show.blade.php` (신규)

---

### 3.6 Phase 2-2: 출퇴근 설정 관리

**URL**: `/hr/attendance-settings`

**설정 항목** (`attendance_settings` 테이블 기반):

| 항목 | 필드 | 설명 |
|------|------|------|
| GPS 출퇴근 사용 | `use_gps` | on/off 토글 |
| 자동 출퇴근 | `use_auto` | on/off 토글 |
| 허용 반경 | `allowed_radius` | 미터 단위 입력 |
| 본사 주소 | `hq_address` | 주소 입력 |
| 본사 위도/경도 | `hq_latitude`, `hq_longitude` | 좌표 입력 |

**수정 대상 파일**:
- `mng/routes/web.php`, `mng/routes/api.php`
- `mng/app/Http/Controllers/HR/AttendanceSettingController.php` (신규)
- `mng/app/Models/HR/AttendanceSetting.php` (신규 — API 모델 미러링)
- `mng/resources/views/hr/attendance-settings/index.blade.php` (신규)

---

## 4. 데이터 흐름

### 4.1 MNG 자체 CRUD 패턴 (현재)

```
브라우저 ──HTMX──→ MNG API Controller ──→ MNG Service ──→ DB (직접)
                   (api/admin/hr/attendances)
```

> MNG는 API 서버를 경유하지 않고 DB에 직접 접근한다.

### 4.2 엑셀 다운로드 흐름

```
브라우저 ──GET──→ MNG AttendanceController::export()
                   → AttendanceService::getExportData()
                   → ExportService::download() (라라벨 엑셀)
                   ← BinaryFileResponse (.xlsx)
```

---

## 5. 구현 순서 및 의존 관계

```
Phase 1 (버그 수정 + 핵심)
  1-1 버그 수정 ─────────────────────────────┐
  1-2 엑셀 다운로드 ─────────────────────────┤ 독립적, 병렬 가능
  1-3 일괄 삭제 ─────────────────────────────┤
  1-4 통계 기간 선택 ────────────────────────┘

Phase 2 (확장)
  2-1 개인별 상세 ───→ 2-3 월간/주간 요약 (데이터 재사용)
  2-2 출퇴근 설정 ─── 독립적
  2-4 일괄 등록 ───── 독립적
```

---

## 6. 관련 파일 목록

### MNG 프로젝트 (`/home/aweso/sam/mng`)

| 파일 | 역할 |
|------|------|
| `app/Models/HR/Attendance.php` | 모델 (8개 상태, json_details) |
| `app/Services/HR/AttendanceService.php` | 비즈니스 로직 |
| `app/Http/Controllers/HR/AttendanceController.php` | 뷰 컨트롤러 |
| `app/Http/Controllers/Api/Admin/HR/AttendanceController.php` | API 컨트롤러 |
| `resources/views/hr/attendances/index.blade.php` | 메인 페이지 |
| `resources/views/hr/attendances/partials/table.blade.php` | 테이블 partial |
| `routes/web.php` | 웹 라우트 |
| `routes/api.php` | API 라우트 |

### API 프로젝트 (`/home/aweso/sam/api`)

| 파일 | 역할 |
|------|------|
| `database/migrations/2025_12_09_*_attendances*` | 마이그레이션 (2개) |
| `database/migrations/2025_12_17_*_attendance_settings*` | 설정 테이블 |
| `app/Models/Tenants/Attendance.php` | API 모델 (참조용) |
| `app/Models/Tenants/AttendanceSetting.php` | 설정 모델 (참조용) |

### 참조 문서

| 문서 | 경로 |
|------|------|
| 근태 API 규칙 | `docs/rules/attendance-api.md` |
| GPS 출퇴근 스펙 | `docs/specs/erp-analysis/03-gps-attendance.md` |

---

## 7. 검증 방법

### Phase 1 체크리스트

- [ ] 근태 등록 모달 → 사원 선택 + 날짜 + 상태 입력 → 저장 성공
- [ ] 근태 수정 모달 → 기존 데이터 로드 → 수정 → 저장 성공
- [ ] 동일 사원/날짜 중복 등록 시 기존 데이터 업데이트 (Upsert)
- [ ] 엑셀 다운로드 버튼 클릭 → .xlsx 파일 다운로드
- [ ] 체크박스 선택 → 일괄 삭제 → 테이블 갱신
- [ ] 연/월 선택 → 통계 카드 갱신

### Phase 2 체크리스트

- [ ] 사원 이름 클릭 → 개인별 상세 페이지 이동
- [ ] 달력에 근태 상태 색상 표시
- [ ] 출퇴근 설정 페이지 → GPS/자동 토글 → 저장
- [ ] 허용 반경 변경 → 저장 → DB 반영

---

**최종 업데이트**: 2026-02-26
