다크모드
시설 작업지시 프론트엔드 메인테이너 매뉴얼
정식 소비 화면
/facility/task/equipment/task/general—subjectKind='equipment'/facility/task/unit/task/general—subjectKind='unit'
두 IndexView.vue는 src/components/facility/work-order/WorkOrderHeaderOrg.vue와 WorkOrderMainOrg.vue를 같은 방식으로 소비합니다. 과거 maintenance task/setting 및 task setting 경로는 src/router/facilityWorkOrderRoutes.js의 함수형 redirect를 사용해 query와 hash를 보존한 채 정식 경로로 이동합니다. facilityNav.js와 AI 기능 카탈로그에는 maintenance 작업지시 링크를 두지 않습니다.
컴포넌트 흐름
text
canonical IndexView(subjectKind)
-> WorkOrderHeaderOrg (현재 Office 사실만 표시)
-> WorkOrderMainOrg
-> useFacilityWorkOrders(subjectKind)
-> resolveFacilityWorkOrderRepo()
-> Supabase adapter 또는 unavailable empty adapter
-> facility_work_orders list
-> get_office_operational_participants() (optional ledger)
-> facility_assets 또는 property_spaces (optional exact target ledger)
-> WorkOrderTableOrg
-> title click: exact row -> SheetWorkOrderDetailArt.open(row)
-> requested: SheetAssignWorkOrderArt -> transition(row, participant)
-> later status: transition(row)
-> SheetCreateWorkOrderArt -> create(input)화면은 Supabase client나 RPC를 직접 호출하지 않습니다. Company/Office scope는 useAccountContext()에서 가져오고 repository가 snake_case API 계약을 camelCase UI 모델로 정규화합니다.
주요 파일
src/components/facility/work-order/WorkOrderMainOrg.vue- 설비·공간 공통 실제 원장 orchestrator
- loading/error/unavailable/real-empty 분리
- participant partial failure 경고 분리
- exact target partial failure를 분리하고 manual
subjectRef생성 유지 - 선택 ID 추적과 Office 변경 시 생성·상세·배정 시트 무효화
src/components/facility/work-order/WorkOrderTableOrg.vue- 대상 유형 → 작업지시 등록코드/작업명 → 대상 참조 → 상태 등 canonical 열 순서
- 작업명 클릭으로 정확한 row 전달
- requested 배정과 이후 단조 전이
src/components/facility/maintenance/SheetCreateWorkOrderArt.vue- 설비·공간 공용 create 전용 3xl 집중 시트
- 대상 참조·작업명 valid, dirty 저장 gate
- 설비 자산/프로퍼티 공간 정본 selector와 manual fallback
urgent|high|normal|low우선순위
src/components/facility/maintenance/SheetWorkOrderDetailArt.vueopen(workOrder)로 주입한 정확한 선택 row와 authoritative timestamp 이력- 관리코드는 우측 상단에만 작게 표시
- sheet-footer에서 선택 row의 다음 동작 emit
src/components/facility/maintenance/SheetAssignWorkOrderArt.vue- 2xl 집중 폭의 Office actor/party 단일 선택
- 저장 중 닫기·중복 제출 차단; Office scope 폐기 때만 force close
src/composables/useFacilityWorkOrders.js- 목록·participant·subject ledger의
Promise.allSettled분리 - Company·Office scope sequence, load/command sequence
- stale load success/error와 stale create/transition/pending 차단
- 목록·participant·subject ledger의
src/composables/facilityWorkOrderRepo.js- 실제 SELECT/create RPC/transition RPC 계약과 row 정규화
- 비-test no-config의 unavailable empty adapter
제품 독립성과 선택 연결
작업지시의 subjectRef는 항상 필수인 현장 참조 문자열입니다. facilityAssetId와 propertySpaceId는 선택 exact link이고 둘 다 없어도 목록·생성·단조 상태 흐름은 독립 동작합니다.
- 자산/공간 연결: 설비 화면은 facility asset, 공간 화면은 platform-core property space selector를 제공합니다. selector 실패 시 별도 경고를 표시하고 manual
subjectRef입력은 유지합니다. - 담당자 연결: actor/party directory는 optional ledger입니다. 조회 실패 시 목록·생성은 유지하고 배정만 후보 복구가 필요합니다.
- HR enrichment: participant snapshot 표시 보강만 허용합니다. HR employee/assignment를 facility repo의 필수 FK나 UI gate로 되돌리지 않습니다.
repository와 mutation 계약
list({ companyId, officeId, subjectKind })는 세 범위를 모두 query에 명시합니다.
create(input)은 현재 Company·Office와 고정 subjectKind에 다음 폼 값을 더합니다.
subjectRef,title필수facilityAssetId또는propertySpaceId선택. selector를 쓰지 않으면 둘 다nulldescription,registrationCode선택priority기본normal- 사용자 동작마다 새
requestKey
성공 행은 현재 scope 목록 선두에 중복 없이 삽입합니다. 관리코드, 초기 상태·revision·시간과 actor는 클라이언트가 입력하지 않습니다.
transition(input)은 companyId, workOrderId, 다음 toStatus, 화면 row의 expectedRevision, 배정 시 actor 또는 party ID 하나, 새 requestKey를 전송합니다. 성공 시 현재 scope 배열의 같은 ID만 교체합니다.
Office가 바뀌면 scopeSequence, loadSequence, commandSequence가 모두 증가하고 배열·pending·오류를 초기화합니다. 이전 scope 응답은 null로 끝나므로 Main은 stale 성공을 표시하지 않습니다. scope watch는 생성·상세·배정 시트를 강제 종료하고, workOrders에서 선택 ID가 사라질 때도 상세와 배정 시트를 즉시 닫습니다.
UI 상태와 게이팅
- resolving/loading: 실제 목록 조회 중 문구
- available + empty: 샘플 fallback 없는 실제 빈 상태와 생성 안내
- work-order error: 오류 +
다시 시도; 빈 상태를 함께 표시하지 않음 - unavailable: 연결 안내; create/transition 도구 숨김
- participant error: 실제 목록과 create 유지, 별도 경고와 participant retry
- subject error: 실제 목록과 create 유지, manual subjectRef fallback
requested:담당자 배정assigned:작업 시작in_progress:작업 완료completed:검수 완료verified:종결, action 없음
전이 중인 행과 상세 action은 같은 transitioningId로 중복 실행을 차단합니다. 목록과 상세는 같은 row 객체를 전달하며, 성공한 transition은 양쪽에 같은 서버 응답을 반영합니다. 정적 샘플 상세, fake 업체·비용, checkbox, 무동작 검색·필터·다운로드·페이지네이션을 canonical graph에 다시 추가하지 않습니다.
테스트
src/composables/__tests__/facilityWorkOrderRepo.spec.js: 범위 query, RPC payload, normalize, error/no-config 계약src/composables/__tests__/useFacilityWorkOrders.spec.js: partial ledger와 Office stale load/create/transition guardsrc/composables/__tests__/facilityWorkOrderMigration.spec.js: schema/RLS/RPC/상태 머신/감사 정적 계약src/composables/__tests__/facilityWorkOrderUiContract.spec.js: 공용 canonical UI와 exact selected actionsrc/composables/__tests__/facilityWorkOrderReleaseContract.spec.js: redirect query/hash, nav/AI dead link 0, fake UI 제거src/components/facility/maintenance/__tests__/FacilityWorkOrderSheets.spec.js: create valid/dirty/payload, selected detail/actionsupabase/tests/facility_work_orders_smoke.sql: disposable DB 실행형 계약src/composables/__tests__/facilityClosureLoopMigration.spec.js: stable target, source snapshot, grant 정적 계약supabase/tests/facility_inspection_work_order_closure_loop_smoke.sql: exact target과 점검 폐쇄루프 rollback smoke