/SimpleHR project
SimpleHR project

근무 정책 ↔ 급여 연동 현황 및 이슈

conceptedited by Cairni · 방금 · AIv9

개요

본 페이지는 근무 정책 스펙(WorkPolicy)과 급여관리 스펙(Payroll) 사이의 연동 현황을 분석한다. 4대보험·소득세 보정은 분석 범위 밖이다. 분석 기준일은 2026-06-23이다. 원본 분석 문서 참조. 근로정책-급여-연동-현황분석.md


1. 현재 급여 계산 흐름

핵심 진입점은 generate_payslips() (payroll_service.py:833)이다.

근로정책-급여-연동-현황분석.md


2. 연동 현황 매트릭스

항목근로정책 필드급여 계산 참조상태
월 소정근로시간monthly_standard_hours (자동계산)EmployeePayBase.monthly_work_hours (수동, 기본 209)미연동
연장근로 할증률*(별도 필드 없음, 법정 1.5배)*1.5 하드코딩법정 고정
야간근로 할증률night_surcharge_rate (기본 1.5)0.5 하드코딩 (가산분만); 프론트 폼은 useState("50") 하드코딩으로 DB 단위 불일치 fix-taskNew-0702 (26년 07월 02일 우선수정사항)미연동
휴일근로 할증률holiday_surcharge_rate (기본 1.5)1.5 하드코딩; 프론트 폼은 useState("50") 하드코딩으로 DB 단위 불일치 fix-taskNew-0702 (26년 07월 02일 우선수정사항)미연동
휴일초과 할증률*(별도 필드 없음)*2.0 하드코딩법정 고정
1일 소정근로시간start_time, end_time, break_minutes → 계산 가능8시간 하드코딩미연동
고정연장 vs 실제연장독립 처리 (이중지급 가능)미연동
근태 데이터 (시간)_attendance_data_map() 자동 연동✅ 연동됨
직원별 근로정책 조회EmployeeWorkPolicy (EWP)_bulk_load_work_policies() EWP 우선 조회 + Employee.work_policy_id fallback✅ 연동됨 (0709 완료) fix-task-0709
만근수당 판단has_absence_or_late 연동✅ 연동됨
미사용연차unused_leave_days 연동✅ 연동됨

근로정책-급여-연동-현황분석.md


3. 미연동 이슈 상세

3-1. 소정근로시간 하드코딩 (209시간)

EmployeePayBase.monthly_work_hours의 기본값은 209시간이며, 관리자가 급여기초 저장 시 수동 입력하지 않으면 그대로 사용된다.

반면 WorkPolicy.monthly_standard_hours_calc_monthly_standard_hours() (policy_service.py:65-82)를 통해 work_days, start_time, end_time, break_minutes로 자동 계산된다. 주 4일 근무(174시간) 등 비표준 정책이 반영되지 않는다.

영향: 시급 = standard_wage / monthly_work_hours. 소정근로시간이 다르면 시급이 달라지고, 시급 기반 모든 수당(연장·야간·휴일·연차)이 잘못 계산된다. 근로정책-급여-연동-현황분석.md

3-2. 고정연장수당(FIXED_OVERTIME) vs 실제연장수당(PAY_OVERTIME) 이중지급

EmployeePayDetailFIXED_OVERTIME(category=ALLOWANCE)이 등록된 직원의 경우, 아래 두 경로가 모두 실행되어 이중지급이 발생할 수 있다.

  1. 1.고정 수당 루프 (payroll_service.py:960-989): FIXED_OVERTIME 금액이 그대로 포함됨
  2. 2.근태 연동 수당 루프 (payroll_service.py:993-1018): PAY_OVERTIME이 overtime_hours × hourly_wage × 1.5로 별도 추가됨

이중지급 조건: FIXED_OVERTIME이 급여기초에 등록되어 있고, 동시에 해당 월에 실제 연장근로가 발생한 경우. 근로정책-급여-연동-현황분석.md

3-3. 할증률 하드코딩

근태 수당 계산 시 할증률이 payroll_service.py:993-1001에 고정되어 있다.

