SimpleHR project
계약일 이중저장 불일치 보정 절차 (배포 전)
conceptedited by Cairni · 방금 · AIv1
개요
Simple HR 시스템에서 계약 시작일·종료일이 employees 테이블(Employee.contract_end_date)과 employee_contracts 테이블(EmployeeContract.end_date) 두 곳에 이중 저장되어 있어, 값이 서로 달라지는 불일치 상황이 발생할 수 있다. 배포 직전에 아래 4단계 절차로 보정해야 한다. 26년 06월 26일 수정사항 참고.
기준 우선순위: 관리자가 직원 상세 드로어에서 수정한Employee.contract_end_date값이 최신 의도값이므로, 이 값을 기준으로EmployeeContract.end_date를 맞춘다.
불일치가 발생하는 원인
보정 절차 다이어그램
1단계: 불일치 현황 재조회
두 가지 케이스를 각각 조회한다.
케이스 A — EmployeeContract 레코드가 아예 없는 직원
Employee.contract_end_date는 있지만 유효한(CANCELLED가 아닌) EmployeeContract가 없는 직원 목록을 확인한다.
bash
docker exec simplehr-prod-postgres psql -U simplehr_prod -d simplehr_prod -c "
SELECT e.id, u.name, e.contract_type, e.contract_end_date
FROM employees e
JOIN users u ON u.id = e.user_id
WHERE e.contract_end_date IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM employee_contracts ec
WHERE ec.employee_id = e.id
AND ec.status != 'CANCELLED'
);"케이스 B — end_date 값이 서로 다른 직원
bash
docker exec simplehr-prod-postgres psql -U simplehr_prod -d simplehr_prod -c "
SELECT e.id, u.name,
e.contract_end_date::date AS employee_end,
ec.end_date::date AS contract_end,
ec.id AS ec_id
FROM employees e
JOIN users u ON u.id = e.user_id
JOIN employee_contracts ec ON ec.employee_id = e.id
AND ec.status != 'CANCELLED'
WHERE e.contract_end_date IS NOT NULL
AND ec.end_date::date != e.contract_end_date::date;"2단계: EmployeeContract 없는 직원 → 계약서 생성
케이스 A에 해당하는 직원이 있을 때만 실행한다.
방법 1 (권장): 관리자 UI(/admin/employees)에서 해당 직원의 근로계약서를 직접 생성한다. 근로계약서 스펙 참조.
방법 2 (수동 SQL): 아래 예시 쿼리를 직원 ID·tenant_id 확인 후 실행한다.
sql
-- 예시 (직원 ID, tenant_id 확인 후 실행)
-- INSERT INTO employee_contracts (
-- id, tenant_id, employee_id, contract_number, contract_type,
-- start_date, end_date, status, created_at, updated_at
-- ) VALUES (
-- gen_random_uuid(), '테넌트ID', '직원ID', 'MANUAL-001',
-- '계약유형', '입사일', '만료일', 'ACTIVE', now(), now()
-- );⚠️tenant_id,employee_id,contract_type,start_date,end_date는 반드시 실제 값으로 치환한 후 실행할 것.
3단계: 불일치 직원 → EmployeeContract.end_date 보정
케이스 B에서 조회된 ec_id를 사용하여 EmployeeContract.end_date를 Employee.contract_end_date 기준으로 업데이트한다.
sql
-- 최신 계약(created_at DESC)의 end_date만 업데이트
-- 2단계 쿼리 결과의 ec_id를 사용
-- UPDATE employee_contracts
-- SET end_date = '2026-07-31', updated_at = now()
-- WHERE id = 'ec_id값';주의: 여러 건이 있을 경우 각 ec_id별로 개별 실행한다. 일괄 UPDATE 시 의도하지 않은 레코드가 변경되지 않도록 WHERE 절을 반드시 확인한다.4단계: 보정 후 검증
보정 완료 후 불일치 건수가 0건인지 확인한다.
bash
docker exec simplehr-prod-postgres psql -U simplehr_prod -d simplehr_prod -c "
SELECT count(*)
FROM employees e
JOIN employee_contracts ec ON ec.employee_id = e.id
AND ec.status != 'CANCELLED'
WHERE e.contract_end_date IS NOT NULL
AND ec.end_date::date != e.contract_end_date::date;"결과가 0이면 보정 완료. 0이 아닌 경우 3단계로 돌아가 나머지 건을 처리한다.
보정 체크리스트
계약일 보정 단계별 진행 상태AI · 출처 클릭
대기1
4단계: 보정 후 검증 (불일치 0건 확인)
진행 필요3
1단계: 불일치 현황 재조회 (케이스 A·B)
2단계: EmployeeContract 없는 직원 계약서 생성 (해당자 있을 때만)
3단계: end_date 불일치 직원 보정 (Employee 기준 UPDATE)
관련 맥락
- 이 보정 작업은 26년 06월 26일 수정사항에서 배포 전 수동 작업으로 지정되었다.
- 계약일 수정 기능(직원 상세 드로어에서 계약 시작일·만료일 수정,
Employee.contract_end_date캐시 동기화)은 같은 날짜 수정사항에서 함께 구현되었다. - 직원 재직 상태 변경 워크플로 및 배포 후 관리자 조치 체크리스트 (HNT 이관)도 함께 참고할 것.
- 유사한 배포 전 데이터 보정 사례는 데이터 이관 작업 스펙 (HNT) 참조.