HBSA210_Organizations (목록·상세·설정·역할·관리자)
(Hereby) 시스템 관리 > [[HBSA200]] > Organizations
| 앱 | System Admin (포트 4100) |
| 부모 화면 | [[HBSA200]] |
| 대상 사용자 | 플랫폼 운영자(OPERATOR) |
| 프로토타입 | TBU |
| 관련 정책 | [[POL_권한(RBAC)]] · [[POL_AI안전경계]] |
| Status | draft (코드 기반 — 라이브 실사 불가: dev 라우트 AccessDenied 격리, 2026-08-25 확인) |
| Owner | 카나 |
| 하위 화면 | [[HBSA211]] Provision Modal |
개요
전 엔드포인트를 fan-out으로 합친 조직(병원) 목록 + 조직 상세 패널. 상세에서는 조직 기본정보·상태 변경, 5개 설정 카드(Password Policy / Self-Editable Fields / Login Methods / AI Assistant), 역할(Roles) 테이블, 관리자(System Admin Accounts) 테이블을 관리한다. 모든 쓰기는 ?endpoint= 라우팅 + API systemProcedure에서 감사된다.
문서 히스토리
| 날짜 | 작성자 | 팀 | 변경 내용 |
|---|---|---|---|
| 2026-08-25 | 카나 | 콸 | 최초 작성 (redesign PR #583 코드 census 기반, 라이브 미실사) |
| 2026-09-02 | 카나 | PM | 멀티 엔드포인트 시 조직 탭의 엔드포인트 컨텍스트 보존 반영(#606 머지 9/1, +785줄) — 조직 행 액션이 해당 조직의 소속 엔드포인트로 라우팅되도록 수정. 세부 UI 변화는 코드 기준·라이브 격리로 TBU |
| 2026-09-21 | 카나 | PM | 조직 AI 블록에 시트 모듈 토글·월 토큰/일 호출 한도(조직 타임존 경계, 1cfa01e #810)·조직 상세 aiUsage 표시(18f766b #815)·CS 리포트 「배포대기」(awaiting_release) 열림 상태 + 상세 AI 행(0572fd06 #799) 반영 — 커밋 근거, 라이브 실사 이월(TBU) |
| 2026-09-23 | 카나 | PM | 조직 목록 서버 페이징·서버 검색 반영(DS 표준 페이저 30/50/100, 이름/코드 ILIKE·400ms 디바운스, 엔드포인트별 최대값 기준 페이지 수, 표와 조직 셀렉터 풀 분리, 433af92 #854) · CS 리포트 공유 딥링크 #cs-reports/<엔드포인트>/<id>·「링크 복사」·처리 폼 현재 상태 프리필 반영(8b8d7b7 #855) — 커밋 근거, 라이브 실사 이월(TBU) |
| 2026-09-23 | 카나 | PM | 조직 AI 블록 모듈별 모델 오버라이드 편집(비우면 기본 모델, 경량 모델 전환 MED-177 ② 운영 시험용) 반영 — AI 모니터링 요약 「적용 모델」과 세트(3c66d8b #863), 커밋 근거·라이브 실사 이월(TBU) |
| 2026-10-01 | 카나 | PM | 조직 AI 블록에 직원 앱 어시스턴트 모듈(켬/끔·조직 월 토큰·하루 호출·1인당 월 토큰/하루 호출·모델 오버라이드) 반영(bccb5ada, #925) — 커밋 근거, 라이브 실사 이월(TBU) |
| 2026-10-02 | 카나 | PM | CS 리포트 상세 「AI 대화 열기」(AI 모니터링 대화 딥링크·신고 답변 강조) 신설 A2-2(598ee51b, #1000) · Admin 모달 비밀번호 라벨·검사를 병원 비밀번호 규칙 연동, 첫 로그인 변경 강제 30(c6347029·382eec17, #995) — 커밋 근거, 라이브 실사 이월(TBU) - 카나/PM |
| 2026-10-03 | 카나 | PM | 조직 AI 블록에 「문서 기반 사용법 안내」 즉시 저장 토글 신설 85(기본 off·저장 중 표시·실패 롤백, e13018b7, #1023) — 커밋 근거, 라이브 실사 이월(TBU) - 카나/PM |
| 2026-10-08 | 카나 | PM | (10/7 머지분) PR #1079(7c24b4d) 반영: 「조직 수정」이 settings 전체(ai.modules 포함)를 보내면 500(operator is not unique, PostgreSQL 42725)이 나던 결함 수정 — 설정 패치 SQL의 jsonb ai 패치를 괄호로 감싸 연산자 우선순위(-가 ->보다 높음) 오류 제거. 같은 원인으로 modules 없는 ai 패치가 기존 ai 설정을 조용히 지우던 경로도 함께 수정(2026-10-07 운영 장애). UI 변화 없음 — 커밋 근거 |
| 2026-10-09 | 카나 | PM | (10/8 머지분) PR #1121 반영: 조직 상세 「Messenger Encryption」 카드(86 신설) · PR #1123 반영: capabilities actions 상한 64→256(대화 복구 action 66개 추가로 자기 응답 검증 실패 → 엔드포인트 INCOMPATIBLE 차단 결함, API·system-admin 동시 배포 필요 — UI 변화 없음 비고) · #1121 동반 수정: serviceProcedure 대화 복구 action 6개 매핑 누락으로 복구 호출 전부 실패하던 결함 — 커밋 근거, 라이브 실사 불가(운영 콘솔) |
| 2026-10-21 | 카나 | PM | (10/20 머지분) #1269(2602142) 관리자 「delete」 분리 — 기본 = 권한 해제(revoke), 직원 삭제 = 별도 danger 버튼(remove), 마지막 관리자 가드 양쪽 적용, 소프트 삭제 직원 재추가 시 레코드 복구(A1 갱신) · #1266(5ffa868) 관리자 추가 「기존 계정 연결」 출처(A0 갱신) — 커밋 근거, 라이브 실사 불가(운영 콘솔). 같은 날 신설 「계정 관리」 탭은 미채번 신규 화면 — HBSA000 히스토리 참조(채번 제안 HBSA290) |
Data I/O
Server → Client
| 변수 | 소스(systemProcedure) | 값 없을 때 | 비고 |
|---|---|---|---|
organizations[] | platform.systemOrganizations (fan-out) | Empty row | code/name/type/status/employeeCount/createdAt + endpointId 태깅 |
orgList*(표 전용 상태) | platform.systemOrganizations (page/pageSize/search 관통) | Empty row | 조직 셀렉터 풀 organizations 와 분리 — 페이지 전환이 다른 탭 드롭다운을 비우지 않음(433af92) · 개별 변수명 TBU |
selectedOrgDetail.organization | platform.systemOrganizationDetail | - | id/name/code/legalName/type/size/medicalField/timezone/fiscalYearStart/subscriptionTier/settings |
selectedOrgDetail.roles[] | 상세 응답 | "No roles found" | code/name/type/permissions.length/isActive |
selectedOrgDetail.adminEmployees[] | 상세 응답 | "No admin accounts found" | employeeNumber/name/email/status |
allPermissions[] | platform.systemPermissions | - | 역할 모달 권한 체크리스트 |
Client → Server
| 액션 | 콘솔 REST | systemProcedure | 권한 게이트 |
|---|---|---|---|
| 목록/새로고침 | GET /api/organizations?page&pageSize&search | systemOrganizations (fan-out, 엔드포인트별 ORGANIZATIONS_READ 로 관통) | OPERATOR |
| 조직 셀렉터 풀 조회 | GET /api/organizations (파라미터 없음) | systemOrganizations (fan-out) | OPERATOR — 기존 동작 유지 |
| 상세 진입 | GET /:id?endpoint= | systemOrganizationDetail | OPERATOR |
| 상태 변경 | PUT /:id/status | systemSetOrganizationStatus | OPERATOR, audit |
| 정보 수정 | PUT /:id | systemUpdateOrganization | OPERATOR, audit |
| 삭제 | DELETE /:id (confirmName) | systemDeleteOrganization | OPERATOR, audit, 소프트삭제 캐스케이드 |
| 설정 저장(pw/sef/lm/ai) | PUT /:id (settings.*) | systemUpdateOrganization | OPERATOR, audit |
| Seed Defaults | POST /api/provision/seed-defaults/:orgId | systemSeedOrgDefaults | OPERATOR, audit |
| Seed Item Codes | POST /api/provision/seed-item-codes/:orgId | systemSeedOrgItemCodes | OPERATOR, audit |
| 역할 CRUD | POST/PUT/DELETE /:orgId/roles | systemCreate/Update/DeleteOrgRole | OPERATOR, audit |
| 관리자 CRUD | POST/PUT/DELETE /:orgId/admins | systemCreate/Update/DeleteOrgAdmin | OPERATOR, audit |
코드 근거: tabs/organizations.html, server/routes/organizations.ts, routes/roles.ts, routes/admins.ts, routes/provision.ts.
화면 플로우
메인 화면 사양표 — 목록 + 상세
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 화면 진입 조건 | - | activeTab === 'organizations'. 조건1 [!tabLoading && !selectedOrg] 목록 / 조건2 [selectedOrg && selectedOrgDetail] 상세 | - | |
| 01 | 초기 상태 | Output | 목록 상단 "Total: {organizations.length}" + 필터 인풋 | - | |
| 10 | 목록 헤더 | - | 필터 placeholder "Filter by name, code, status..." / "refresh" 버튼 / "+ New Organization" 버튼 | orgFilter, openProvisionModal() | |
| 20 | 조직 테이블 | List | [List] 컬럼 "code"/"name"/"type"/"status"/"employees"/"created". 행 클릭 → selectOrg(o.id) 상세 진입 | filteredOrganizations | code=orange, type 없으면 "—", createdAt 날짜부만 |
| 20-P | ㄴ 서버 페이징 | Pager | • 목록이 100건 고정 + 클라이언트 필터라 100건 밖 조직은 보이지도 검색되지도 않던 것을 서버 페이징으로 교체 • DS 표준 페이저(30/50/100) 적용. 집계 라우트가 page/pageSize/search 를 엔드포인트별 ORGANIZATIONS_READ 로 관통• 페이지 수 = 엔드포인트 합이 아니라 엔드포인트별 최대값 기준(빈 페이지 방지 — 단위 테스트로 고정) • 표( orgList*)와 조직 셀렉터 풀(organizations)을 분리해 페이지 전환이 다른 탭 드롭다운을 비우지 않음. 파라미터 없는 셀렉터 풀 호출은 기존 동작 유지 | GET /api/organizations?page&pageSize&search · systemOrganizations | 신설 (코드 반영: 433af92, #854) · 01·10·20 의 클라이언트 필터/전건 카운트 서술은 이 항목으로 대체 — 화면 문구 실측 갱신 대기 · TBU: 라이브 실사 이월 |
| 20-S | ㄴ 서버 검색 | Input Box | • 목록 검색어를 서버로 보내 이름/코드 ILIKE 로 조회 • 입력 400ms 디바운스 후 요청. 검색 결과도 위 페이저 기준으로 페이징 | search 파라미터 | 신설 (코드 반영: 433af92, #854) · 기존 클라이언트 orgFilter 대체 · TBU: 라이브 실사 이월 |
| 21 | ㄴ status 배지 | Badge | ACTIVE=green / TRIAL=primary / INACTIVE·SUSPENDED=gray | - | |
| 20-E | ㄴ Empty | Text | "No organizations yet. Use "New Organization" to provision one." | - | |
| 30 | 상세 헤더 | - | "back" / 조직명·code / "Edit Info"([[#Org Edit 모달 사양표]]) / "Delete"(red) | closeOrgDetail() | |
| 31 | ㄴ Delete | Button | 클릭 → deleteOrganization(id, name) → confirmName 일치 검사 후 소프트삭제(조직+직원+owner 계정, 토큰 무효화) | systemDeleteOrganization | owner는 앱 내 삭제 불가 → 이 경로로만 |
| 40 | Organization 정보 | Output | id/name/code/legalName/type/size/medicalField/timezone/fiscalYearStart/subscriptionTier (값 있는 필드만 표시) | selectedOrgDetail.organization | 값 없으면 hide |
| 41 | ㄴ status 변경 | Dropdown | ACTIVE/INACTIVE/SUSPENDED/TRIAL. @change → updateOrgStatus() 즉시 반영 | systemSetOrganizationStatus | 유효값 외 400 |
| 50 | Password Policy 카드 | - | FORMAT: "숫자만 (0-9)"/"소문자 + 숫자 (a-z, 0-9)"/"대소문자 + 숫자 (A-Z, a-z, 0-9)" · LENGTH(4-20) · "Save". 안내 "임시 비밀번호 생성 시 적용됩니다" | settings.passwordPolicy | 저장 중 "saving..." |
| 60 | Self-Editable Fields 카드 | Checkbox | "프로필 사진"/"전화번호"/"주소"/"비상연락처"/"계좌정보" 체크박스 + "Save". 안내 "직원이 내정보에서 직접 수정할 수 있는 항목을 설정합니다" | settings.selfEditableFields | |
| 70 | Login Methods 카드 | Checkbox | "비밀번호 (Password)"/"휴대폰 인증번호 (SMS OTP)" + "Save". 최소 1개 필수(0개 시 alert "최소 하나 이상의 로그인 방법을 선택해야 합니다.") | settings.loginMethods | SMS OTP는 직원 authMethods에 phone_otp 포함 시만 활성 |
| 80 | AI Assistant 카드 | Toggle | "AI 어시스턴트 사용" 체크 + "MONTHLY TOKEN LIMIT"(placeholder "무제한") + "Save". 안내 "기본 off — 켠 조직만 AI 채팅 위젯이 노출... ai:execute 권한 필요" | settings.ai | [[POL_AI안전경계]] |
| 81 | ㄴ Sheet 모듈 토글·한도 | Toggle/Input | • AI 블록에 시트 어시스턴트 모듈 설정 추가 — settings.ai.modules.sheet = { enabled, monthlyTokenLimit?, dailyCallLimit? }(core Zod 스키마로 정규화)- enabled OFF: 해당 조직 시트 턴을 서버가 거절하고 위젯도 스스로 숨음(ai.status가 modules 반환)- monthlyTokenLimit / dailyCallLimit 값 없음: 조직 전체 한도만 적용• 한도 검사 3겹 = 조직 월 토큰 + 시트 모듈 월 토큰 + 시트 일 호출. 월·일 경계는 조직 타임존(기존 UTC 월 검사 대체) | [[HBAD110_AI 어시스턴트]] · Organization.settings.ai.modules.sheet | 신설 (코드 반영: 1cfa01e, #810) · TBU: 라이브 실사 이월 |
| 82 | ㄴ aiUsage 표시 | Output | • 조직 상세에 AI 사용량(aiUsage)을 표시 — 한도 검사와 같은 숫자를 노출- 값 없음: 사용 이력 없는 조직 표기 = TBU | system-admin-organization.service | 신설 (코드 반영: 18f766b, #815) · TBU: 라이브 실사 이월 |
| 83 | ㄴ 모델 오버라이드 편집 | Input | • AI 블록에서 모듈별로 쓸 AI 모델을 조직 단위로 바꿔 끼우는 입력 — 비워 두면 기본 모델 사용 • 목적: 경량 모델 전환(MED-177 ②)을 운영 조직에서 시험·판단 — 바꾼 결과는 AI 모니터링 요약의 「적용 모델」로 확인 - CASE01 [값 없음]: 기본 모델(플랫폼 설정) 적용 | system-admin-ai.service · [[HBSA200_시스템 관리자]] AI 모니터링 「적용 모델」 | 신설 (코드 반영: 3c66d8b, #863) · TBU: 라이브 실사 이월 |
| 84 | ㄴ 직원 앱 어시스턴트 모듈 | Toggle/Input | • "직원 앱 어시스턴트 사용" 체크 + 조직 한도 2(월 토큰·하루 호출, placeholder "무제한", 현재 "이번 달 N 토큰"·"오늘 N회") + 1인당 한도 2("PER EMPLOYEE · MONTH TOKENS" placeholder "기본 150,000" / "PER EMPLOYEE · DAILY CALLS" placeholder "기본 40") • 모델 오버라이드 입력 "직원 앱 어시스턴트 (employee_app)"(placeholder "기본") • 「AI 어시스턴트 사용」(마스터)과 함께 켜야 동작, 켬/끔은 병원 관리자 설정에서도 변경 가능 · 한도·모델은 여기서만 | settings.ai.modules.employeeApp · [[HBAD110_AI 어시스턴트]] 120 · [[HBEA500_더보기]] 37 | 신설(bccb5ada, #925) · 1인당 한도는 비우면 서버 기본값(무제한 아님) · TBU: 라이브 실사 |
| 85 | ㄴ 문서 안내(Guidance) 토글 | Toggle | • AI 블록에 스위치 「문서 기반 사용법 안내」 — settings.ai.modules.guidance.enabled, 기본 off• 체크 변경 → 즉시 저장(별도 Save 버튼 없음), 저장 동안 "저장 중..." 표시 + 스위치 disabled - CASE01 [저장 실패]: 스위치를 원래 값으로 되돌림(롤백) • 안내문 "조직별로 즉시 저장돼요. 조직 AI와 문서 검색 연결, 운영 검토가 준비된 경우에만 실제 안내가 제공됩니다." — 토글 on이어도 조직 AI 켜짐·문서 검색 연결·운영 검토 버전 충족 시에만 실제 안내 동작 | settings.ai.modules.guidance · [[HBAD110_AI 어시스턴트]] CASE07 · [[HBSA200]] 20-10 | 신설 (코드 반영: e13018b7, #1023 — #993 문서 안내의 조직별 opt-in) · TBU: 라이브 실사 이월 · (10/8, #1079 7c24b4d) 설정 패치 SQL 수정 — ai 설정 저장 정상화(아래 히스토리) |
| 86 | Messenger Encryption 카드 | Card | • (10/8, #1121, a40de5b0) 조직 상세에 「Messenger Encryption」 카드 — 복구 키 유무 표시 + 확인·최근 재인증 뒤 대화 암호화 켜기(내부 action organization:messenger-encryption:update, enabled: true만) • 일방향: 한 번 켜면 끌 수 없음(끄면 기기가 방 키를 못 맞춰 암호문을 못 엶). 병원 관리자 organization.updateSettings가 messenger를 보내도 저장된 값 유지(서버가 무시) • 켜진 조직의 사용자 가시 동작은 [[HBEA300_메신저]] ㄴ45, 관리자 대화 복구는 HBAD310(채번 제안) | organization settings(messenger) · chat-crypto | 신설 (#1121) · 라이브 실사 불가(운영 콘솔) — 커밋 근거 |
| 90 | Roles 섹션 | List | [List] 컬럼 code/name/type/permissions/active/actions. "Seed Defaults"/"Seed Item Codes"/"+ Add Role" 버튼 | selectedOrgDetail.roles | |
| 91 | ㄴ Seed Defaults | Button | 클릭 → ask "기본 권한과 역할을 생성하시겠습니까?\n(이미 존재하는 항목은 건너뜁니다)" → seedDefaults() | systemSeedOrgDefaults | design: 기존 역할 권한을 카탈로그로 동기화(교체) |
| 92 | ㄴ Seed Item Codes | Button | 클릭 → ask "기본 항목코드(수당/공제)를 등록하시겠습니까?\n(이미 존재하는 코드는 건너뜁니다)" → seedItemCodes() | systemSeedOrgItemCodes | skip-if-exists |
| 93 | ㄴ 역할 행 액션 | Button | "edit" → Role 모달 / "delete" → confirm/cancel 인라인. SUPER_ADMIN은 delete 미노출 | systemDeleteOrgRole | SUPER_ADMIN 삭제 금지 |
| 90-E | ㄴ Empty | Text | "No roles found" | - | |
| A0 | System Admin Accounts 섹션 | List | [List] 컬럼 employee #/name/email/status/actions. "+ Add Admin" - (10/20, #1266 5ffa868) 관리자 추가에 「기존 계정 연결」 출처 추가 — 회원 계정(Account)을 검색해 이 조직의 관리자 직원으로 생성·연결하고, 이미 이 조직의 직원이면 관리자로 승격. 권한 organization_admin:manage (계정 관리 탭의 ACCOUNT_EMPLOYEE_CREATE 액션 공유: 실계정만 · 조직당 1명 · 사번 중복 거부) | selectedOrgDetail.adminEmployees | 커밋 근거 · 운영 콘솔 실사 불가 |
| A2 | ㄴ CS 리포트 「배포대기」 상태 | Badge | • 시스템 관리 콘솔 CS 리포트 처리 상태에 「배포대기」(awaiting_release) 추가 — 수정은 끝났지만 버전 패치가 아직 배포되지 않은 신고를 구분- 열림 상태: 콘솔 「열림 전체」 필터에 포함. 종결이 아니므로 resolvedAt 미기록 · 사용자 알림 없음- 전이: received/triaged/in_progress → awaiting_release → resolved. 배포 전 재작업은 in_progress로 되돌림 - 배포 후 운영자가 「해결」로 바꾸는 시점에만 사용자 처리 완료 알림 발송("적용됐다" 확인이 한 곳에서만 나감) - 컬럼이 varchar(20)이라 마이그레이션 없음 • 리포트 상세에 AI 행 표시(AI 답변 「문제 신고」로 들어온 건) | CsReportStatus.AWAITING_RELEASE · [[HBEA110_Shell·탭바·알림]] · [[HBAD110_AI 어시스턴트]] | 신설 (코드 반영: 0572fd06 #799 · 18f766b #815) · ⚠ CS 리포트 콘솔 탭은 전용 사양서 부재 — 신규 화면 작성은 보고만 · TBU: 라이브 실사 이월 |
| A2-1 | ㄴ CS 리포트 딥링크·처리 폼 | Link/Form | • CS 리포트 상세에 공유 가능한 해시 딥링크 #cs-reports/<엔드포인트>/<id> 와 「링크 복사」 버튼 추가- 링크로 들어오면 로그인 후 해당 리포트가 바로 열림 - 브라우저 뒤로가기 = 모달 닫기(조직 상세와 동일 패턴·헬퍼 재사용) • 처리 폼이 항상 '확인중/우선순위 유지'로 시작하던 것을 현재 상태·우선순위 프리필로 변경 - 실제 변경이 있을 때만 「상태 변경」 버튼 활성( priority 는 바뀐 경우에만 payload 포함)• 클라이언트 로그 response 펼쳐보기는 수집기가 응답 본문을 저장하지 않아(요약만) 제외 | CsReportStatus · [[HBEA110_Shell·탭바·알림]] | 신설 (코드 반영: 8b8d7b7, #855) · ⚠ CS 리포트 콘솔 탭은 전용 사양서 부재 — 본 절에만 기록 · TBU: 라이브 실사 이월 |
| A2-2 | ㄴ CS 리포트 「AI 대화 열기」 | Link | • AI 답변 카드 「문제 신고」로 들어온 리포트 상세 상단에 info 안내 "AI 어시스턴트 답변에서 보낸 신고예요" (+ " · {모듈명}") 와 「AI 대화 열기」 버튼 • 클릭 시: 리포트 모달 닫힘 → AI 모니터링 탭 전환 → 해당 대화 상세 오픈(딥링크 #ai-monitor/<ep>/<org>/<conversation>, href 복사 가능)- 신고된 답변 말풍선에 테두리 강조 + 라벨 "CS 리포트에서 신고된 답변" · 스크롤 이동, 상세 닫으면 강조 해제 - CASE01 [엔드포인트 ai:read 없음]: 버튼 미노출, 아래 컨텍스트 행의 id만 표시 | csReportAiLink() · context.ai · [[HBSA200]] 20-10 | 신설 (코드 반영: 598ee51b, #1000) · TBU: 라이브 실사 이월 |
| A1 | ㄴ 관리자 행 액션 | Button | "edit" → Admin 모달 / (10/20, #1269 2602142) "delete" 동작 분리: - 기본 「delete」 = 관리자 권한만 해제(mode=revoke) — 종전의 「직원 소프트 삭제」 동작을 폐기 - 직원 완전 삭제는 별도 버튼 + danger 확인창(mode=remove, ?mode=remove일 때만 삭제 전송 — 구 호출은 자동으로 안전한 revoke)- 마지막 관리자 가드는 두 모드 모두 적용 - 동반 수정: 소프트 삭제된 직원이 같은 계정 재추가 INSERT를 막던 운영 23505 → 재추가 시 기존 레코드 복구(deletedAt 해제·ACTIVE·같은 직원 id로 이력 유지), link 경로는 409 안내 | systemDeleteOrgAdmin (mode=revoke/remove) | 마지막 관리자 삭제 방지(API) · 커밋 근거 · 운영 콘솔 실사 불가 |
| A0-E | ㄴ Empty | Text | "No admin accounts found" | - | |
| B0 | 값 없음 처리 | - | type/optional 필드 "—", 리스트 0건 Empty row, medicalField 등 값 없으면 상세에서 hide | - | |
| B1 | 에러·실패 | - | 목록 로드 실패 → tabError 배너([[HBSA200]]). mutation 4xx → 원 상태코드 보존(409/404/400/403). 실측 토스트 TBU | callOrgScopedMutation |
서브 화면 / 모달 사양표
Admin 모달 사양표 (Create / Edit)
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | showAdminModal. 타이틀 case01 [create] "Create Admin Account" / case02 [edit] "Edit Admin Account" | openCreateAdmin()/openEditAdmin() | |
| 10 | 이름 | Input Box | "LAST NAME *"(placeholder "김") / "FIRST NAME *"(placeholder "관리자") | adminForm | |
| 20 | 계정 | Input Box | "EMAIL *"(placeholder "admin@example.com") / "EMPLOYEE # *"(placeholder "ADMIN001", edit 시 disabled) | - | |
| 30 | 비밀번호 | Input Box | • 라벨이 고른 병원의 일반 비밀번호 규칙을 안내: create "PASSWORD * — {규칙}" / edit "NEW PASSWORD — {규칙}"(placeholder "leave blank to keep") - {규칙} 예: "8자 이상, 대문자·소문자·숫자·특수문자 포함" (병원 settings.userPasswordPolicy, 없으면 기본 규칙)• 제출 시 서버와 같은 규칙으로 먼저 검사 → 위반 시 red 배너( adminError) 예: "비밀번호는 {N}자 이상이어야 해요." · edit에서 비워 두면 검사 안 함• 콘솔에서 정한 비밀번호(생성·재설정)는 첫 로그인 때 변경 강제( mustChangePassword) | 원문 TLS → API bcrypt · [[HBAD270_설정 (조직 설정·내 정보)]] | 갱신 (코드 반영: c6347029·382eec17, #995) · minlength=8 제거 · TBU: 라이브 실사 이월 |
| 31 | ㄴ PHONE | Input Box | placeholder "010-0000-0000" | - | |
| 40 | STATUS(edit 전용) | Dropdown | ACTIVE/INACTIVE/SUSPENDED | - | edit 모드만 노출 |
| 50 | 제출 | Button | create "Create" / edit "Save" → saveAdmin(). 저장 중 "saving...". 에러 시 red 배너(adminError) | systemCreate/UpdateOrgAdmin |
Role 모달 사양표 (Create / Edit)
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | showRoleModal. 타이틀 create "Create Role" / edit "Edit Role" | - | |
| 10 | 기본 | Input Box | "CODE *"(placeholder "CUSTOM_ROLE", edit disabled) / "NAME *"(placeholder "커스텀 역할") / "TYPE" 셀렉트(system/team/custom) | roleForm | |
| 20 | Permissions | Checkbox | "Permissions ({n} selected)" + "select all"/"clear". allPermissions 2열 체크리스트(code + name). @change → togglePermission() | systemPermissions | 저장 시 permissionCodes 전체 교체 |
| 30 | 제출 | Button | create "Create" / edit "Save" → saveRole(). 중복 코드 409. 에러 red 배너(roleError) | systemCreate/UpdateOrgRole |
Org Edit 모달 사양표
| 번호 | 항목/기능명 | 타입 | 사양 및 기능 설명 | 연관/영향 범위 | 비고 |
|---|---|---|---|---|---|
| 00 | 노출 조건 | - | showOrgEditModal. 타이틀 "Edit Organization" | openOrgEditModal() | |
| 10 | 식별 | Input Box | "NAME *" / "CODE *" / "LEGAL NAME" | orgEditForm | |
| 20 | 분류 | Dropdown | "종류"(의원/병원/종합병원/상급종합병원/요양병원/정신병원/치과병원/한방병원/조산원/기타) / "병상 수"(30미만/30~99/100~299/300이상) / "진료 분야"(placeholder "재활 전문, 노인 요양 중심 등") | type/size/medicalField | |
| 30 | 연락 | Input Box | EMAIL / PHONE / WEBSITE / FAX | - | |
| 40 | 로케일 | Input Box | TIMEZONE / LOCALE / CURRENCY / "FISCAL YEAR START (month)"(1-12) | - | |
| 50 | 제출 | Button | "Save" → saveOrgEdit(). 에러 red 배너(orgEditError) | systemUpdateOrganization |
권한 / 상태 요약
| 시나리오 | 트리거 | 결과 | 비고 |
|---|---|---|---|
case01 [상태 변경] | status 셀렉트 | 즉시 API 반영 + audit | |
case02 [삭제 confirmName 불일치] | Delete 확인 | 400 거부 | 소프트삭제 방지 |
case03 [역할 중복 코드] | Create Role | 409 | |
case04 [Seed Defaults] | 확인 | 기본 권한/역할 동기화 | 기존 권한 카탈로그로 교체 주의 |
case05 [권한별] | OPERATOR | 전 org 전권 / SUPPORT는 발급 grant 범위만 | [[POL_권한(RBAC)]] |
OQ
- 설정 카드 Save 성공/실패 UI 피드백 실측 = TBU
- subscriptionTier·settings 스키마 전체 필드 = 부분만 코드 노출, 나머지 TBU
- fan-out 부분 실패 시 목록에 표시되는 조직 범위(성공 엔드포인트만) UI 롤업 = 코드상 endpointStatuses 전달, 화면 표기 위치 TBU