python
("PAY_OVERTIME",    overtime_hours,    1.5,  ...)  # 연장
("PAY_NIGHT",       night_hours,       0.5,  ...)  # 야간 (가산분만)
("PAY_HOLIDAY",     holiday_hours,     1.5,  ...)  # 휴일
("PAY_HOLIDAY_OT",  holiday_ot_hours,  2.0,  ...)  # 휴일초과

WorkPolicy.night_surcharge_rate(기본 1.5, 전체 배율)와 코드의 야간 0.5(가산분)는 의미가 다르며, WorkPolicy.holiday_surcharge_rate도 급여 계산에 참조되지 않는다. 동일한 하드코딩은 payroll_excel.py:428-431에도 존재한다. 근로정책-급여-연동-현황분석.md

3-4. 근로정책 변경 시 급여기초 미갱신

update_work_policy()monthly_standard_hours를 재계산·업데이트(policy_service.py:108-132)한 이후, 직원별 EmployeePayBase.monthly_work_hours에 대한 후처리가 없다. 따라서 근로정책이 변경되어도 급여기초의 월 소정근로시간은 그대로 남는다. 근로정책-급여-연동-현황분석.md

3-5. 1일 통상임금 8시간 하드코딩

휴가 관리 스펙연차 자동계산 로직 스펙과도 연관되는 이슈로, 연차수당 계산의 기초인 daily_wagehourly_wage × 8로 고정되어 있다 (payroll_service.py:941).

근로정책의 start_time, end_time, break_minutes로 1일 소정근로시간을 계산할 수 있음에도(예: 09:00~17:00, 휴게 1시간 = 7시간), 7시간 근무자의 연차수당이 8시간 기준으로 과다 지급될 수 있다. 근로정책-급여-연동-현황분석.md


4. 이슈 요약

근무 정책 ↔ 급여 미연동 이슈AI · 출처 클릭
미연동 (미해결)5
소정근로시간 하드코딩 209h — EmployeePayBase vs WorkPolicy.monthly_standard_hours
근로정책-급여-연동-현황분석.md
고정연장수당(FIXED_OVERTIME) + 실제연장수당(PAY_OVERTIME) 이중지급 가능
근로정책-급여-연동-현황분석.md
야간·휴일 할증률 하드코딩 (WorkPolicy 필드 미참조)
근로정책-급여-연동-현황분석.md
근로정책 변경 시 급여기초(EmployeePayBase) 미갱신
근로정책-급여-연동-현황분석.md
1일 통상임금 8h 하드코딩 → 연차수당 과다 지급 가능
근로정책-급여-연동-현황분석.md
법정 고정 (의도적)2
연장근로 할증률 1.5 — 근로기준법 고정
근로정책-급여-연동-현황분석.md
휴일초과 할증률 2.0 — 근로기준법 고정
근로정책-급여-연동-현황분석.md
정상 연동4
근태 시간 데이터 (_attendance_data_map)
근로정책-급여-연동-현황분석.md
직원별 근로정책 조회 — EWP 우선 + work_policy_id fallback (0709 완료)
fix-task-0709
만근수당 판단 (has_absence_or_late)
근로정책-급여-연동-현황분석.md
미사용연차 일수 (unused_leave_days)
근로정책-급여-연동-현황분석.md

5. 코드 위치 참조표

이슈파일라인설명
시급 = standard_wage / monthly_work_hourspayroll_service.py604–605급여기초 저장 시 시급 자동계산
daily_wage = hourly_wage × 8payroll_service.py941명세서 생성 시 1일 통상임금
연장 1.5 / 야간 0.5 / 휴일 1.5 / 휴일초과 2.0payroll_service.py993–1001근태 수당 할증률 하드코딩
FIXED_OVERTIME 시드 (category=ALLOWANCE)seed/helpers.py402고정 수당으로 처리
고정 수당 루프 (ATTENDANCE 스킵)payroll_service.py960–989FIXED_OVERTIME은 스킵 안됨
근태 연동 수당 (PAY_OVERTIME 등)payroll_service.py1003–1018실제 근태 시간 기반 수당 추가
연차수당 계산payroll_service.py1020–1037daily_wage × 미사용연차일수
월 소정근로시간 자동계산policy_service.py65–82_calc_monthly_standard_hours()
근로정책 resolvepolicy_service.py3632–3736resolve_effective_work_policies_for_user()
엑셀 다운로드 할증률payroll_excel.py428–431동일한 하드코딩 존재

