From 6b2d990d6ab4179f4bc3fb583b4359fa3954d7ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Thu, 26 Feb 2026 20:35:37 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20[hr]=20=EA=B7=BC=ED=83=9C=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=20=EA=B8=B0=ED=9A=8D=EC=84=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 화면 구성, 데이터 구조, 비즈니스 규칙, API 엔드포인트 정리 - 1차 구현 완료 12건, 2차 고도화 예정 8건 목록 - INDEX.md에 문서 등록 --- INDEX.md | 2 + features/hr/attendance-management-spec.md | 340 ++++++++++++++++++++++ 2 files changed, 342 insertions(+) create mode 100644 features/hr/attendance-management-spec.md diff --git a/INDEX.md b/INDEX.md index f36570d..7f840d4 100644 --- a/INDEX.md +++ b/INDEX.md @@ -163,8 +163,10 @@ docs/ | [barobill-kakaotalk/README.md](features/barobill-kakaotalk/README.md) | 바로빌 카카오톡 (알림톡/친구톡) 연동 | | [boards/README.md](features/boards/README.md) | 게시판 시스템 구현 | | [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 분석 (근태/직원/부서) | | [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용) | ### projects/ - 프로젝트별 문서 diff --git a/features/hr/attendance-management-spec.md b/features/hr/attendance-management-spec.md new file mode 100644 index 0000000..eb8e9b3 --- /dev/null +++ b/features/hr/attendance-management-spec.md @@ -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