docs: [hr] 근태관리 기획서 작성

- 화면 구성, 데이터 구조, 비즈니스 규칙, API 엔드포인트 정리
- 1차 구현 완료 12건, 2차 고도화 예정 8건 목록
- INDEX.md에 문서 등록
This commit is contained in:
김보곤
2026-02-26 20:35:37 +09:00
parent 34f9cf41e7
commit 6b2d990d6a
2 changed files with 342 additions and 0 deletions

View File

@@ -163,8 +163,10 @@ docs/
| [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 (알림톡/친구톡) 연동 | | [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 (알림톡/친구톡) 연동 |
| [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 | | [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 |
| [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 | | [boards/mng-implementation.md](features/boards/mng-implementation.md) | MNG 게시판 구현 상세 |
| [hr/attendance-management-spec.md](features/hr/attendance-management-spec.md) | 근태관리 기획서 (화면/데이터/비즈니스규칙/API) |
| [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) | | [hr/hr-api-analysis.md](features/hr/hr-api-analysis.md) | HR API 분석 (근태/직원/부서) |
| [quotes/README.md](features/quotes/README.md) | 견적 시스템 분석 (BOM 계산, 10단계 로직) | | [quotes/README.md](features/quotes/README.md) | 견적 시스템 분석 (BOM 계산, 10단계 로직) |
| [business-card-request.md](features/business-card-request.md) | 명함신청 관리 (3단계 워크플로우: 요청→제작의뢰→처리완료) |
| [academy/fire-shutter-image-prompts.md](features/academy/fire-shutter-image-prompts.md) | 방화셔터 백과사전 이미지 생성 프롬프트 (Gemini용) | | [academy/fire-shutter-image-prompts.md](features/academy/fire-shutter-image-prompts.md) | 방화셔터 백과사전 이미지 생성 프롬프트 (Gemini용) |
### projects/ - 프로젝트별 문서 ### projects/ - 프로젝트별 문서

View File

@@ -0,0 +1,340 @@
# 근태관리 기획서
> **작성일**: 2026-02-26
> **상태**: 1차 구현 완료 / 2차 고도화 예정
> **담당**: MNG 인사관리 모듈
---
## 1. 개요
### 1.1 목적
사원의 일별 출퇴근 및 근태 상태를 체계적으로 관리하여, 급여 산정·인사 평가·법정 근로시간 준수의 기초 데이터를 확보한다.
### 1.2 핵심 원칙
| 원칙 | 설명 |
|------|------|
| **정확성** | 출퇴근 시간·상태를 실시간으로 정확히 기록 |
| **자동화** | 지각/정시 자동 판정, 근무시간 자동 계산 |
| **유연성** | 휴가·출장·외근·재택 등 다양한 근무 형태 지원 |
| **감사 추적** | 모든 등록·수정·삭제에 작업자 기록 |
---
## 2. 화면 구성
### 2.1 메뉴 위치
```
인사관리
├── 사원관리
├── 근태관리 ← 현재 문서
├── 달력 관리
└── (향후 확장)
```
### 2.2 메인 화면 레이아웃
```
┌─────────────────────────────────────────────────────────────┐
│ 근태현황 [+ 근태 등록] │
│ 2026년 2월 현재 │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌────────┐│
│ │ 정시출근 │ │ 지각 │ │ 결근 │ │ 휴가 │ │ 기타 ││
│ │ 42건 │ │ 3건 │ │ 0건 │ │ 5건 │ │ 2건 ││
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └────────┘│
├─────────────────────────────────────────────────────────────┤
│ [검색: 사원명] [부서 ▼] [상태 ▼] [시작일] [종료일] [검색] │
├─────────────────────────────────────────────────────────────┤
│ 날짜 │ 사원 │ 부서 │ 상태 │ 출근 │ 퇴근 │ 비고 │
│──────────┼────────┼────────┼────────┼───────┼───────┼──────│
│ 02-26 │ 홍길동 │ 개발팀 │ 정시 │ 08:55 │ 18:10 │ │
│ 02-26 │ 김철수 │ 영업팀 │ 지각 │ 09:15 │ 18:30 │ │
│ 02-25 │ 이영희 │ 경영 │ 휴가 │ - │ - │ 연차 │
├─────────────────────────────────────────────────────────────┤
│ ◀ 1 2 3 4 5 ▶ │
└─────────────────────────────────────────────────────────────┘
```
### 2.3 근태 등록/수정 모달
```
┌──────────────── 근태 등록 ─────────────────┐
│ │
│ 사원 [홍길동 ▼] │
│ 날짜 [2026-02-26] │
│ 상태 [정시출근 ▼] │
│ 출근시간 [09:00] │
│ 퇴근시간 [18:00] │
│ 비고 [ ] │
│ │
│ [취소] [저장] │
└─────────────────────────────────────────────┘
```
---
## 3. 근태 상태 유형
| 상태 | 코드 | 색상 | 설명 |
|------|------|------|------|
| 정시출근 | `onTime` | 🟢 emerald | 정해진 출근 시간 내 출근 |
| 지각 | `late` | 🟡 amber | 출근 시간 초과 후 출근 |
| 결근 | `absent` | 🔴 red | 무단 미출근 |
| 휴가 | `vacation` | 🔵 blue | 연차·반차·병가 등 |
| 출장 | `businessTrip` | 🟣 purple | 사외 업무 수행 |
| 외근 | `fieldWork` | 🟤 indigo | 외부 근무 |
| 야근 | `overtime` | 🟠 orange | 정규시간 초과 근무 |
| 재택 | `remote` | 🟦 teal | 원격 근무 |
---
## 4. 데이터 구조
### 4.1 attendances 테이블
| 컬럼 | 타입 | 설명 |
|------|------|------|
| `id` | BIGINT PK | 고유 ID |
| `tenant_id` | BIGINT FK | 테넌트 ID |
| `user_id` | BIGINT FK | 사용자 ID |
| `base_date` | DATE | 기준 일자 |
| `status` | ENUM | 근태 상태 (8종) |
| `json_details` | JSON | 상세 정보 (출퇴근 시간, GPS 등) |
| `remarks` | VARCHAR(500) | 비고 |
| `created_by` | BIGINT | 등록자 |
| `updated_by` | BIGINT | 수정자 |
| `deleted_by` | BIGINT | 삭제자 |
| `created_at` | TIMESTAMP | 등록일시 |
| `updated_at` | TIMESTAMP | 수정일시 |
| `deleted_at` | TIMESTAMP | 삭제일시 (Soft Delete) |
**제약 조건**:
- `UNIQUE (tenant_id, user_id, base_date)` — 일자별 사용자당 1건만 허용
### 4.2 json_details 구조
```json
{
"check_in": "09:00:00",
"check_out": "18:00:00",
"check_ins": [
{ "time": "09:00:00", "recorded_at": "2026-02-26T09:00:00+09:00" }
],
"check_outs": [
{ "time": "18:00:00", "recorded_at": "2026-02-26T18:00:00+09:00" }
],
"gps_data": {
"check_in": { "lat": 37.5665, "lng": 126.9780, "accuracy": 10 },
"check_out": { "lat": 37.5665, "lng": 126.9780, "accuracy": 10 }
},
"work_minutes": 480,
"break_minutes": 60,
"overtime_minutes": 0,
"late_minutes": 0,
"early_leave_minutes": 0,
"vacation_type": "annual",
"external_work": {
"location": "고객사",
"purpose": "미팅",
"start_time": "14:00",
"end_time": "16:00"
}
}
```
### 4.3 attendance_settings 테이블
| 컬럼 | 타입 | 설명 |
|------|------|------|
| `tenant_id` | BIGINT UNIQUE | 테넌트별 1건 |
| `use_gps` | BOOLEAN | GPS 출퇴근 사용 여부 |
| `use_auto` | BOOLEAN | 자동 출퇴근 사용 여부 |
| `allowed_radius` | INT | 허용 반경 (m, 기본 100) |
| `hq_address` | VARCHAR(255) | 사업장 주소 |
| `hq_latitude` | DECIMAL(10,8) | 사업장 위도 |
| `hq_longitude` | DECIMAL(11,8) | 사업장 경도 |
---
## 5. 비즈니스 규칙
### 5.1 출퇴근 기록
| 규칙 | 설명 |
|------|------|
| R1 | 같은 날짜 + 사용자 조합은 1건만 존재 (Upsert) |
| R2 | 출근 기록 시 WorkSetting의 `start_time` 기준으로 지각/정시 자동 판정 |
| R3 | 퇴근 기록 시 근무시간 자동 계산: (최초 출근 ~ 최종 퇴근) - 휴게시간 |
| R4 | 다중 출퇴근 기록 지원 — `check_ins`/`check_outs` 배열로 이력 관리 |
| R5 | GPS 기록 시 사업장 반경 내 여부 검증 (Haversine 공식) |
### 5.2 상태 자동 판정
```
출근 시간 기록 시:
├── WorkSetting.start_time 이전 → 상태: 'onTime' (정시출근)
├── WorkSetting.start_time 이후 → 상태: 'late' (지각)
└── WorkSetting 미설정 → 상태: 'onTime' (기본값)
```
### 5.3 근무시간 계산
```
총 근무시간 = (가장 늦은 퇴근시간 - 가장 빠른 출근시간) - 휴게시간
휴게시간 산출:
├── WorkSetting에 break_start/break_end 설정 있음
│ └── 근무시간이 휴게 시간대를 포함하면 차감
└── 미설정 → 휴게시간 0분
```
### 5.4 권한
| 역할 | 조회 | 등록 | 수정 | 삭제 |
|------|:----:|:----:|:----:|:----:|
| 관리자 (admin) | ✅ 전체 | ✅ | ✅ | ✅ |
| 부서장 | ✅ 소속 부서 | ✅ | ✅ | ❌ |
| 일반 사원 | ✅ 본인 | ❌ | ❌ | ❌ |
---
## 6. 기능 목록
### 6.1 1차 구현 (완료)
| 기능 | 상태 | 설명 |
|------|:----:|------|
| 근태 목록 조회 | ✅ | 페이지네이션, 필터링, HTMX 테이블 |
| 근태 등록/수정 | ✅ | 모달 기반 CRUD |
| 근태 삭제 | ✅ | Soft Delete + 확인 대화상자 |
| 월별 통계 카드 | ✅ | 정시/지각/결근/휴가/기타 집계 |
| 필터링 | ✅ | 사원명 검색, 부서/상태/날짜 범위 필터 |
| 출근/퇴근 기록 API | ✅ | check-in/check-out 엔드포인트 |
| 근무시간 자동 계산 | ✅ | 출퇴근 시간 차 - 휴게시간 |
| 상태 자동 판정 | ✅ | WorkSetting 기준 지각/정시 판별 |
| 엑셀 내보내기 | ✅ | 월별 데이터 Excel 다운로드 |
| GPS 설정 | ✅ | 사업장 좌표, 허용 반경 설정 |
| 다중 출퇴근 기록 | ✅ | check_ins/check_outs 배열 관리 |
| 감사 로그 | ✅ | created_by, updated_by, deleted_by |
### 6.2 2차 고도화 (예정)
| 기능 | 우선순위 | 설명 |
|------|:--------:|------|
| 월간 캘린더 뷰 | 🔴 높음 | 달력 형태로 사원별 근태 현황 표시 |
| 일괄 등록 | 🔴 높음 | 다수 사원의 근태를 한 번에 등록 (CSV/엑셀 업로드) |
| 근태 승인 워크플로우 | 🟡 중간 | 휴가/출장 신청 → 부서장 승인 → 확정 |
| 초과근무 알림 | 🟡 중간 | 주 52시간 초과 시 관리자 알림 |
| 사원별 월간 요약 | 🟡 중간 | 개인별 월간 근무일수, 총 근무시간, 지각 횟수 등 |
| GPS 출퇴근 (모바일) | 🟢 낮음 | 모바일 앱에서 GPS 기반 자동 출퇴근 |
| 자동 결근 처리 | 🟢 낮음 | 영업일에 출근 기록 없으면 자동으로 결근 표시 |
| 연차 관리 연동 | 🟢 낮음 | 휴가 상태 등록 시 잔여 연차 자동 차감 |
---
## 7. API 엔드포인트
### 7.1 MNG 내부 API (HTMX)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/admin/hr/attendances` | 목록 조회 (HTML/JSON) |
| POST | `/api/admin/hr/attendances` | 등록 |
| PUT | `/api/admin/hr/attendances/{id}` | 수정 |
| DELETE | `/api/admin/hr/attendances/{id}` | 삭제 |
### 7.2 외부 API (sam/api)
| Method | Path | 설명 |
|--------|------|------|
| GET | `/api/v1/attendances` | 목록 조회 (페이지네이션) |
| GET | `/api/v1/attendances/{id}` | 상세 조회 |
| POST | `/api/v1/attendances` | 등록 |
| PATCH | `/api/v1/attendances/{id}` | 수정 |
| DELETE | `/api/v1/attendances/{id}` | 삭제 |
| POST | `/api/v1/attendances/bulk-delete` | 일괄 삭제 |
| POST | `/api/v1/attendances/check-in` | 출근 기록 |
| POST | `/api/v1/attendances/check-out` | 퇴근 기록 |
| GET | `/api/v1/attendances/monthly-stats` | 월별 통계 |
| GET | `/api/v1/attendances/export` | 엑셀 내보내기 |
---
## 8. 프로세스 흐름
### 8.1 관리자 근태 등록
```
관리자 → [근태 등록] 클릭 → 모달 열림
→ 사원 선택, 날짜·상태·시간 입력
→ [저장] 클릭
→ Fetch POST /api/admin/hr/attendances
→ 같은 날짜+사용자 기존 기록 있으면 Upsert
→ 성공 → 테이블 HTMX 새로고침
```
### 8.2 사원 출근 (API)
```
사원(모바일) → [출근] 버튼
→ POST /api/v1/attendances/check-in
{ user_id, check_in_time, gps? }
→ 서버: WorkSetting.start_time 기준 지각/정시 판정
→ 기존 기록 없으면 신규 생성
→ 기존 기록 있으면 check_ins 배열에 추가
→ 응답: 근태 레코드 반환
```
### 8.3 사원 퇴근 (API)
```
사원(모바일) → [퇴근] 버튼
→ POST /api/v1/attendances/check-out
{ user_id, check_out_time, gps? }
→ 서버: 근무시간 자동 계산
(가장 빠른 출근 ~ 가장 늦은 퇴근) - 휴게시간
→ check_outs 배열에 추가
→ work_minutes, overtime_minutes 업데이트
→ 응답: 근태 레코드 반환
```
---
## 9. 관련 파일
### MNG
| 파일 | 설명 |
|------|------|
| `app/Http/Controllers/HR/AttendanceController.php` | 페이지 렌더링 |
| `app/Http/Controllers/Api/Admin/HR/AttendanceController.php` | HTMX API |
| `app/Models/HR/Attendance.php` | 모델 (Accessor 포함) |
| `app/Services/HR/AttendanceService.php` | 비즈니스 로직 |
| `resources/views/hr/attendances/index.blade.php` | 메인 페이지 |
| `resources/views/hr/attendances/partials/table.blade.php` | 테이블 partial |
### API
| 파일 | 설명 |
|------|------|
| `app/Http/Controllers/Api/V1/AttendanceController.php` | RESTful API |
| `app/Models/Tenants/Attendance.php` | 모델 |
| `app/Models/Tenants/AttendanceSetting.php` | GPS/자동 설정 |
| `app/Services/AttendanceService.php` | 서비스 (642줄) |
| `database/migrations/2025_12_09_*` | 테이블 생성 |
### 문서
| 파일 | 설명 |
|------|------|
| `docs/rules/attendance-api.md` | API 비즈니스 규칙 |
| `docs/specs/erp-analysis/03-gps-attendance.md` | GPS 출퇴근 스펙 |
| `docs/specs/erp-analysis/04-hr-management.md` | HR 시스템 분석 |
---
**최종 업데이트**: 2026-02-26