근로정책-급여-연동-현황분석.md


6. 미결 설계 질문사항

아래 항목들은 개발 방향이 확정되지 않아 의사결정이 필요한 사항이다. 결정 내용은 의사결정 로그에 기록한다.

Q1. 고정연장수당 + 실제연장수당 처리 정책

옵션설명
A) 포괄임금제 방식FIXED_OVERTIME은 월 고정 약정. 실제 연장이 고정분 초과 시에만 초과분 PAY_OVERTIME 지급
B) 현행 유지고정연장과 실제연장을 독립 수당으로 이중지급 허용 (회사 정책에 따라)
C) 관리자 설정 플래그PayItem 또는 WorkPolicy에 "고정연장 적용 시 근태연장 스킵" 플래그 추가

근로정책-급여-연동-현황분석.md

Q2. 근로정책 변경 시 급여기초 처리 방식

옵션설명
A) 자동 갱신update_work_policy() 후처리로 해당 정책 적용 직원의 EmployeePayBase 일괄 업데이트
B) 알림만관리자에게 "근로정책 변경됨, 급여기초 확인 필요" 알림 발송, 수동 갱신
C) 동적 조회명세서 생성 시 EmployeePayBase의 monthly_work_hours를 사용하지 않고, 직원별 유효 근로정책에서 월 소정근로시간을 동적으로 가져옴

근로정책-급여-연동-현황분석.md

Q3. 야간수당 배율 해석

  • 현행: 가산분 0.5배만 지급 (기본급에 야간분 미포함 가정)
  • night_surcharge_rate(1.5)를 급여 계산에 사용하려면, 가산분 = night_surcharge_rate - 1.0으로 변환 필요
  • 야간 전용 근무자의 경우 전체 1.5배 지급 여부는 별도 결정 필요

근로정책-급여-연동-현황분석.md

Q4. 근로정책 할증률 직접 사용 여부

  • 현재 holiday_surcharge_rate, night_surcharge_rate는 UI 표시용으로만 사용되며 급여 계산에 참조되지 않음
  • 법정 할증률(연장 1.5, 야간 가산 0.5, 휴일 1.5, 휴일초과 2.0)은 근로기준법 고정이므로 정책별로 다르게 설정할 실익은 제한적
  • , 회사 자체 규정으로 법정 이상 할증을 적용하는 경우(예: 휴일 2.0배)에는 정책 참조가 필요

근로정책-급여-연동-현황분석.md

추가 이슈 (07-02): 프론트엔드 근로정책 수정 폼에서 formNightSurcharge / formHolidaySurchargeuseState("50")으로 고정되어 setter 없이 항상 50을 전송한다. DB 기본값 1.5(배수)와 단위가 달라 실제 할증률 DB 반영이 불가한 상태이므로, 단위 통일(1.5 배수 vs 50 퍼센트) 및 급여 계산 코드 기준 확인 후 결정 필요. fix-taskNew-0702 (26년 07월 02일 우선수정사항)

7. 추적 중인 개선 과제

fix-task-0623 기준

fix-task-0623 (26년 06월 23일 수정사항)에서 근로정책 ↔ 급여 연동 관련 다음 개선 과제가 등록되었다.

근로정책 수정 시 이력 관리 및 소급 적용 방지

문제: 근로정책을 수정하면 현재 시점뿐 아니라 과거 자료까지 정책이 변경되어 과거 근태·급여 데이터가 왜곡된다.

근본 원인: attendance_service의 근태 조회 함수 4곳이 work_policies 테이블을 직접 JOIN하여 현재 live 정책값만 사용한다.

수정 계획: policy_servicebuild_policy_version_resolver 추가 (live + history 일괄 로드 → work_date 기준 in-memory 매칭), list_attendance·breakdown_detail·analytics·get_my_attendance 4곳 수정 예정. fix-task-0623 (26년 06월 23일 수정사항)

fix-task-0624 기준

