연차 관리
- 대상 사용자 : 인사 관리자
- 화면의 목적 : 연차 항목을 설정하며, 각 직원의 남은 연차와 연차 규칙 설정을 위한 화면
연차 현황(탭)
1️⃣ 필터링
- 연도
- 옵션: 현재 연도 기준 최근 5개 연도 (예: 2026년 ~ 2022년)
- 기본: 현재 연도
- 동작: 선택 연도 말일(
{연도}-12-31) 기준으로 부여·사용·잔여를 산정
- 소속
- 멀티셀렉트 드롭다운
- 기본: 전체 (미선택)
- placeholder:
소속 선택 - 선택한 팀 중 하나라도 소속된 직원만 표시
- 비활성 팀은 목록에 노출하지 않음 (공통정책)
- 선택 해제(X) 시 필터 초기화 후 목록 갱신
- 검색
- 위치: 필터 영역 오른쪽 (공통정책: 필터 왼쪽 · 버튼/검색 오른쪽)
- placeholder:
사번 / 이름 / 이메일 - 검색 결과 없음:
검색 결과가 없어요.
- 조회 대상 직원
- 재직 상태인 직원만 표시 2️⃣ 요약 통계
- 필터 아래, 표 위에 고정 노출. 필터 결과에 따라 함께 갱신.
| 항목 | 표시 예 | 설명 |
|---|---|---|
| 대상 인원 | 42명 | 현재 필터 조건에 해당하는 직원 수 |
| 평균 사용 | 7.2일 | 대상 인원의 사용일수 평균 (소수 1자리) |
| 평균 잔여 | 7.8일 | 대상 인원의 잔여일수 평균 (소수 1자리) |
- 대상 0명일 때:
0명/0일/0일
3️⃣ 리스트뷰
- 레이아웃
- 상단(사번, 이름, 소속, 입사일, 총 부여, 사용, 잔여, 사용률, 산정기준) 고정
- 표 본문만 세로 스크롤
- 페이지 하단에 페이지네이션 노출
- 정렬
- 기본: 성 → 이름 오름차순
| 사번 | 이름 | 소속 | 입사일 | 부여일수 | 사용일수 | 잔여일수 | 사용률 | 산정 기준 |
|---|---|---|---|---|---|---|---|---|
| ADMIN003 | 홍길동 | 개발팀 | 2024.03.01. | 15일 | 8일 | 7일 | ████░░ 53% | 입사일 기준 |
- 컬럼 정의
- 사번: 없으면
- - 이름: 말줄임 + hover 시 전체 이름
- 근무 미배정 경고 (2026-09-14 기준 변경) — 이름 옆 주황 경고 아이콘
- 근무 그룹과 근무 형태가 둘 다 없는 직원에게만 띄운다. 조직 기본 소정근로시간으로 연차를 환산하고 있다는 뜻이다
- 근무 그룹은 있는데 그룹 안 형태마다 시간이 달라(3교대 · 요일별 근무) 조직 기본으로 환산하는 직원은 정상이므로 띄우지 않는다. 그전에는 이들에게도 떠서 파일럿 데이터 기준 126명이 경고 대상이었다(고친 뒤 1명)
- 툴팁 : 근무 그룹·근무 형태가 배정되지 않아 조직 기본 소정근로시간({n}시간)으로 연차를 환산해요. / 클릭하면 이 자리에서 바로 근무를 배정할 수 있어요.
- 누르면 그 직원의 근무 배정 팝업이 열린다 — 직원 관리로 건너가지 않고 이 자리에서 배정한다
- 근무 미배정 경고 (2026-09-14 기준 변경) — 이름 옆 주황 경고 아이콘
- 소속: 첫 번째 활성 팀명, 없으면
- - 입사일:
YYYY.MM.DD.형식 - 부여일수:
{n}일— 선택 연도 기준 부여된 연차 - 사용일수:
{n}일— 승인된 휴가 중 연차 차감 일수 합계 - 잔여일수:
{n}일— 굵게 표시 - 사용률: 프로그레스 바
- 산정 기준: 배지 — 목록이 보여주는 기준. 기본은 조직 적용 기준이고, 「산정 기준 보기」로 반대 기준을 고르면 참고 환산값에
(참고)가 붙음 (참고 기준 환산)입사일 기준(hire_date) — 기본값회계연도 기준(fiscal_year)- 「전환 기준」 배지는 없음 — 날짜에 따라 기준이 자동으로 바뀌는 동작은 2026-09-14에 폐기됨 (연차 산정 기준 참고)
- 사번: 없으면
- 데이터가 없을 때
- 문구 :
데이터가 없어요.
- 문구 :
부여 기준(탭)
1️⃣ 상단 영역
- [규칙 추가] 버튼 (오른쪽)
- 공통정책으로 인해 오른쪽에 위치
- 클릭 시 부여 기준 추가 모달 제공 (4️⃣ 참고) 2️⃣ 기본 규칙 등록 배너 안내 문구와 표 사이에 주황색 안내 박스로 노출.
| 구성 | 내용 |
|---|---|
| 안내 문구 | 근로기준법 제60조 기본 연차규칙을 일괄 등록해요. (입사 1년 미만 월별발생, 1~3년 15일, 3년 이상 근속가산) |
| 버튼 | [기본 규칙 등록] |
- [기본 규칙 등록] 클릭 시 확인 팝업
- title: 기본 연차규칙 등록
- message:
근로기준법 기본 연차규칙을 등록할까요? (기존 규칙은 유지돼요) - 버튼
- [취소], x 버튼: 팝업만 닫힘
- [확인] 버튼 : 아래 12개 기본 규칙을 순서대로 등록 + 해당 팝업 닫힘
- 기존 규칙은 삭제·덮어쓰지 않음
- 동일 규칙이 이미 있으면 해당 건은 건너뜀
등록되는 기본 규칙 (12건)
| # | 근속연수 | 부여일수 | 발생유형 | 최대일수 | 설명 |
|---|---|---|---|---|---|
| 1 | 0년 ~ 1년 미만 | 11일 | 월별 발생 | 11일 | 입사 1년 미만: 매월 1일 발생 (최대 11일) |
| 2 | 1년 ~ 3년 미만 | 15일 | 연간 부여 | - | 1~3년: 연 15일 |
| 3 | 3년 ~ 5년 미만 | 16일 | 연간 부여 | - | 3~5년: 연 16일 (2년 초과 시 1일 가산) |
| 4 | 5년 ~ 7년 미만 | 17일 | 연간 부여 | - | 5~7년: 연 17일 |
| 5 | 7년 ~ 9년 미만 | 18일 | 연간 부여 | - | 7~9년: 연 18일 |
| 6 | 9년 ~ 11년 미만 | 19일 | 연간 부여 | - | 9~11년: 연 19일 |
| 7 | 11년 ~ 13년 미만 | 20일 | 연간 부여 | - | 11~13년: 연 20일 |
| 8 | 13년 ~ 15년 미만 | 21일 | 연간 부여 | - | 13~15년: 연 21일 |
| 9 | 15년 ~ 17년 미만 | 22일 | 연간 부여 | - | 15~17년: 연 22일 |
| 10 | 17년 ~ 19년 미만 | 23일 | 연간 부여 | - | 17~19년: 연 23일 |
| 11 | 19년 ~ 21년 미만 | 24일 | 연간 부여 | - | 19~21년: 연 24일 |
| 12 | 21년 이상 | 25일 | 연간 부여 | - | 21년 이상: 연 25일 (법정 최대) |
3️⃣ 리스트뷰
| # | 근속연수 | 부여일수 | 발생유형 | 최대일수 | 상태 | 설명 | 관리 |
|---|---|---|---|---|---|---|---|
| 1 | 0년 ~ 1년 미만 | 11일 | 월별 발생 | 11일 | 활성 | 입사 1년 미만: 매월 1일 발생 (최대 11일) | ✏️ 🗑️ |
| 2 | 1년 ~ 3년 미만 | 15일 | 연간 부여 | - | 비활성 | 1~3년: 연 15일 | ✏️ 🗑️ |
- 컬럼 정의
- #: 목록 순번 (1부터)
- 근속연수:
{시작}년~{끝}년 미만/ 끝 값 없으면{시작}년 이상 - 부여일수:
{n}일— 굵게, 주황색 - 발생유형: 배지
월별 발생: 노란 배지연간 부여: 청록 배지
- 최대일수:
{n}일/ 없으면- - 설명: 말줄임, 없으면
- - 관리: 아이콘 버튼만 (공통정책)
- [수정] 버튼
- 수정 팝업 제공(4️⃣ 관리 버튼>③ 부여 기준 추가 / 수정 모달 참고)
- [삭제] 버튼 (4️⃣ 관리 버튼>② [삭제] 버튼 과 동일)
- [수정] 버튼
- 상태
- 활성 : 부여기준으로 연차가 발생
- 비활성 : 부여기준으로 연차 발생하지 않음
- 상태 변경
- 비활성 → 활성
- 조건이 중복되는 부여기준의 경우, 먼저 적용된 규칙만 유지한다.
- 활성 → 비활성
- 이미 해당 조건으로 연차가 부여된 경우 연차 수를 변경하지 않는다.
- 비활성 → 활성
- 빈 목록일 때
- 표 중앙:
등록된 연차 부여기준이 없어요. 부여 기준을 추가해 주세요.4️⃣ 관리 버튼 ① [수정] 버튼
- 표 중앙:
- 클릭 시 부여 기준 수정 모달 (추가 모달과 동일 필드, 기존 값 채움)
- title:
부여 기준 수정
② [삭제] 버튼
- 부여 기준이 활성 상태일 때
- title:
삭제 - message:
부여 기준을 삭제할 수 없어요. 먼저 비활성 상태로 변경한 뒤 삭제할 수 있어요. - 버튼: [확인]
- 팝업만 닫힘
- title:
- 부여 기준이 상태 비활성 + 연결된 연차 부여 있음
- title:
삭제 - message:
이 유형을 부여한 연차가 있어요. 삭제하면 {부여 기준 이름} 기준으로 부여된 연차는 다시 계산돼요. - 버튼
- [취소], [X]: 팝업만 닫힘
- [확인] : 부여 기준 삭제 + 팝업 닫힘 + 적용되 기준 중 가장 오래된 것 적용
- title:
- 부여 기준이 상태: 비활성 + 연결된 연차 내역 없음
- title:
삭제 - message:
{부여 기준 이름} 연차 부여 기준을 삭제할까요? - 버튼
- [취소], [X]: 팝업만 닫힘
- [확인] : 부여 기준 삭제 · 팝업 닫힘 · 목록 갱신 +
휴가 규칙을 삭제했어요.토스트
- title:
③ 부여 기준 추가 / 수정 모달
- title
- 추가:
부여 기준 추가 - 수정:
부여 기준 수정
- 추가:
- 모달 규칙: 배경 클릭으로 닫히지 않음 · [X] / [취소]로만 닫힘
- 필수 값인 경우 필드 이름 옆에
*표시
| 필드 | 필수 | 기본값 (추가 시) | 설명 |
|---|---|---|---|
| 이름 | O | 빈칸 | placeholder : 회계년도 연차 발생 |
| 근속연수 시작 (이상) | O | 0 | 0 이상 정수 |
| 근속연수 끝 (미만) | X | 빈칸 | 빈칸 = 무제한 · placeholder: 무제한 |
| 부여일수 | O | 15 | 0 이상, 0.5 단위 입력 가능 |
| 발생유형 | O | 연간 부여 | 드롭다운: 연간 부여 / 월별 발생 |
| 최대일수 (월별 발생 시 상한) | X | 빈칸 | 발생유형 = 월별 발생일 때만 노출 · placeholder: 제한 없음 |
| 설명 | X | 빈칸 | 최대 200자 · placeholder: 예: 근로기준법 제60조 기준 |
| 상태 | O(단 필수 표시 하지 않음) | 활성 | 옵션 : 활성, 비활성 |
상태 툴팁 (필드 옆 ⓘ · hover)
추가 모달
비활성상태일 때 :비활성 상태로 추가하면 규칙이 적용되지 않아요.활성상태일 때 :활성 상태로 추가하면 규칙이 바로 적용돼요. 다른 규칙이 적용된 경우 적용되지 않아요.
수정 모달
비활성상태일 때 :활성 상태로 변경하면 규칙이 바로 적용돼요. 다른 규칙이 적용된 경우 적용되지 않아요.활성상태일 때 :비활성 상태로 변경해도 이미 적용된 경우 변경되지 않아요.
푸터 버튼
- [취소], x 버튼: 저장 없이 모달만 닫힘
- [저장]
- 클릭 시 저장 · 모달 닫힘 · 목록 갱신
- 추가된 목록의 경우 최상단에서 보이도록 수정
- 추가:
휴가 규칙을 추가했어요.토스트 - 수정:
휴가 규칙을 수정했어요.토스트
- 클릭 시 저장 · 모달 닫힘 · 목록 갱신
휴가 유형(탭)
1️⃣ 필터링(추가기능)
- 상태
- 옵션 : 전체, 활성, 비활성
- 기본 : 전체
2️⃣ [휴가 추가] 버튼
리스트 뷰 위쪽에 오른쪽에 위치함(공통정책)
버튼을 누르면 '휴가 유형' 팝업 제공
휴가 유형 추가 팝업
- title : 휴가 유형
- 이름
- 입력란
- 필수입력 표시 (
*) - placeholder : 연차, 반차, 경조 휴가 등
- 시간
- 입력란
- placeholder : 0
- 단위 : 시간
- 소수점 둘째자리까지 입력
- 차감 일수
- 입력란
- placeholder : 0
- 단위 : 일
- 0.5 단위 입력 가능
0이면 연차 잔여에서 차감하지 않음 (예: 경조 휴가)
- 신청 단위 (2026-09-14 추가 — 저장 필드
deductionKind)- 라디오 : 하루 단위(기본) / 시간 단위
- 하루 단위(
rate) : 신청한 날마다 「시간 설정」만큼 차감 — 종일 8시간 · 반차 4시간 같은 고정 유형 - 시간 단위(
hourly) : 직원이 신청할 때 사용 시간을 30분 단위로 고름. 상한은 본인의 1일 소정근로시간(근무 형태workHours, 없으면 조직 기본값), 고른 분(requestedMinutes)이 그대로 차감량 — 연차 정책 「휴가 유형마다 차감량을 다르게 할까요?」 설정과 무관하게 존중됨 - 시간 단위에서 「시간 설정」은 「기본 사용 시간」(
defaultMinutes) — works 신청 폼 초기값이고 직원이 바꿀 수 있음 - works 는
deductionKind === "hourly"일 때만 「사용 시간」·「시작 시간」 입력과 「2시간 = 0.25일 차감」 미리보기를 보여줌 - 수정 저장 시 저장된 신청 단위를 그대로 유지함(예전 폼은 이 축이 없어 시간 단위 유형이 하루 단위로 덮어써졌음)
- 설명(추가)
- 입력란
- placeholder : 일반 휴가
- 스케줄러 연동 체크 박스
- 툴팁 : 체크하면 스케줄러에서 해당 휴가 유형을 사용할 수 있어요.
- 체크박스 선택하면 해당 휴가 유형 스케줄러에서 선택할 수 있도록 제공됨
- 코드
- 필수입력 표시 (
*) - 입력란
- placeholder : D, E, N 등
- 필수입력 표시 (
- 코드 라벨 색상
- 새 휴가 유형 생성 시 사용 가능한 색상을 순차적으로 자동 선택
- 표는 Hereby sign에서 가져온 값임
# 색상 HEX 1 오렌지 #F660142 연두 #A3C75A3 하늘 #A0D3F94 핑크 #F2C7E35 네이비 #26426B6 블루 #2463EB7 퍼플 #826AED8 레드 #E632249 다크그린 #0F662510 브라운 #A2812D11 옐로우 #F09C0012 틸 #00A19D13 테라코타 #B5523914 다크브라운 #71383815 그레이 #B8B8B8- 사용자는 원하는 색상으로 변경 가능 - 모든 색상을 사용한 경우 처음 색상부터 다시 순환하여 선택 - 색상을 사용자가 선택할 수 있도록 진행- 상태
- 드롭다운
- 기본 : 활성
- 옵션 : 활성, 비활성
- 비활성인 경우 Works(mobile) 휴가 신청에서 해당 유형 보이지 않음
- 기존 신청·승인·반려·취소 건의 유형·차감 일수는 변경하지 않음
- 버튼
- [취소], [X]: 저장 없이 팝업만 닫힘
- [저장]
- 활성화: 필수 항목 입력 후 활성화됨
- 클릭: 저장 후 팝업 닫힘 · 목록 갱신 · 추가한 행은 목록 상단으로 이동 3️⃣ 리스트 뷰
| 이름 | 설명 | 코드 | 시간 | 차감 일수 | 스케줄러 연동 | 상태 | 관리 |
|---|---|---|---|---|---|---|---|
| 연차 | 일반 연차 | AL | 8시간 | 1일 | 사용 | 활성 | ✏️ 🗑️ |
| 반차 | 일반 반차 | HD | 4시간 | 0.5일 | 사용 | 활성 | ✏️ 🗑️ |
| 경조 휴가 | 경조사로 인해 사용하는 휴가, 사전 합의 필요 | EV | 8시간 | 0일 | 미사용 | 활성 | ✏️ 🗑️ |
- 컬럼 정의
- 이름 : 휴가 유형 이름 · 말줄임 + hover 시 전체 이름
- 설명 : 없으면
-· 말줄임 - 코드 : 등록된 코드 문자열 (예:
AL,HD)- 배경색 : 등록된 HEX 색상 (
코드 라벨 색상팝업과 동일) - 글자색 : 배경 대비 가독성에 따라 자동(밝은 배경 → 진한 글자, 어두운 배경 → 밝은 글자)
- 배경색 : 등록된 HEX 색상 (
- 시간 :
{n}시간· 소수 둘째 자리까지 (예:8시간,4.00시간) - 차감 일수 :
{n}일· 0.5 단위 (예:1일,0.5일,0일) - 스케줄러 연동 :
사용/미사용배지 - 상태 :
활성/비활성배지 - 관리 : 아이콘 버튼만 (공통정책)
- [수정] · [삭제]
- [수정] 버튼
- 클릭하면 휴가 유형 수정 팝업 제공
- title : 휴가 유형
- 필드는 휴가 유형 추가 팝업과 동일
- 활성 → 비활성 저장 시 확인 팝업
- title : 휴가 유형 비활성화
- message :
이 휴가 유형을 비활성화할까요? 비활성화하면 Works에서 새 휴가 신청 시 선택할 수 없어요. 이미 신청·승인된 휴가는 그대로 유지돼요. - [취소] : 팝업만 닫힘 · 상태 변경 없음
- [확인] : 비활성 저장 · 팝업 닫힘 · 목록 갱신
- [삭제] 버튼
- 활성 상태일 때 (2026-09-17 변경 — 「활성은 삭제 불가」 규칙은 유지하고 안내를 실행 가능한 형태로)
- title:
삭제 - message:
'{이름}' 휴가 유형은 활성 상태라 바로 삭제할 수 없어요./지금 비활성으로 바꿀까요? 비활성으로 바꾸면 Works에서 새 휴가 신청 시 선택할 수 없고, 이미 신청·승인된 휴가는 그대로 유지돼요./바꾼 뒤 삭제를 다시 누르면 삭제할 수 있어요. - 버튼
- [취소], [X]: 팝업만 닫힘 · 상태 변경 없음
- [비활성으로 변경] : 비활성 저장 · 팝업 닫힘 · 목록 갱신 +
'{이름}' 휴가 유형을 비활성으로 바꿨어요. 이제 삭제할 수 있어요.토스트
- 이 창에서 삭제까지 하지 않는다 — 비활성으로 바꾼 뒤 [삭제]를 다시 눌러야 삭제 확인으로 넘어간다. 「비활성으로 변경」을 누른 사람이 삭제까지 당하지 않게 두 단계를 유지한다.
- 이전 동작:
휴가 유형을 삭제할 수 없어요. 먼저 비활성 상태로 변경한 뒤 삭제할 수 있어요.+ [확인] 하나뿐이라, 사용자가 수정 팝업의 상태 드롭다운을 직접 찾아가야 했다(CS-OKBEST-260917-0003 「휴가 연차유형 삭제 안됨」).
- title:
- 상태 비활성 + 연결된 휴가 내역 있음
- title:
삭제 - message:
이 유형을 사용한 휴가 내역이 있어요. 삭제하면 해당 휴가 내역의 유형은 **삭제**로 표시돼요. - 버튼
- [취소], [X]: 팝업만 닫힘
- [확인] : 유형 삭제 + 팝업 닫힘 + 해당 유형 사용한 휴가 내역의 유형을 '삭제'로 표시
- title:
- 상태: 비활성 + 연결된 휴가 내역 없음
- title:
삭제 - message:
{이름} 휴가 유형을 삭제할까요? - 버튼
- [취소], [X]: 팝업만 닫힘
- [확인] : 유형 삭제 · 팝업 닫힘 · 목록 갱신
- title:
- 활성 상태일 때 (2026-09-17 변경 — 「활성은 삭제 불가」 규칙은 유지하고 안내를 실행 가능한 형태로)
- 빈 목록일 때
- 표 중앙 :
등록된 휴가 유형이 없어요. 휴가 유형을 추가해 주세요.
- 표 중앙 :
연차/휴가 결재(탭)
1️⃣ 필터링
- 상태
- 옵션 : 전체, 대기, 승인, 반려, 취소
- 기본 : 전체
- 기간
- 적용 기간(시작일~종료일) 기준 조회
2️⃣ 리스트뷰
| 사번 | 이름 | 유형 | 적용기간 | 차감 일수 | 사유 | 상태 | 관리 |
|---|---|---|---|---|---|---|---|
| ADMIN003 | 홍길동 | 연차 | 2026.06.10. ~ 2026.06.12. | 3 | 가족 행사 | 대기 | [보기] 버튼 |
- 컬럼
- 사번 : 없으면
- - 이름
- 유형 : 휴가 유형 탭에 등록된 이름 · 삭제된 유형은
삭제 - 적용기간 :
YYYY.MM.DD. ~ YYYY.MM.DD.· 시작일=종료일이면 하루 - 사유 : 없으면
-· 말줄임 - 상태 :
대기/승인/반려/취소
- 사번 : 없으면
- 빈 목록 :
휴가 신청 내역이 없어요.
3️⃣ [보기] 버튼
- 휴가 상세 팝업 제공
- ① 대기 상태일 때 '휴가 상세' 팝업
- 휴가신청서
- 직원 :
- 유형 :
- 적용 기간 : 2026.06.10. ~ 2026.06.12.
- 차감 일수 :
- 반차인 경우 0.5로 표시
- 소수점 둘째자리까지 표시 가능
- 사유 : {가족 행사} / 없으면
-
- 푸터 버튼
- [승인]
- 사유 입력: 불필요
- 동작
- 상태 변경되고 모든 팝업 닫힘
- 상태 : 대기 → 승인
- 결재자, 결재 일시 기록
- 연차 현황 사용일수·잔여일수 반영
- [반려]
- 반려 사유 입력 팝업 제공
- title : 휴가 반려
- 사유입력
- 필수 표시 (
*) - 입력란
- placeholder :
반려사유를 입력해 주세요.
- 필수 표시 (
- 버튼
- [취소] : 휴가 반려 팝업만 닫힘
- [확인] 버튼
- 반려 사유를 입력해야 버튼 활성화됨
- 버튼 클릭하면 반려로 변경되고 모든 팝업 닫힘
- 반려 사유 입력 팝업 제공
- [승인]
- 휴가신청서
- ② 반려 상태일 때 '휴가 상세' 팝업
- 휴가 신청 내역과 반려 내역 제공
- 휴가 신청 내역은 '휴가신청서'와 동일
- 반려 내역
- 결재자 :
- 결재 일시 : 2026.06.11. 오후 02:30:00
- 사유 :
- 푸터 버튼
- [확인] : 해당 팝업 닫힘
- ③ 승인 상태일 때 '휴가 상세' 팝업
- 휴가 신청 내역과 승인 내역 제공
- 휴가 신청 내역은 '휴가신청서'와 동일
- 승인 내역
- 결재자 :
- 결재 일시 : 2026.06.11. 오후 02:30:00
- 사유 :
-(승인 시 사유 없음)
- 푸터 버튼
- [확인] : 해당 팝업 닫힘
- ④ 취소 상태일 때 '휴가 상세' 팝업
- 휴가 신청 내역 제공 (휴가신청서와 동일)
- 취소 내역
- 처리자 : {성이름(사번)} 또는
- 처리 일시 : 2026.06.11. 오후 03:00:00
- 사유 :
- 푸터 버튼
- [확인] : 해당 팝업 닫힘
- ① 대기 상태일 때 '휴가 상세' 팝업
연차 사용촉진(annual-leave-promotion)
근로기준법 제61조 연차 사용촉진 워크플로는 이 화면과 별도로 구현돼 있어요. 상세 상태·프로시저는 연차 사용촉진 문서를 참고해 주세요. (요약: 관리자가 잔여 연차 보유 직원에게 메신저로 1차 안내 + hereby Sign 연차 사용계획서를 발송 → 기본 10일 내 미서명 시 자동 취소 → 2차 시기 지정.)
과거 연차 내역 일괄 업로드
기존 근태 시스템(eCount 등)에 쌓인 사용 이력을 hereby 로 옮기는 기능이에요. 연차 현황 우측 상단 「업로드」 로 열어요. 다른 병원 온보딩에도 반복되는 요구라 Admin 기능으로 두었어요.
1️⃣ 흐름 — 직원 대량 업로드와 같은 계약
- 템플릿 다운로드 → 파일 선택(
.xlsx/.xls/.csv, 최대 20,000행) → 미리보기 → 근태종류 매핑·퇴사자 처리 선택 → 검증 → 오류 0건일 때만 [확인] 활성 → 저장(All-or-Nothing). - 부분 저장 옵션: 검증 오류가 있을 때 「오류 행은 건너뛰고 나머지만 저장해요」를 켜면 오류 행을 제외한 나머지만 저장돼요(
skipInvalidRows). 건너뛴 행과 사유는 배치summary.skippedErrors(앞 500건)에 남고 이관 내역 표의 「건너뜀」 열에 수가 보여요. 그 행만 파일에서 고쳐 다시 올리면 나머지는 「이미 이관된 행」으로 막히고 새 행만 저장돼요. 저장할 수 있는 행이 0이면 [확인]은 비활성. - 파일은 tRPC(JSON) 라 base64 로 보내고, 파싱·검증·저장은 전부 서버(
leave-import.service)가 해요.
2️⃣ 파일 형식 — 헤더로 자동 판별(어댑터)
| 형식 | 헤더 | 비고 |
|---|---|---|
| hereby 템플릿 | 사번 * · 사원명 · 근태종류 * · 시작일 * · 종료일 · 차감 * · 사유 | 종료일 비우면 시작일과 같음. 차감은 일수(0.5 = 반차, 시간 단위는 일 근무시간으로 나눈 값) |
| eCount 근태현황 내보내기 | 전표일자 · 부서명 · 직급 · 사원번호 · 사원명 · 근태종류 · 근태 · 적요(근태기간) · 적요 | 제목 행·합계 행·출력 시각 꼬리 행은 무시. 적요(근태기간)의 40여 표기를 파싱(parseEcountPeriod) |
- eCount 규칙: 시작·종료일은 적요(근태기간)에서(
2026-9-23,26-1-20,2021-11-02 ~ 05,2024-12-22~12-23,2026-8-28~30(3)), 쉼표 나열(2026-3-11,17(2))은 행을 나누고 근태 일수를 균등 배분, 괄호 일수와 근태 열이 다르면 근태 열 기준 + 경고, 사번은 대소문자 무시, 셀 끝 탭 제거. - 새 형식은
leave-import-parse.ts에 detect + adapt 함수 하나씩만 더해요.
3️⃣ 저장 규칙
- 모든 행을
leave_requests에 승인 완료 +source = import+importBatchId+importedDays(파일 일수 원값) 로 저장해요. 상세 팝업 사용 내역에 「이관」 배지로 전 기간이 보여요. - 원장 USE 는 직원의 현재 연차 기간에 속한 행 + 차감 유형(잔여 미차감 아님) 만 게시해요(
sourceType = leave_import,sourceId = 신청 id). 현재 기간은 오늘 날짜의 산정 기준(leavePeriodKey)으로 판정하고, 과거 기간 행은 조회·퇴직 정산 보존용으로만 남아요. 분 환산은 직원별 소정근로시간이에요. - 근태종류 → 휴가 유형 매핑은 업로드 때 고르고(이름이 같으면 자동 제안) 배치에 저장돼요. 잔여 미차감 유형(공가·병가·조퇴 등)으로 연결한 행은 이력만 남아요.
- hereby 에 없는 사번(퇴사자)은 업로더가 고른 정책으로 처리해요: 퇴사자 계정 생성(기본 — 퇴사 상태, 로그인 수단·이메일·휴대폰 없음, 성 1자 분리, 입사일 = 파일의 가장 이른 날짜, 팀은 부서명이 일치할 때만) / 건너뛰기 / 오류.
- 같은 직원·시작일·유형·일수의 이관 행이 이미 있으면 중복 오류 → 같은 파일을 두 번 올려도 이중 차감되지 않아요.
3️⃣-b 시트에서 바로 반영 — 「연차 신청 리스트」 양식
- 병원이 연차 신청을 시트로 관리하면, 시스템 양식 「연차 신청 리스트」(근태 ▸ 연차, slug
leave_request_list)로 시트를 만들고 hr-system 데이터 ▾ 「연차 내역으로 반영」 으로 같은 파이프라인에 태워요. 열은 hereby 템플릿과 같아요(사번 * · 사원명 · 근태종류 * · 시작일 * · 종료일 · 차감 * · 사유). 사번은 리터럴이라 엑셀에서 통째로 붙여넣을 수 있어요. - 프로시저
leaveImport.previewSheet / runSheet(입력sheetViewId). 서버가 시트 행을 읽어(resolveSheetRows) 템플릿 표로 바꾸고 파일과 같은 매핑·검증·저장을 해요. 배치format = sheet, 파일명 자리에는 시트 이름. - 파일 업로드와 다른 점 하나: 이미 이관된 행은 오류가 아니라 조용히 건너뛰어요(
existingRowsPolicy = skip). 누적 시트를 매달 다시 반영해도 새 행만 들어가고 이중 차감이 없어요. 오류 메시지의 「N행」은 시트의 N-1번째 행이에요. - 권한 분리: 시트 편집은 시트 접근 권한(editor)으로, 반영은
leave_request:update(연차 조정과 같은 권한)로 갈려요. 그래서 팀원이 시트를 채우고 담당 과장만 반영하는 운영이 가능해요. 비공개 시트는 만든 사람만 반영할 수 있어요. 되돌리기는 admin 연차 현황 ▸ 업로드 ▸ 이관 내역에서 배치 단위로 해요.
4️⃣ 되돌리기 — 배치 단위
- 원장은 append-only 라 USE 를 상쇄 항목으로 되돌리고, 신청은 취소 처리(사유 「과거 내역 이관 되돌리기」), 이 배치가 만든 퇴사자 계정은 다른 이관 행이 없을 때만 soft delete 해요.
- 배치 표(
leave_import_batches)에 파일명·행 수·차감 행 수·업로더·상태(적용됨/되돌림)가 남아요.
5️⃣ 검증 오류 메시지 예
5행: 근태종류 "조퇴" 에 연결할 휴가 유형을 골라 주세요.
12행: 사번 bestrhxx01 직원이 없어요. 퇴사자 처리 방식을 바꾸거나 직원을 먼저 등록해 주세요.
40행: 적요(근태기간) "2026-3-11,17~20" 을(를) 날짜로 읽을 수 없어요.
88행: 이미 이관된 행이에요 (bestrhsu31 2026-09-14 연차 1일).연차 산정 기준 (입사일 / 회계년도)
연차를 어느 기간 단위로 부여하고 잔여를 셀지를 정하는 축이에요. 조직마다 하나를 쓰고, 관리자가 적용 시작일을 정해 예약하기 전에는 절대 바뀌지 않아요. 바뀌는 시점과 바꾼 사람은 이력으로 남아요.
1️⃣ 기준은 관리자가 "언제부터"를 정해 예약한다
- 저장 위치:
leave_accrual_basis_changes(append-only 이력표). 열: 새 기준basis(hire_date/fiscal_year) · 적용 시작일effectiveFrom· 예약 시점 회계일 스냅샷fiscalYearStart· 신규 입사자 부여 방식newHireMode· 메모 · 예약자 · 취소 일시/취소자 · 전환 정산 완료 시각appliedAt. - 행이 하나도 없으면 입사일 기준(기본값). 조직 설정(
settings)에는 기준값이 없어요 — 회계일settings.fiscalYearStart("MM-DD", 기본 01-01)만 있어요. - 판정은 항상 계산 대상 날짜로 해요(
resolveLeaveBasisAt): 취소되지 않은 행 중 적용 시작일이 그 날짜 이하인 것 가운데 가장 최근 행. 그래서 과거 날짜의 신청·원장은 그 당시 기준에, 이후는 새 기준에 귀속돼요. - 지정 화면: 근태 현황 → 연차 → 「유형·기준 관리」 → 「연차 부여 기준」 상단 「적용 기준」 영역의 「기준 변경 예약」. 현재 기준과 예약된 변경(적용 시작일·예약자)이 함께 보이고, 도래 전에는 취소할 수 있어요. 이력은 같은 자리에서 펼쳐 봐요.
- 코드에는 기준을 정하는 날짜·조건이 없어요. 날짜가 되면 자동으로 회계년도로 넘어가던 구
FISCAL_YEAR_TRANSITION(2027-01-01)과 「전환 기준(transition)」 정책값은 2026-09-14에 폐기했어요.
2️⃣ 예약 제약
- 적용 시작일은 오늘 이후(오늘 포함)만 돼요. 도래 전 예약은 한 번에 하나예요.
- 회계년도 기준은 회계일부터만 시작할 수 있어요(첫 회계 기간이 온전해야 이월 정산이 맞아요). 입사일 기준으로 되돌리는 것은 어느 날짜든 돼요.
- 적용 시작일 전날에 이미 같은 기준이면 예약할 수 없어요.
- 회계년도 기준을 예약할 때는 신규 입사자 부여 방식(3️⃣)을 함께 골라요.
3️⃣ 두 기준의 동작
| 항목 | 입사일 기준 (hire_date) | 회계년도 기준 (fiscal_year) |
|---|---|---|
| 기간 | 입사기념일 창 — 입사일 + N년 ~ + N+1년 − 1일 | 회계일 창 — 회계일 ~ 다음 회계일 − 1일 |
기간 식별자(periodKey) | hire-N (N = 만 근속연수) | fy-YYYY (YYYY = 기간 시작 연도) |
| 부여 규칙 | 「입사일」 탭의 규칙만 사용 | 「회계년도」 탭의 규칙만 사용 |
| 근속 매칭 시점 | 기준일의 근속연수 | 기간 시작일의 근속연수 |
| 신규 입사자(1년 미만) | 월별 발생 규칙(최대일수 상한) | newHireMode에 따라 아래 두 방식 중 하나 |
회계일(fiscalYearStart) | 쓰지 않음 | 기간의 기점 |
| 퇴직 정산 | 현재 기간 잔여 그대로 | 퇴사 처리 화면에 입사일 기준 참고 환산 잔여를 정산 기준값으로 표시 (참고 기준 환산) |
회계년도 기준의 신규 입사자 부여 방식(newHireMode, 기준 변경 예약 때 선택):
| 방식 | 입사한 회계연도 | 다음 회계연도 | 그 다음부터 |
|---|---|---|---|
prorate_in_hire_year (기본) | 남은 기간만큼 바로 비례 부여 (예: 6월 입사 → 15 × 7/12 = 8일) | 전부 (15일) | 전부 |
monthly_then_retroactive (고용노동부 행정해석 방식) | 입사일 기준 매월 발생만 (1년 미만 규칙, 최대 11일) | 회계일에 입사 연도 남은 개월수 비례분을 소급 부여(15 × 7/12 = 8일) + 만 1년이 될 때까지 월별 발생을 이어 감 | 전부 |
monthly_then_prorate_at_anniversary | 입사일 기준 매월 발생만 (동일) | 회계일에는 월별 발생만 이어 가고, 만 1년이 되는 날에 그 회계연도 남은 개월수 비례분(6월 입사 → 6/1에 15 × 7/12 = 8일) 부여. 연간 총량은 위와 같고 부여 시점만 늦음 | 전부 |
- 원장(
leave_ledger_entries)·동결 부여(leave_grants)는periodKey로 묶여요. 기준이 다르면 키 체계도 다르므로 두 기준의 항목이 섞이지 않아요. - 규칙이 하나도 없으면 근로기준법 기본값으로 계산해요(1년 미만 월 1일·최대 11일, 1년 15일, 이후 2년마다 +1일·최대 25일).
4️⃣ 적용 시작일에 생기는 일 — 전환 정산
- 적용 시작일이 되면 잡(
leave-basis-transition.job, 매시 확인)이 직원별로 적용 시작일 전날 기준의 기간 잔여(부여 − 사용, 조정 포함)를 새 기준 첫 기간에carryover원장 항목으로 실체화해요. 출처는 변경 행(sourceType = basis_transition,sourceId = 변경 id)이라 멱등하고, 상세 팝업 사용 내역에 「이월」로 보여요. - 새 기준 첫 기간이 적용 시작일보다 먼저 시작했으면(예: 입사일 기준으로 되돌린 날이 입사기념일이 아닐 때) 그 기간의 부여는 남은 일수 비례(0.5일 단위 내림)로 줄여요. 회계년도 기준은 회계일부터 시작하므로 줄지 않아요. 이월과 비례 부여가 짝을 이뤄 겹치는 구간이 이중 부여되지 않아요.
- 정산이 끝난 변경은 취소할 수 없어요. 되돌리려면 새 변경을 예약해요.
5️⃣ 화면 표시 규칙
- 연차 현황 「산정 기준」 배지·상세 팝업 「적용된 규칙」 탭의 산정 기준은 모두 오늘 날짜로 판정한 값을 보여줘요. 직원마다 다른 값이 나올 수 없어요.
- 「적용 기준」 영역 ⓘ 툴팁(다중 줄)으로 3️⃣의 요점을 설명하고, 예약이 있으면 연차 현황 상단에도 "YYYY-MM-DD부터 ○○ 기준으로 바뀔 예정" 안내가 떠요.
- 반대 기준 탭에 만들어 둔 규칙은 그 기준이 적용될 때까지 쓰이지 않아요 — 탭에 안내 배너가 떠요.
⚠️ 구현 현황 · 하드닝 후보 (2026-08-13)
CODE가 진실이에요.
참고 기준 환산 — 회계년도·입사일 동시 조회 (2026-09-14)
병원은 일상 관리는 회계년도 기준으로, 퇴사 정산은 입사일 기준으로 연차를 봐야 해요(9/9 베스트 온보딩). 정본(원장·부여)은 여전히 조직 적용 기준 하나이고, 반대 기준은 참고 환산으로만 보여줘요.
- 어디서: 연차 현황 「산정 기준 보기」(입사일 / 회계년도 — 적용 기준과 다르면 안내 배너 + 배지에
(참고)), 상세 팝업 「적용된 규칙」의 참고 행, 퇴사 처리 화면의 「입사일 기준 잔여 연차」(정산 기준값). - 부여: 그 기준이 처음부터 적용됐다고 보고 계산해요(기준 변경 비례 축소 미적용). 그 기준의 기간 키로 동결 부여(
LeaveGrant)가 있으면 그 값을 써요. - 사용·조정: 원장 항목의
periodKey와 무관하게 귀속 달력일이 그 기준의 기간 창 안에 드는 항목만 세요. 귀속 달력일은 신청 기반 USE는 신청 시작일(calcBasis.startDate), 상쇄는 원본의 날짜, 그 외(조정·소멸)는 게시일이에요. 기준 전환 정산 CARRYOVER(sourceType = basis_transition)는 제외해요 — 이전 기준 잔여를 새 기간으로 옮긴 항목이라 이전 기준으로 되돌려 보면 이중 계상이 돼요. - 일↔분 환산은 본 잔여와 같은 규칙(항목별 소정근로시간 스냅샷)이에요.
- API:
leaveRequest.listBalances({ basis })→ 응답basis.reference,leaveRequest.balanceRuleDetail().reference,leaveRequest.settlementBalance(employeeId, asOfDate?)(항상 입사일 기준). 계산은leave-ledger.service.computeReferenceBalance(순수 함수). - 참고값은 원장을 바꾸지 않고, 신청·승인 검증(잔여 부족 판정)에도 쓰이지 않아요.
산정 기준 배지 「전환 기준(transition)」 — 해소 (2026-09-14)
- 경위: 2026-03 베스트재활의원 Phase 1 결정("입사일 기준 ~2026.12 → 2027.01~ 회계연도")이
annual-leave.service.ts의 상수FISCAL_YEAR_TRANSITION = 2027-01-01로 전 조직 공통 코드에 박혀 있었고, 전환 첫해를transition정책으로 표시했어요. - 결정: 산정 기준은 코드가 아니라 관리자가 조직 설정(
settings.leaveAccrualBasis)으로 직접 지정해요. 날짜에 따른 자동 전환,transition정책값, 전환연도 이월 특례는 제거했어요. 상세는 연차 산정 기준.