HBEA420_근무 신청 (연장·휴일/외근)
(Hereby) 직원 앱 > 결재 허브([[HBEA400_결재 허브]]) > 근무 서브탭 > 근무 신청 (연장·휴일/외근)
| 앱 | 직원 앱 (employee-app, 포트 4002) |
| 대상 사용자 | 조건1 [직원 (self scope)] |
| 프로토타입 | TBU |
| 관련 정책 | [[POL_연장근무·외근 결재]] · 정책 원천 docs/ko/policy/01_Domains/mobile/approval.md |
| Status | review |
| Owner | 카나 (PM) |
개요
- 결재 허브([[HBEA400_결재 허브]]) "근무" 서브탭 화면. 요약 카드 + 내역 필터 칩(4종) + 신청 내역 리스트 + 우하단 FAB(+) → 액션시트(2종) 로 구성된다.
- FAB 액션시트에서 "연장·휴일 근무 신청" → 연장근무 신청 폼, "외근 신청" → 외근 신청 폼으로 분기한다. 연장은
OvertimeRecord, 외근은OffsiteWorkRecord를 self scope로status=pending생성한다. - 대기 상태 외근 내역은 행 내 "취소" 버튼으로 컨펌 없이 즉시 취소(대기→취소)한다. 승인된 외근 내역에는 "외근 보고서 작성" 버튼이 노출되어 [[HBEA421_보고서 제출]]로 전환된다.
- 연장/외근 유형은 Admin 유형([[HBAD261_유형 설정 (연장근무·외근·휴가)]])을 소비하고, 대기 건 결재는 팀 결재([[HBTM220_근무 관리 (연장·휴일/외근)]])에서 처리된다. 공통 서브탭 골격은 [[HBEA400_결재 허브]] 참조(중복 정의 금지).
문서 히스토리
| 날짜 | 작성자 | 팀 | 변경 내용 |
|---|---|---|---|
| 2026-07-06 | 카나 | PM | 최초 작성 |
| 2026-07-10 | 카나 | PM | 라이브 기능 검토 반영 (필터 칩·외근 폼·취소 버튼) |
| 2026-07-13 | 카나 | PM | 버튼 행동 명세 보강 |
| 2026-07-21 | 카나 | PM | GC700 깊이 재작성 |
| 2026-07-21 | 카나 | PM | 셀 스타일 확정판 적용 (콸 승인) |
| 2026-07-21 | 카나 | PM | TC 크로스체크 확정분 반영 (🟡) |
| 2026-07-29 | 카나 | PM | 코드 변경 반영(7c2eab6) |
Data I/O
Server → Client
| 변수 | DB 엔티티.컬럼 | 값 없을 때 | 비고 |
|---|---|---|---|
| $ | 집계(OvertimeRecord + OffsiteWorkRecord + 보고서, self) | "근무 신청 0건 (승인 0)" / "보고서 0건 (승인 0)" | census 실데이터 문구 |
| $ | OvertimeRecord[] (self, status별) | 리스트 Empty "근무 신청 내역이 없습니다" | 연장·휴일 신청 내역 |
| $ | OffsiteWorkRecord[] (self, status별) | 리스트 Empty "근무 신청 내역이 없습니다" | 외근 신청 내역 |
| $ | Admin 연장근무 유형 (OvertimeType[]) | Select placeholder "연장근무 유형을 선택하세요." | 예 "야간 연장" / "평일 연장-1" |
| $ | Admin 외근 유형 (OffsiteWorkType[]) | Select placeholder(값없음 시 빈 옵션) TBU | [[HBAD261_유형 설정 (연장근무·외근·휴가)]] |
Client → Server
| 액션 | 전달 값 | tRPC / SDK | 권한 토큰 |
|---|---|---|---|
| 연장 신청 "신청" | workDate · overtimeHours · category(OvertimeCategory.WEEKDAY 등) · startTime · endTime · reason | overtime.request (TC 라이브 확인) | overtime:write.self (추정) |
| 외근 신청 "신청" | date · startTime · endTime · location · notes | attendance.registerFieldWork (TC 라이브 확인) | offsiteWork:write.self (추정) |
| 외근 내역 "취소" | recordId | sdk.fieldwork.cancel() (추정) | offsiteWork:cancel.self (추정) |
| 내역 필터 칩 선택 | filter(전체/연장·휴일/외근/보고서) | 클라이언트 필터 (추정) | - |
외부 통합 (cross-app)
| 외부 시스템 | 데이터 | 동기/비동기 | 비고 |
|---|---|---|---|
| 팀 결재 ([[HBTM220_근무 관리 (연장·휴일/외근)]]) | 대기중 → 승인 / 반려 / 취소요청 결재 | 비동기 (결재자 액션 시) | OvertimeRecord.status / OffsiteWorkRecord.status 전이 |
| Admin 유형 ([[HBAD261_유형 설정 (연장근무·외근·휴가)]]) | overtime_types / offsite_work_types 원천 (typeId) | 동기 (폼 진입 시 조회) | junk 옵션 노출 관찰(테스트 데이터) |
| 근무 보고서 ([[HBEA421_보고서 제출]]) | 승인된 연장/외근 → 보고서 작성·제출 | 비동기 (승인 후 트리거) | 보고서 승인 → 근태/급여 반영 |
화면 플로우 (Mermaid)
근무 신청 공통 사양표 (요약 카드·내역 필터 칩·FAB·리스트)
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 화면 진입 조건 | - | 조건1 [직원 인증(self)] · 결재 허브 "근무" 서브탭 선택 시 노출, 미인증 시 hide | 인증 세션(self) · [[HBEA400_결재 허브]] | 공통 골격 |
| 01 | 초기 상태 | Output | 진입 → 요약 카드 + 필터 칩("전체" 활성) + 내역 리스트 렌더 | ${work_summary} · ${overtime_requests} · $ | census 확인 |
| 10 | 요약 카드 | Card / Output | • 신청·승인·보고서 건수를 집계해 표시하는 카드. 원문 "근무 신청 0건 (승인 0)" / "보고서 0건 (승인 0)" • 서버 0건 시: "0건 (승인 0)" 그대로 표시(hide 아님) | ${work_summary} · 보고서([[HBEA421_보고서 제출]]) | census 원문 · TBU: 집계 실패 시 갱신 무반응=버그 후보 |
| 20 | 내역 필터 칩 | Filter / Tab | • 선택 유형으로 내역 리스트를 거르는 필터 칩. 원문 4종 "전체" / "연장·휴일" / "외근" / "보고서", 기본 "전체" 활성 • 클릭 시: 선택 유형으로 리스트 필터 - CASE01 ["연장·휴일"]: OvertimeRecord만- CASE02 ["외근"]: OffsiteWorkRecord만- CASE03 ["보고서"]: 보고서만([[HBEA421_보고서 제출]]) - CASE04 [선택 유형 0건]: Empty(30-E) | ${overtime_requests} · ${offsite_requests} · 보고서 | census 원문 · TBU: 필터 처리 실패 시 무반응 |
| 30 | 신청 내역 리스트 | List | • 필터 결과 행을 렌더하는 리스트 • 표시 시: 상태별 행 액션 노출 - CASE01 [status=pending]: "대기" 배지 · 대기 외근 행 "취소"(60) - CASE02 [status=approved]: 승인 외근 행 "외근 보고서 작성"(70) • 연장 카드 시간·보고서 대기/승인 카드 "실제 근무/외근 시간"을 소수 대신 h:mm(8:30)으로 표기 | OvertimeRecord[] / OffsiteWorkRecord[] (self) · fmtHM(req.hours) · fmtHM(req.report.actualHours) | h:mm 표기 (코드 반영: 7c2eab6) · TBU: 행 컬럼 상세 |
| 30-E | ㄴ Empty | Text | • 리스트 0건 시 안내 문구 표시. 원문 "근무 신청 내역이 없습니다" | - | TBU: 필터별 문구 분화 |
| 40 | 신청 작성 FAB | Button (+) | • 신규 신청을 시작하는 우하단 "+" 버튼(접근성 이름 "새 신청"). self 인증 시 상시 노출 • 클릭 시: 액션시트(50) 오픈 | 50 액션시트 | census (접근성명 EA 공통) · TBU: 액션시트 미오픈 시 무반응=버그 후보 |
| 50 | 액션시트 | ActionSheet | • FAB에서 올라오는 하단 시트. 2종 "연장·휴일 근무 신청" / "외근 신청" (별도 표) • 클릭 시: 하단 시트 오픈 | [[근무 신청 액션시트]] | census 원문 |
| 60 | 외근 내역 취소 | Button | • 대기 외근 신청을 취소하는 행 내 버튼. 대기 외근 행에만 노출 (별도 표) • 클릭 시: 컨펌 없이 즉시 취소(대기→취소) | OffsiteWorkRecord.status (pending→cancelled) | census 검증 |
| 70 | 외근 보고서 작성 | Button | • 승인된 외근에 대한 보고서 작성을 여는 행 내 버튼. 승인 외근 행에만 노출 (별도 표) • 클릭 시: [[HBEA421_보고서 제출]] 전환 | [[HBEA421_보고서 제출]] | 승인 후 트리거 |
근무 신청 액션시트 사양표
FAB(40) 클릭 시 하단에서 올라오는 액션시트. 원문 2개 액션.
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | 조건1 [직원 인증(self)] · FAB(40) "+" 클릭 시 하단 시트로 노출 | 40 FAB | |
| 10 | 연장·휴일 근무 신청 | Button | • 연장근무 신청 폼으로 진입하는 액션. 원문 "연장·휴일 근무 신청" • 클릭 시: 연장근무 신청 폼 전환(액션시트 닫힘) | 연장근무 신청 폼 | census 원문 |
| 20 | 외근 신청 | Button | • 외근 신청 폼으로 진입하는 액션. 원문 "외근 신청" • 클릭 시: 외근 신청 폼 전환(액션시트 닫힘) | 외근 신청 폼 | census 원문 |
| 30 | 닫기(배경/제스처) | - | • 배경 탭/아래 스와이프로 시트를 닫는 동작(추정) | - | TBU: 닫힘 동작 |
연장근무 신청 폼 사양표
액션시트 "연장·휴일 근무 신청" → 연장근무 신청 폼. 제출 시 OvertimeRecord(status=pending) 생성.
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | 액션시트 "연장·휴일 근무 신청"(10) 클릭 시 노출 | 액션시트 10 | |
| 01 | 초기 상태 | Output | 폼 타이틀 "연장근무 신청", 각 필드 미입력 상태로 진입 | - | census 원문 |
| 10 | 근무일 | DatePicker | • 연장근무 실시 일자를 지정하는 필드 • 입력 시: 일자 지정. 미선택 시 제출 disabled(추정) | OvertimeRecord.workDate | census 필드 |
| 20 | 시작 시간 | TimePicker | • 연장시간 산정 기준 시작 시각 필드. 원문 "시작 시간" • 입력 시: 시작 시각 지정 | OvertimeRecord.startTime → overtimeHours | census 원문 |
| 30 | 종료 시간 | TimePicker | • 연장시간 산정 기준 종료 시각 필드. 원문 "종료 시간" • 입력 시: 연장시간 자동 계산(정책 §1) | OvertimeRecord.endTime → overtimeHours | census 원문 |
| ㄴ31 | 익일 퇴근 체크박스 | Checkbox | • "종료 시간" 라벨 우측 "익일 퇴근" 체크박스. 기본 비활성(disabled), 시작보다 이른 종료 시각 입력 시 활성+자동 체크 — 시간 계산의 +24h(익일 종료) 규칙을 확인시키는 표시 | isNextDayEnd(newOvertime) | 신설 (코드 반영: 7c2eab6) |
| ㄴ32 | 연장 시간 h:mm 표기 | Output | • "연장 시간:" 자동 계산 값을 소수 대신 h:mm(8:30)으로 표기 (기존 "N시간" 제거) | fmtHM(newOvertime.hours) | h:mm 표기 (코드 반영: 7c2eab6) |
| 40 | 유형 | Select | • 연장근무 유형을 선택하는 필드. placeholder "연장근무 유형을 선택하세요.", 옵션 예 "야간 연장" / "평일 연장-1" • 선택 시: 유형 지정. 시간 따라 자동 설정 후 직접 변경 가능(정책 §1) - 관찰: junk 옵션 노출(테스트 데이터) | [[HBAD261_유형 설정 (연장근무·외근·휴가)]] · overtime_types (typeId, multiplier) | census 원문 · TBU: 유형 0건 시 옵션 |
| 50 | 사유 | Select + Text | • 연장근무 사유를 지정하는 필드. 프리셋 5종 "업무 마감" / "긴급 대응" / "환자 응대" / "회의/교육" / "인수인계" + 자유입력 병행 • 선택/입력 시: 사유 지정 | OvertimeRecord.notes (추정) | census 원문 · TBU: 필수 여부 |
| 60 | 신청 버튼 | Button | • 연장근무 신청을 제출하는 버튼 • 클릭 시: 즉시 제출(컨펌 없음), 성공: 내역 최상단 "대기" 행 + 요약 카운트 증가 → 팀 결재(HBTM220) - CASE01 [필수 필드 미입력]: 제출 차단(추정) | overtime.request({workDate, overtimeHours, category:OvertimeCategory.WEEKDAY, startTime, endTime}) (TC 확정: 01:1.2) · OvertimeRecord(pending) | census 원문 · TBU: 제출 실패 시 토스트/무반응=버그 후보 |
외근 신청 폼 사양표
액션시트 "외근 신청" → 외근 신청 폼. 제출 시 OffsiteWorkRecord(status=pending) 생성. location NOT NULL.
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | 액션시트 "외근 신청"(20) 클릭 시 노출 | 액션시트 20 | |
| 01 | 초기 상태 | Output | 외근 신청 폼, 각 필드 미입력 상태로 진입 | - | |
| 10 | 외근일 | DatePicker | • 외근 실시 일자를 지정하는 필드 • 입력 시: 일자 지정. 미선택 시 제출 disabled(추정) | OffsiteWorkRecord.workDate | census 필드 |
| 20 | 시작 시간 | TimePicker | • 외근 시작 시각 필드. 원문 "시작 시간" • 입력 시: 시작 시각 지정 | OffsiteWorkRecord.startTime | census 원문 |
| 30 | 종료 시간 | TimePicker | • 외근 종료 시각 필드. 원문 "종료 시간" • 입력 시: 종료 시각 지정 | OffsiteWorkRecord.endTime | census 원문 |
| ㄴ31 | 익일 퇴근 체크박스 | Checkbox | • "종료 시간" 라벨 우측 "익일 퇴근" 체크박스. 연장 신청과 동일 규칙 — 기본 비활성(disabled), 시작보다 이른 종료 시각 입력 시 활성+자동 체크 | isNextDayEnd(newOffsite) | 신설 (코드 반영: 7c2eab6) |
| ㄴ32 | 외근 시간 h:mm 표기 | Output | • "외근 시간:" 자동 계산 값을 소수 대신 h:mm(8:30)으로 표기 (기존 "N시간" 제거) | fmtHM(newOffsite.hours) | h:mm 표기 (코드 반영: 7c2eab6) |
| 40 | 장소 | Text (Input Box) | • 외근 장소를 지정하는 필드. placeholder "예: 거래처 본사, 강남구청" • 입력 시: 장소 지정. 미입력 시 제출 차단(NOT NULL) | OffsiteWorkRecord.location (NOT NULL) | census 원문 |
| 50 | 유형 | Select | • 외근 유형을 선택하는 필드. Admin 외근 유형 소비 • 선택 시: 유형 지정 - 관찰: junk 옵션 노출(테스트 데이터) | [[HBAD261_유형 설정 (연장근무·외근·휴가)]] · offsite_work_types (typeId) | TBU: 유형 0건 시 옵션 |
| 60 | 사유 | Textarea | • 외근 사유를 지정하는 필드. placeholder "외근 목적을 작성해주세요.", 프리셋 5종 "거래처 방문" / "외부 미팅" / "교육/세미나" / "관공서 업무" / "물품 구매" + 자유입력 • 선택/입력 시: 사유 지정 | OffsiteWorkRecord.reason (추정) | census 원문 |
| 70 | 신청 버튼 | Button | • 외근 신청을 제출하는 버튼 • 클릭 시: 즉시 제출(컨펌 없음), 성공: 내역 최상단 "대기" 행 + 요약 카운트 증가 → 팀 결재(HBTM220) - CASE01 [필수 필드(외근일/장소 등) 미입력]: 제출 차단(NOT NULL location) | attendance.registerFieldWork({date, startTime, endTime, location, notes}) (TC 확정: 01:1.13) · OffsiteWorkRecord(pending) | census 원문 · TBU: 제출 실패 시 토스트/무반응=버그 후보 |
외근 내역 취소·보고서 작성 사양표
내역 리스트(30) 행 내 액션 버튼. 상태별로 취소(대기) / 보고서 작성(승인) 노출.
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | 조건1 [직원 인증(self)] · 본인 외근 내역 행 | OffsiteWorkRecord (self) | |
| 10 | 외근 내역 취소 | Button | • 대기 외근 신청을 취소하는 행 내 버튼. 원문 "취소". 정책 §2.1 승인 전 앱 즉시 취소 • 클릭 시: 컨펌 없이 즉시 취소, 성공: 상태 대기→취소(cancelled) + "취소" 버튼 소멸 - CASE01 [status=pending]: 노출 - CASE02 [승인/반려/취소]: 미노출 | OffsiteWorkRecord.status (pending→cancelled) · sdk.fieldwork.cancel() (추정) | census 검증 · TBU: 취소 실패 무반응 |
| 20 | 외근 보고서 작성 | Button | • 승인된 외근의 보고서 작성을 여는 행 내 버튼. 원문 "외근 보고서 작성" • 클릭 시: [[HBEA421_보고서 제출]] 전환 - CASE01 [status=approved]: 노출(팀장 승인 후, HBTM220) - CASE02 [승인 전]: 미노출 | [[HBEA421_보고서 제출]] · [[HBTM220_근무 관리 (연장·휴일/외근)]] | 승인 후 트리거 · TBU: 전환 실패 무반응 |
권한·상태 분기 요약
| 시나리오 | 트리거 | 결과 | 비고 |
|---|---|---|---|
| 조건1 [직원 인증(self)] | 근무 서브탭 진입 | 근무 신청 화면 노출 | 미인증 hide |
| CASE01 [status=pending] | 연장/외근 "신청" 제출 | 내역 "대기" 행 + 요약 카운트 증가 → 팀 결재 | HBTM220 결재 대상 |
| CASE02 [승인 전 취소] | 외근 대기 행 "취소" 클릭 | 즉시 취소(대기→cancelled), 버튼 소멸 | 컨펌 없음, 연장도 정책상 Work 취소 가능(UI 확인 TBU) |
| CASE03 [status=approved] | 팀장 승인 | 외근 행에 "외근 보고서 작성" 노출 | HBTM220 승인 후 |
| CASE04 [status=rejected] | 팀장 반려 | "반려" 배지 | 재신청 경로 TBU |
| CASE05 [취소 요청] | 승인 후 취소 요청 | 결재자 취소 승인 → 취소 상태 유지 | 정책 approval.md §3.1/§4.3 (연장 기준; 외근 UI 노출 TBU) |
| 조건2 [보고서 승인] | 보고서 결재 승인 | 근태/급여 반영 | [[HBEA421_보고서 제출]] |
Open Question
- 연장/외근 내역 리스트 행 컬럼 상세(유형·시간·사유·상태 배지 배치)와 필터별 Empty 문구 분화 여부. TBU.
- 연장 신청 category =
OvertimeCategory(예WEEKDAY) 확정 (TC: 01:1.2). 유형 "평일 연장-1" ↔ overtime_types 매핑 및 휴일 유형 별도 여부 = TBU. - 사유 프리셋 선택값 저장 컬럼(
notesvs 별도) 및 자유입력 병행 저장 방식. TBU. - 연장 내역 승인 전 앱 취소 버튼(정책 §2.1 Work 취소)의 UI 노출 여부 — 외근은 검증됨, 연장은 라이브 미확인. TBU.
- 승인 후 취소 요청(정책 §3.1)의 EA UI 노출 여부(외근 포함). TBU.
- 신청 제출/취소 실패 시 에러 처리(토스트 vs 무반응). TBU — 무반응이면 버그 후보.