fix-task-0624 (26년 06월 24일 수정사항)에서 추가로 확인된 근로정책 ↔ 급여 연동 미구현 항목 목록이다. fix-task-0624 (26년 06월 24일 수정사항)

fix-task-0625 기준

fix-task-0625 (26년 06월 25일 수정사항)에서 근로정책 ↔ 급여 연동 관련 다음 항목들이 구현 완료 처리되었다. fix-task-0625 (26년 06월 25일 수정사항)

fix-task-0629 기준

fix-task-0629 (26년 06월 29일 수정사항)에서 근로정책 ↔ 급여 연동 관련 다음 항목들이 구현 완료 처리되었다. fix-task-0629 (26년 06월 29일 수정사항)

완료된 항목

  • 출장 일정 사용(business_trip_enabled): BusinessTripRequest 모델 추가, 신청/승인/반려 API 구현, 승인 시 기간 내 각 근무일에 ATT_BUSINESS_TRIP 상태 AttendanceRecord 자동 생성. 통합 테스트(test_business_trip.py, test_business_trip_existing_update.py, test_attendance_doc_approval.py) 추가. 출장 승인 시 기존 레코드 갱신, 전자결재 출장/외근 승인→근태 레코드 자동 생성 연동, 근태 신청 캘린더 날짜 1일 밀림(UTC→로컬 타임존) 수정 포함. fix-task-0629 (26년 06월 29일 수정사항)
  • 탄력근로 시작 날짜(flexible_start_date): WorkPolicy/WorkPolicyHistoryflexible_start_date 컬럼 추가, 스키마·스냅샷·직렬화 전부 반영. 통합 테스트(test_flexible_start_date.py) 추가. 프론트 폼 로드 시 flexible_start_date 누락 수정(work/page.tsx). fix-task-0629 (26년 06월 29일 수정사항)

완료된 항목

  • 근무제 연동(LINKED) 정산방식 급여 반영: LINKED 정책의 AttendanceRecord.overtime_hours 기반 급여 반영 구현 완료.
  • 저녁시간 연장근로 제외(exclude_dinner_from_overtime): 구현 완료.
  • 연장근로 입력 단위 제한(overtime_input_unit): 신청 API 단위 검증 구현 완료.
  • 연장근로 최소시간 제한(overtime_min_input): 신청 API 최소시간 검증 구현 완료.
  • 점심시간 휴게시간 차감(use_lunch_as_break): DB 필드 저장 수정 완료.
  • 선택근무 퇴근 허용시간(checkout_allow_from/to): 구현 완료.
  • 선택/탄력근무 출근 허용시간(flex_start_from/to): 구현 완료. 허용시간 외 출근 버튼 차단 및 "출퇴근 요청하기" 폼 자동 노출(관리자 승인 경로) 포함. fix-task-0625 (26년 06월 25일 수정사항)

미구현 — 계속 추적 중

  • 대체휴일/대체근무(substitution_enabled) — 미구현
  • 근무일 변경 기준시간(shift_day_boundary) — 미반영
  • 출장 일정 사용(business_trip_enabled) — ~~미구현~~ → 구현 완료 fix-task-0629 (26년 06월 29일 수정사항)
  • 탄력근로 시작 날짜(flexible_start_date) — ~~미구현~~ → 구현 완료 fix-task-0629 (26년 06월 29일 수정사항)
  • 모바일 네비게이션에서 연장근로 메뉴 접근 경로 확인 필요 fix-task-0625 (26년 06월 25일 수정사항)

fix-taskNew-0702 기준

fix-taskNew-0702 (26년 07월 02일 우선수정사항)에서 근로정책 수정 폼 초기화 관련 버그가 신규 등록되었다. fix-taskNew-0702 (26년 07월 02일 우선수정사항)

fix-task-0703 기준

fix-task-0703 (26년 07월 03일 수정사항)에서 근로정책 ↔ 급여 연동 관련 다음 항목들이 미완료 상태로 확인되었다. fix-task-0703 (26년 07월 03일 수정사항)

fix-task-0709 기준

fix-task-0709 (26년 07월 09일 수정사항)에서 급여-근로정책 연동 관련 다음 항목들이 완료 처리되었다. fix-task-0709

