Skip to content

Time 근태 정정 관리 (FE 메인테이너)

2026-07-18 as-built. 공통 router/catalog/nav 충돌을 피하기 위해 이 Wave는 독립 view와 Time 전용 컴포넌트를 제공하고 공통 메뉴 연결은 통합 브랜치에 남긴다.

컴포넌트 트리

text
src/views/time/AttendanceCorrectionsView.vue
└─ AttendanceCorrectionPanelOrg.vue
   ├─ 정정 요청 목록
   ├─ 유효 출퇴근 기록
   ├─ SheetCreateAttendanceCorrectionArt.vue
   └─ SheetDecideAttendanceCorrectionArt.vue

모든 화면은 EDS/MDS 0.10 공식 card, table, badge, field, sheet, button, alert, empty-state 어휘를 조합한다. 로컬 CSS, override, !important, 신규 디자인 primitive는 없다. 생성·판단은 side sheet 전체 폼과 sheet-footer 저장/취소를 사용한다.

입력 props

AttendanceCorrectionPanelOrg와 view:

  • companyId: Company UUID
  • officeId: Office UUID
  • employeeId: 본인 또는 현재 조회 직원 UUID
  • employeeName: 요청 snapshot에 저장할 현재 표시명
  • periodStart: 월 1일 YYYY-MM-01
  • canManage: pending 요청에 검토 action을 표시할지 결정

canManage는 UX 표시용이다. 서버 decide_time_attendance_correction이 Office 관리자 권한을 다시 검사한다.

데이터 흐름

text
AttendanceCorrectionPanelOrg
  └─ useAttendanceCorrections(scope)
      ├─ repo.loadPeriod
      ├─ repo.listRequests
      ├─ repo.listEffectiveEvents
      ├─ repo.requestCorrection
      └─ repo.decideCorrection

              ├─ Supabase RPC adapter
              └─ test/config-missing local adapter

attendanceCorrectionRepo.js는 snake_case row를 camelCase UI shape로 정규화한다. Supabase adapter는 table direct write를 하지 않는다. 로컬 adapter도 원본 이벤트를 수정하지 않고 correction overlay를 별도 배열에 추가해 서버 의미를 모사한다.

UI 게이트

요청 sheet

  • replace: original + proposed type/time 필수
  • add: proposed type/time 필수, original 없음
  • void: original 필수, proposed 없음
  • work date와 5자 이상 사유가 있어야 요청 활성

판단 sheet

  • 5자 이상 판단 사유 필수
  • 열린 기간 승인: 바로 decision + correction event
  • 닫힌 기간 승인: 재오픈·재마감 동의 + 5자 이상 reopen reason 필수
  • 반려: reopen UI를 숨기고 decision만 생성

성공 후 sheet를 닫고 period, requests, effective events를 모두 다시 읽는다. revision conflict나 evidence conflict는 사용자 메시지로 바꾸고 sheet를 유지한다. 동일 원본 승인 경쟁의 loser는 time_attendance_correction_original_already_corrected를 받아 이미 정정된 원본 기록으로 안내하고 현재 유효 기록을 다시 확인하도록 한다.

상태 표시

서버 projection표시의미
pending검토 대기decision 없음
applied승인·적용approved decision + correction event
rejected반려rejected decision, correction event 없음

유효 기록 표는 corrected=true정정 이벤트, false를 원본 기록으로 표시한다. void된 원본은 표에서 사라지지만 요청·판단 이력은 요청함에 남는다.

loose coupling

  • approval component/composable/repo를 import하지 않는다.
  • payroll component/composable/repo를 import하지 않는다.
  • 전자결재 adapter는 후속에 별도 subject link/outbox 소비자로 추가한다. core submit/decide UX는 연결 여부와 무관하게 유지한다.
  • 공통 router/nav/i18n은 통합 브랜치에서 최소 연결했으며, catalog/auth와 상품 경계는 기존 Time 계약을 그대로 쓴다.

통합 체크리스트

  1. ✅ 공용 router가 /human-capital/time/attendance-correctionsAttendanceCorrectionsView를 연결한다.
  2. ✅ Time 메뉴의 근태 정정 항목이 기존 moduleRouteAccess entitlement gate 아래 노출된다.
  3. canManage는 현재 principal의 Time Office capability로 계산한다.
  4. 패널의 도메인 문구는 한국어 source string을 유지하고 메뉴명은 공용 i18n을 사용한다.
  5. 실제 Supabase 세션을 포함한 desktop/mobile visual regression은 후속 E2E 범위다.

Select anatomy

근태 예외·정정·판단·출퇴근 화면의 native Select는 <div class="select select-md w-full"><select>…</select></div> 구조를 사용한다. .select를 native element에 직접 붙이지 않는다. audit-ssot-conformance E4가 이 계약을 차단 검사한다.

테스트

  • AttendanceCorrectionPanelOrg.spec.js: 마감 배지, 독립 로컬 승인 문구, 명시적 reopen 동의, 승인 뒤 revision+2와 정정 projection
  • attendanceCorrectionRepo.test.js: 닫힌 기간 gate, 승인 overlay, 반려 불변
  • attendanceCorrectionMigration.spec.js: append-only/RLS/reopen-reclose/approval 비의존 계약