엑셀 자료 이관과 시트 탭 등록
제품 개발 기록으로 · 급여 시트 · HR 원천 기록 · 조직과 권한
CLI·파서·DB 쓰기 구현을 대조한 운영용 안내입니다. 병원 엑셀을 읽거나 DB 이관을 실행한 검증은 아닙니다. 웹 앱에서 파일을 고르는 시트 가져오기와 구분됩니다.
대상과 준비
현재 등록된 조직별 파서는 BESTRH 하나입니다. 다른 병원 파일을 형식 확인 없이 이 파서에 넣으면 동일한 의미로 이관된다고 보장할 수 없습니다. --org는 파서 종류, --target은 저장할 조직 코드이며 서로 다릅니다. DB 권한은 .env 연결 정보로 결정되고 사용자 UI의 역할 선택 단계는 없습니다.
현재 조직별 구현의 급여 기간은 2026년 1월, 정산 연도는 2025년으로 상수화돼 있습니다. 임의 연월을 받는 옵션은 없습니다. 현재 월 자료 이관기로 오해하지 않습니다. 원본을 수정하기 전에 기간·원천 탭·조직 매핑을 검토하고 급여 시트의 월별 자료 구조와 맞춰야 합니다.
필요한 준비는 암호가 해제된 지원 워크북, 대상 조직과 DB 백업/복구 경로, 현재 스키마, 실행 계정입니다. 파일 경로를 생략하면 저장소 루트 non-password.xlsx를 사용합니다. 상대 경로도 앱 폴더가 아니라 저장소 루트 기준으로 해석합니다.
옵션과 실제 분기
| 입력 | 필수·기본값 | 현재 결과 |
|---|---|---|
--org=BESTRH | 필수, 대소문자 정규화 | BESTRH 파서 선택. 미등록 코드는 오류 종료 |
--target=DOCS_TEST | 선택, 파서의 기본 조직 코드 | 해당 코드 조직 조회, 없으면 생성 |
--sheet=all | 선택, 기본 all | 지원 원천과 설정된 시트 전체 처리 |
--sheet=sheets | 선택 | 설정된 워크북 탭을 SheetView/행/셀로 기록 |
--sheet=employees, teams, payroll, overtime, nursing, rehab, sports | 선택 | 먼저 직원 파싱·이관 후 지정 원천 분기 |
--sheet=grades, education, settlement, resignation | 문자열로 받지만 현재 단독 실행 문제 있음 | 분기가 직원 처리 조건 안에 있으나 바깥 조건에 이 값이 없어 단독 지정 시 해당 이관에 진입하지 않음. all에서는 실행 |
| 마지막 위치 인자 | 선택, 기본 non-password.xlsx | 읽을 워크북 |
알 수 없는 --sheet 값은 허용 목록 검증으로 거절되지 않습니다. 빈 작업인데 전체 완료 로그가 나올 수 있습니다. 쉼표로 여러 필터를 지정하는 기능, 연월 옵션, dry-run 옵션은 없습니다. --sheet=sheets도 시작 시 「사번」·「급여대장(전체)」를 읽는 코드가 먼저 실행됩니다.
실행하고 결과 확인하기
아래 명령은 사용 예이며 이번 문서 작성에서 실행하지 않았습니다. DOCS_TEST는 검증용 대상 조직 코드 예시로 실제 운영 조직 코드로 자동 대체하지 않습니다.
- 저장소 루트에서
.env의 DB 대상, 파일 경로, 대상 조직, 현재 고정 기간을 확인합니다. 대상 조직이 없으면 자동 생성되므로 철자 오타도 기존 조직 선택 실패가 아닌 새 조직 생성이 될 수 있습니다. - 새 테스트 데이터로 시트만 검증할 경우, 사번 연결에 필요한 직원이 대상 조직에 있는지 먼저 확인합니다. 필요 원천이 없다면 직원 이관을 선행합니다.
- 필요한 범위를 지정해 실행합니다.
pnpm --filter @hereby/importer start -- --org=BESTRH --target=DOCS_TEST --sheet=employees ./fixtures/import-sample.xlsx
pnpm --filter @hereby/importer start -- --org=BESTRH --target=DOCS_TEST --sheet=sheets ./fixtures/import-sample.xlsx전체 이관은 옵션을 --sheet=all로 바꿉니다. 현재 단독 필터 문제가 있는 원천을 위해 운영 DB에 전체 이관을 우회 실행하지 않습니다. 해당 분기 수정·검증이 먼저입니다.
- 시작 로그의 Importer·Target org·File·Filter를 확인하고 탭별 시트/행/셀 수를 수집합니다. 파일을 열지 못하거나 DB 연결이 실패하면 오류 종료합니다.
- '탭 없음', '하위 테이블 0개', '수식 참조 미해결' 경고를 별도로 확인합니다. 최종 성공 로그만으로 모든 탭이 들어간 것은 아닙니다.
- DB에서 대상 조직과 기간의 시트별 행·셀 수, 사번 미연결 행, 수식 참조를 조회하고 원본의 표별 수와 대조합니다. 조회 예시는 표준 이관 가이드에 있습니다. 조직·기간 조건 없이 전체 수치만 비교하지 않습니다.
- 급여 시트를 대상 조직으로 열어 설정 그룹·시트·행·원천 연결을 확인하고 새로고침 후 유지되는지 확인합니다. 시트 저장은 급여 확정이나 직원 명세서 발송이 아닙니다.
새 엑셀 탭을 추가하는 사용법
이 단계는 개발자가 이관 구성을 확장할 때 사용합니다. 설정 필드의 상세 정본은 SHEET-IMPORT-GUIDE.md입니다.
- 탭의 정확한 이름과 공백, 헤더/데이터 시작 행, 사번 열, 합계 행, 가로/세로 배치를 읽습니다. 행·열 번호는 0부터 시작합니다.
- 단일 표는
none,*제목으로 나누는 표는star-prefix, 단일 제목 행으로 나누는 표는section-header, 가로 병렬 표는side-by-side를 선택합니다. 가로 병렬 표에는 시작·끝 열 범위가 필요합니다. sheet-configs.ts의SHEET_TAB_CONFIGS에tabName,groupId, 유일한slug,detection을 넣습니다. 사번 연결이 필요하면rowBasis: employee와 실제 사번 열을 지정합니다. 날짜 축은date, 자유 표는free이며rowDate필드는 없습니다.- 수식 열이 필요하면
formulas에 실제 열 키와 수식을 추가합니다.@slug참조는 같은 대상 조직·기간에서 생성한 시트 ID로 해석됩니다. 누락된 참조는 경고 후 미해결 문자열로 남을 수 있으므로 배포 전에 검증합니다. - 참고/임시 탭은
SKIP_TABS로 명시합니다. 워크북의 모든 탭이 자동 등록되는 것이 아니라 설정 배열을 순회합니다. - 파서 테스트와 importer 빌드로 형식·타입을 확인한 뒤 복제된 DB에서 이관합니다. 반복 열·전치·중복 헤더·합계 제거·사번 미연결을 원본과 비교합니다.
transpose가 켜졌다고 모든 표를 뒤집지 않습니다. 파서의 이름 형태·개수·비율 조건을 충족한 하위 표에 적용됩니다. 사번 매칭 실패 행은 건너뛰는 것이 아니라 employeeId = null로 남습니다.
재실행·중단·실패
시트 이관은 SheetView 메타데이터를 갱신하고 기존 행을 삭제한 뒤 행·셀을 다시 넣습니다. 이관 후 웹에서 편집한 행을 보존하면서 병합하는 방식이 아닙니다. 전체 과정의 일괄 트랜잭션이나 화면상 되돌리기 버튼이 없으므로 중단 시 이미 처리된 자료가 남을 수 있습니다. 동일 조직·기간에 재실행하기 전 데이터 차이를 확인합니다.
파일 누락과 빈 하위 표는 건너뛰지만 DB 쓰기 오류는 상위로 전달돼 실행을 실패시킵니다. 사번/급여대장의 최초 읽기는 탭별 skip 처리와 위치가 다릅니다. 실패 원인과 마지막 성공 시트를 확인하고 복구 또는 대상별 재실행 범위를 결정합니다.
연결과 현재 등록 범위
직원·팀은 조직 관리, 근로계약·교육·정산 원천은 HR 기록, 계산과 반영은 급여 시트, 직원 노출은 급여 배포에서 이어집니다.
아래는 검사한 SHEET_TAB_CONFIGS의 등록 탭입니다. 한 탭이 여러 하위 시트로 분리될 수 있어 탭 수와 생성 시트 수는 같지 않습니다.
| 엑셀 탭 | 그룹 | 기준 slug |
|---|---|---|
| 급여대장(전체) | 급여 | payroll_ledger |
| 사번 | 급여 | employee_numbers |
| Sheet1 | 급여 | special_detail |
| 재활_경력 | 호봉 | rehab_career |
| 기능직_호봉 | 호봉 | functional_grade |
| 간호부_호봉 | 호봉 | nursing_grade |
| 행정시간외 | 시간외 | ot_admin |
| 간호부-시간외근무 | 시간외 | ot_nursing |
| 스포츠치료-시간외 | 시간외 | ot_sports |
| 치료시간외 (토요일) | 시간외 | ot_rehab_sat |
| 치료시간외 (토외) | 시간외 | ot_rehab_weekday |
| NDT(토요일) | 시간외 | ndt_saturday |
| 영양,미화 휴일 | 시간외 | nutrition_cleaning_holiday |
| 스포츠치료(인센) | 인센티브 | sports_incentive |
| 스포츠치료(체외충격파) | 인센티브 | eswt_incentive |
| 재활 | 인센티브 | rehab_incentive |
| 간호부 | 인센티브 | nursing_allowance |
| 간호간병인센티브 | 수당 | nursing_care_incentive |
| 특별수당 | 수당 | special_allowance |
| 기타수당 | 수당 | other_allowance |
| 조정수당 | 수당 | adjustment_allowance |
| 내일채움공제기여금 | 수당 | tomorrow_fund |
| 공제내역 | 공제 | deduction_detail |
| 써티교육비지급 | 교육 | education_subsidy |
| 연말정산 | 연말정산 | year_end_settlement |
| 연말정산 (분할납부) (2) | 연말정산 | year_end_installment |
| 퇴사자 | 퇴사 | resigned_payroll |
| 퇴사자(연차수당) | 퇴사 | resigned_leave_pay |
| 퇴직정산 | 퇴사 | retirement_settlement |
| 단기근무자 | 기타 | short_term_worker |
| 당직의 | 기타 | on_call_doctor |
| 건보정산(곽초희) | 기타 | health_insurance_settlement |
근거와 변경 기록
기존 앱 소개의 '전체 엑셀을 한 번에 이관'을 파서·고정 기간·실제 필터 조건으로 구체화했습니다. 범용 가져오기와 CLI 이관을 분리하고, 필터 미진입 및 재실행 덮어쓰기를 문서화했습니다. 새 실행·캡처는 없으며 필요한 증거는 비식별 샘플 워크북, 대상 조직 로그, DB 수량 대조, HR 시트 재진입 화면입니다.