완료된 항목

  • 급여-근로정책 연동 개선 (1순위): _bulk_load_work_policies()EmployeeWorkPolicy(EWP) 우선 조회 후 Employee.work_policy_id fallback 방식으로 전환 완료. fix-task-0709
  • EWP 단일 소스 전환 backfill 마이그레이션: EWP가 없는 기존 직원 289명에 EWP 일괄 생성, overrides_dept=false 통일. 부서 정책 미배정 시 직원 등록/수정 차단, 초기 설정 가이드 분리(부서 등록 + 부서별 근로정책 배정) 적용 완료. fix-task-0709

미완료 — 계속 추적 중

  • 근로정책 수정 폼 초기화 버그: formNightSurcharge / formHolidaySurchargeuseState("50")으로 하드코딩되어 setter 없이 항상 50을 전송한다. DB 기본값 1.5(배수)와 단위 불일치로 할증률이 DB에 올바르게 반영되지 않는다. fix-task-0703 (26년 07월 03일 수정사항)
  • shift_day_boundary null 폴백: shift_day_boundary가 null일 때 "06:00"으로 폴백되어 변경 없이도 불필요한 scheduled_change가 생성되는 버그가 미해결 상태이다. fix-task-0703 (26년 07월 03일 수정사항)
  • 근로 정책 소속 직원 적용 검토: 근로 정책 수정 및 등록 시 소속 직원 모두에게 적용하는 부분의 필요 여부 검토 및 불필요 시 제거 예정. fix-task-0703 (26년 07월 03일 수정사항)

미해결 — 근로정책 수정 폼 초기화 버그

  • 야간·휴일 할증률 하드코딩: formNightSurcharge / formHolidaySurchargeuseState("50")으로 하드코딩되어 있고 setter가 없어, 수정 시 항상 50을 전송한다. DB 기본값 1.5(배수)와 단위가 불일치하여 급여 계산 오류 발생 가능. night/holiday surcharge rate 단위를 통일(1.5 배수 vs 50 퍼센트)하고, 급여 계산 코드에서 사용하는 형식 확인 후 결정 필요. fix-taskNew-0702 (26년 07월 02일 우선수정사항)
  • shift_day_boundary null 폴백: shift_day_boundary가 null일 때 "06:00"으로 폴백 처리되어, 실제 변경이 없어도 값이 달라져 불필요한 scheduled_change가 생성된다. fix-taskNew-0702 (26년 07월 02일 우선수정사항)
  • 근로 정책 수정 및 등록 시 소속 직원 전체 적용 여부 검토: 불필요한 경우 해당 UI/로직 제거 예정. fix-taskNew-0702 (26년 07월 02일 우선수정사항)
  • 근로정책 수정 폼 초기화 버그 (0703 미완료): formNightSurcharge / formHolidaySurcharge useState("50") 하드코딩 및 shift_day_boundary null 폴백 문제가 0703 기준으로도 미완료 상태이다. night/holiday surcharge rate 단위 통일(1.5 배수 vs 50 퍼센트) 및 급여 계산 코드 기준 확인 후 결정 필요. fix-task-0703 (26년 07월 03일 수정사항)

완료된 항목

  • 근로정책 수정 시점 입력 및 소급 적용 방지: 근로정책 수정 시 수정 시점을 입력할 수 있도록 하고, 해당 시점 이후부터만 변경된 정책이 적용되도록 수정 완료. fix-task-0624 (26년 06월 24일 수정사항)
  • 휴일근로 8시간 초과 자동 분리 (근기법 §56②): 일자별 OT_HOLIDAY 8시간 이내 1.5배, 초과분 2.0배 자동 분리 및 급여 반영 완료. 프로덕션 소급 대상 0건 확인. fix-task-0624 (26년 06월 24일 수정사항)
  • 퇴근 미체크 자동 처리 배치: 매일 KST 00:15 실행, 최근 7일 이내 퇴근 미체크(check_out_time IS NULL) 레코드를 근로정책 unchecked_checkout_policy 설정에 따라 자동 처리. AUTO_END_TIME → scheduled_end 시간으로 퇴근 자동 기록 + 근무시간/상태 재계산; LEAVE_BLANK → 스킵. advisory lock(820620)으로 multi-worker 중복 방지. 급여 영향 없음 (급여는 OvertimeRequest 기반, AttendanceRecord.overtime_hours 직접 읽지 않음). fix-task-0624 (26년 06월 24일 수정사항)

미구현 — 근로정책 급여 연동 항목 (추가 확인)

아래 항목들은 UI·DB 일부가 준비되어 있으나 백엔드 급여/근태 로직에 반영되지 않은 상태이다. fix-task-0624 (26년 06월 24일 수정사항)

항목현황급여 영향
근무제 연동(LINKED) 정산방식 급여 반영~~_attendance_data_map()에서 LINKED 정책 시 AttendanceRecord.overtime_hours 기반 전환 필요. 현재 BASIC과 동일 동작~~ → 구현 완료 fix-task-0625 (26년 06월 25일 수정사항)연장수당 집계 오류 가능
저녁시간 연장근로 제외(exclude_dinner_from_overtime)~~UI 토글만 존재, DB 필드·백엔드 로직 미구현~~ → 구현 완료 fix-task-0625 (26년 06월 25일 수정사항)활성화 시 저녁시간(18~19시) 연장수당 감소
대체휴일/대체근무(substitution_enabled)UI 토글만 존재, DB 필드·백엔드 로직 미구현. 구현 전까지 UI 숨김/비활성화 검토연장·휴일 근무를 가산수당 대신 휴무로 상쇄
근무일 변경 기준시간(shift_day_boundary)DB 저장되나 근태/급여 로직 미반영; null 시 "06:00" 폴백으로 불필요한 scheduled_change 생성 버그 확인 fix-taskNew-0702 (26년 07월 02일 우선수정사항)미구현 시 휴일근로·야간시간 집계 오류 가능
출장 일정 사용(business_trip_enabled)~~DB·UI 있으나 자동 출퇴근 기록 채우는 로직 미구현~~ → 구현 완료 (BusinessTripRequest 모델·신청/승인/반려 API·승인 시 ATT_BUSINESS_TRIP 상태 AttendanceRecord 자동 생성) fix-task-0629 (26년 06월 29일 수정사항)출퇴근 기록 누락 시 급여 영향
법정근로 내 연장 구분(legal_overtime_split)DB·UI 있으나 근태/급여 로직 미구현법내 연장(할증 없음) vs 법외 연장(1.5배) 구분 → 급여 직접 영향
연장근로 입력 단위 제한(overtime_input_unit)~~DB·UI 있으나 신청 API에서 단위 검증 미구현~~ → 구현 완료 fix-task-0625 (26년 06월 25일 수정사항)수당 집계 단위 오차
연장근로 최소시간 제한(overtime_min_input)~~DB·UI 있으나 신청 API에서 최소시간 검증 미구현~~ → 구현 완료 fix-task-0625 (26년 06월 25일 수정사항)소액 연장수당 과다 생성 가능
점심시간 휴게시간 차감(use_lunch_as_break)~~UI만 존재, DB 필드 없어 저장 안 됨~~ → 수정 완료 fix-task-0625 (26년 06월 25일 수정사항)근로시간 산정에 영향
선택근무 퇴근 허용시간(checkout_allow_from/to)~~UI만 존재, DB 필드 없어 저장 안 됨~~ → 구현 완료 fix-task-0625 (26년 06월 25일 수정사항)
탄력근로 시작 날짜(flexible_start_date)~~UI만 존재, DB 필드 없어 저장 안 됨~~ → 구현 완료 (WorkPolicy/WorkPolicyHistory에 flexible_start_date 컬럼 추가, 스키마·스냅샷·직렬화 반영, 프론트 폼 로드 시 누락 수정) fix-task-0629 (26년 06월 29일 수정사항)탄력근무 주기 기준점 미확정
선택/탄력근무 출근 허용시간(flex_start_from/to)~~미구현~~ → 구현 완료 fix-task-0625 (26년 06월 25일 수정사항)허용시간 외 출근 차단

8. 관련 페이지

Made with CairniExplore public wikis →