Clinic EMR

05. 도메인 모델 (as-is) — 닥터팔레트에서 관찰한 엔티티·열거값·상태 머신

상태: 통합본 v1 (2026-09-30) · 작성: S4 통합 목적: 닥터팔레트 공개 자료(제품소식·고객사례·기능 페이지·매뉴얼 영상 프레임)에서 관찰된 데이터 구조를 한곳에 모은다. 우리 앱의 to-be 모델(docs/design/domain-model.md)을 확정하기 직전의 근거 자료다. 범위: 엔티티·필드·열거값·상태 머신을 다룬다. 규칙은 06-business-rules.md, 흐름은 04-workflows.md에 있다.

표기

  • 확신도: 확인 = 화면·원문에 직접 보인다 / 추정 = 정황으로 판단했다 / 미확인 = 자리만 보이고 내용은 모른다.
  • 출처 태그: A1~A6 = 텍스트 분석 파일, V1~V9 = 매뉴얼 영상 분석 파일, V#:영상-초 = 프레임, news#idx = 제품소식 게시글 번호.
  • 필드명은 구현 관점에서 영문 camelCase로 옮겼다. 괄호 안은 화면에 보인 한글 라벨이다.
  • 버전 표기: v2.4 = 2022-09 매뉴얼 영상(V1~V8), 2024 = 플래너 개편(news#124177982), 2025 = 2025 화면(A3·A4·A6).

0. 전체 구조 한눈에

닥터팔레트의 데이터는 환자(Patient) — 내원(Visit) — 차트 칸들을 축으로 도는 구조다. 예약(플래너)은 내원 앞에, 수납·문서·청구는 내원 뒤에 붙는다. 원내 동선은 내원의 위치(대기열) × 상태 두 축으로 표현한다 [A1 구현 시사점, V3 R17].

erDiagram
  Hospital ||--o{ Member : "소속(멀티 병원)"
  Hospital ||--o{ Room : "대기열·공간"
  Hospital ||--o{ Patient : owns
  Patient ||--o{ PatientTagLink : tags
  Patient ||--o{ FamilyLink : family
  Patient ||--o{ ConsentRecord : consents
  Patient ||--o{ IdentityVerification : "본인확인"
  Patient ||--o{ EligibilityCheck : "자격조회"
  Patient ||--o{ PatientNote : "환자기록 스레드"
  Patient ||--o{ Plan : "예약(플랜)"
  PlanCategory ||--o{ Plan : "열·색"
  Schedule ||--o{ SchedulePeriod : "기간 규칙(v2.4)"
  Schedule ||--o{ Plan : "슬롯(v2.4)"
  Plan |o--o| ChartDraft : "차트 초안"
  Plan |o--o| Visit : "접수 전환"
  ExternalBooking |o--o| Plan : "네이버·구글·여신"
  ReceptionRequest |o--o| Visit : "태블릿 접수신청"
  Patient ||--o{ Visit : visits
  Visit ||--o{ QueueEntry : "위치×상태 이동"
  Room ||--o{ QueueEntry : hosts
  Visit ||--o{ ChartSection : "역할별 기록 칸"
  Visit ||--o{ Diagnosis : "상병"
  Visit ||--o{ OrderLine : "진단 및 처방"
  Visit ||--o{ Task : "할 일"
  Visit ||--o{ VisitImage : "≤30장"
  Visit ||--o{ VitalSign : "임상관찰"
  Visit ||--|| Charge : "진료비 산정"
  Visit ||--o{ Payment : "수납·환불"
  Visit ||--o{ IssuedDocument : "문서발급"
  Visit ||--o{ CouponApplication : "쿠폰"
  Patient ||--o{ PointLedger : "포인트"
  Patient ||--o{ PrepaidLedger : "선납금"
  TicketProduct ||--o{ PatientTicket : "판매"
  Patient ||--o{ PatientTicket : owns
  PatientTicket ||--o{ TicketUsage : "회차 차감"
  OrderLine |o--o| TicketUsage : "사용 오더"
  Visit ||--o{ MessageDispatch : "접수 안내"
  Plan ||--o{ MessageDispatch : "예약 알림"
  ClaimBatch ||--o{ ClaimStatement : "명세서"
  Visit ||--o{ ClaimStatement : "원천"

1. 테넌시·조직·권한

엔티티 필드(관찰) 확신도 출처
Hospital id, name, logo, appVersion(화면 좌하단 표기) 확인 V1, V2, V9
HospitalInfo(설정 > 병원정보) 탭 병원정보 · 인증정보 · 보안관리 · 연동정보 · 서비스이용현황; 서류용 상호·주소·대표자, 직인 이미지, 대표자 인장 확인(탭·서식) / 필드 추정 A4 설정, V3 서식, A1 문서
Staff/User id, name, initials(아바타 2글자), avatarColor, loginEmail, licenseNo·licenseType(서류), 서명/인장 이미지, title(직책: 원장…), deptId 확인 V1, V3 R14, A3 직원 디렉터리
Member(병원 소속) userId, hospitalId, jobTitle(직군), dept(부서), roleIds[] 확인(권한 화면) A4 권한
Department name(의료팀·상담팀·코디팀·피부팀·간호팀) 확인 A3 만족도조사
Role(권한 그룹) name, isDefault(기본권한*), 멤버 수. 예: 소유자 · 진료 · 원무 · 원무관리자 · 멤버관리자 · 기본권한 확인 A4 권한(news#160846449)
RolePermission roleId, module(홈·차트·검사·플래너·통계…), action(아래 표) 확인 A4 권한
SecurityAdmin userId, grantedAt. IP 제한 예외 대상 확인 A4 IP
IpAllowRule ip, placeName(본점·원장님 자택…), createdBy, createdAt. 최대 100개, 관리 이력 확인 A4 IP(news#22856912)
PrivacyAccessLog / PrivacyDestroyLog 설정 하위 메뉴 개인정보조회이력, 개인정보파기이력 확인(메뉴) / 필드 미확인 A4 설정
DeviceSetting deviceId, cidModalEnabled(이 PC에서만 CID 팝업) 확인(토글) / 식별 방식 추정 A2 CID

권한 매트릭스(2025, 관찰된 세부 동작) [A4 권한 — 확인]

모듈 세부 동작
홈 병원 업무 수정·삭제, 공지사항 수정·삭제
차트 차트 삭제 · 진료기록 조회/수정 · 이미지 조회/수정 · 진단 및 처방 조회/수정 · 간호기록 조회 · 간호기록 수정·삭제 · 쿠폰내역 조회/수정 · 포인트내역 조회/수정 · 수납 조회/수정 · 문서발급 조회·수정 · 다른 사용자가 작성한 환자기록 수정·삭제
검사 모듈 단위
플래너 카테고리/스케줄 수정 · 플랜 수정·취소 · 플랜 삭제
통계 인사이트 조회(월간 경영 리포트) · 매출 조회 · 차트 조회 …
  • 한 사용자가 여러 역할을 갖는지, 기본권한이 신규 멤버 기본값인지는 추정이다.
  • AI 상담 녹취 기록은 병원 관리자 + 해당 상담실장 본인만 열람한다(레코드 단위 접근 정책) [A3 "닫힌 기록" — 확인(원문)].

2. 병원 설정 마스터

엔티티 필드(관찰) 확신도 출처
Room(대기열·공간·대기리스트) id, name, kind, doctorId?(진료실 담당의 — 그룹 헤더 이니셜 배지), color, sortOrder 확인 V1 R7, V2 R1, V5 R16
VisitPurpose(방문목적) id, name(일반진료·아토피진료·검사·레이저치료·영양제·문서발급·상담…), order 확인 V1, V5, V6
SubPurpose(세부목적) id, purposeId, name(감기·복통·피부질환…). 다중 선택, 없는 방문목적도 있음(검사 → 비활성) 확인 V6 규칙
PatientTag(환자유형) name(VIP·지인추천·검색방문·주의환자·관심환자·외국인환자·연예인·국적…), color 확인 V1 R13, V9, A3
ReceptionTag(접수태그) 자유 입력 문자열 확인(필드) A3 접수 모달
Holiday date, name, isSubstitute(대체공휴일) — 내장 달력으로 추정 추정 V5 R6
WaitingScreen(대기스크린) name(요일 세트, 예 월수금), rooms[], maskName, noticeText, videoUrl, chime, voiceCall 확인 A6 S26~S28
HospitalSetting maskPatientName(대기스크린), 할 일 자동 등록, 루틴 정의, 동의서 사용, CID 연동, 네이버 예약연동… 확인(토글들) V5, A3, A6, A2

Room.kind(관찰값): 진료실(담당의 연결) · 상담실 · 레이저실/시술실 · 진료지원 · 검사실/방사선실 · 수납실 · 접수실 · 태블릿접수(가상 — 유입 채널이 대기열처럼 보임) [V1, V9 위치 그룹, A3 원내 운영].


3. 환자

3-1 Patient

필드 설명 확신도 출처
chartNo no. + 병원별 순번 정수. 등록 시 발급. PACS 환자 ID와 같음 확인 V1 R24, V2 R23
name v2.4 한글 최대 10자 → 2025-02 최대 60자(외국인 이름) 확인 V1 R1, A4(news#158666898)
rrnFront / rrnBack(암호화) 주민·외국인등록번호. 검색 결과는 뒤 첫 자리까지만, 상세 화면은 전체 표시 확인 V1 R23
hasNoRrn 주민등록번호가 없습니다. 예외 체크 확인 V1 R1, V2 R9
nationality 내국인/외국인 확인 V1
sex, birthDate 주민번호에서 파생 확인 V1
phoneMain(대표연락처), phoneEmergency(비상연락처) 확인 V1
zipCode, address1, address2 우편번호 검색. 인사이트는 동 단위 집계 확인 V1, V9
tags[] 멀티 태그 확인 V2 R12
isTemporary 임시환자(2025-02 검색 가능) — 인적사항 없이 먼저 만든 환자 확인(용어) / 의미 추정 A4 환자 검색
isNew(빨간 점) 이름 옆 빨간 점. 신환 표시로 보이나 확정 못 함 추정 V2 R4, V9
eligibilityCheckedAt 환자정보에 자격조회 완료 시각 표시 확인 V2 R10
specialCaseFlags 헤더 칩 산정특례 영유아 확인(칩) V9, A2
prepaidBalance(₩), pointBalance(P) 접수 모달 이름 툴팁에 따로 표시 확인 A3 접수 모달
lastVisitAt, firstVisitDate 검색 결과·통계 확인 V1, V4

3-2 환자 부속

엔티티 필드 확신도 출처
FamilyLink patientId, relatedPatientId, relation(형제·아빠·할머니…). 등록된 환자끼리만 연결. 헤더에 대표 가족 1~2명 + +n. 양방향 저장 여부 미확인 확인 / 양방향 미확인 V1 R12, V2 R8
ConsentRecord patientId, type(개인정보 필수 · 마케팅 선택 · 음성 녹음 및 AI 분석 선택), required, agreed, agreedAt, channel(tablet_self · staff_verbal_attest · signed_form), attestedBy?, docVersion, withdrawnAt? — 동의하지 않은 결과도 기록, 차트에 동의서로 자동 기록 확인(2026 화면) V1 R11, A3 태블릿·녹취 동의
IdentityVerification(본인확인) patientId, verifiedAt, method(실물신분증 · 모바일건강보험증 · 예외), qrNumber?, exemptReason?, verifiedBy, validUntil = +6개월 확인(2024-06) A2 본인확인
EligibilityCheck(자격조회) patientId, checkedAt, eligibilityDate(자격일자), qualification(건강보험 · 의료급여1종 …), nationality, specialNotes[](특이사항 칩), trigger(등록·접수·수동), alerts[](ITS 확진자 알림 등), rawPayload 확인 / 원문 저장 추정 V1 R2, A2, A5 R-42
VitalSign(임상관찰기록) measuredAt, temperature(°C), bpSys/bpDia(mmHg), pulse(회/min), glucoseFasting·glucosePost(mg/dL), weight(kg), height(cm). v2.4는 5종(체온·체중·신장·혈압·혈당) → 2023-06 확장 확인 V1 R10, A1 외래접수
PatientCaution(특이사항) 알러지 등 방문을 넘어 유지되는 주의사항(⚙ 설정 있음) 추정 A4 역할별 기록
FamilyHistory / PatientDrug ⋮ 메뉴 가족력 관리, 환자약품 관리 미확인 A4 ⋮ 메뉴

3-3 환자기록(직원 스레드)

엔티티 필드 확신도 출처
PatientNote id, patientId, authorId, authorRole(원무·간호·원장·영양 칩), body, mentions[staffId], createdAt, isNotice(📢 공지 — 상단엔 최신 1건만 고정, 목록 누적), noticeAt 확인 V1 R22, V2 R18, V9
NoteAck noteId, staffId, at → 메시지 하단 ✓N 확인 V2 R20
NoteBookmark noteId, staffId — 본인 전용 확인 V2 R19
Notification(멘션) type=mention, targetUserId, patientId, noteId, readAt. 문구 "{작성자}님이 {환자}님의 환자기록에서 나를 멘션했습니다." + [차트열기][✓확인] 확인 A1 환자기록
  • 환자기록은 방문과 무관하게 환자 단위로 누적된다 [A1]. 접수 모달·예약 모달의 주요기록/최근기록(최근 10건)에 재노출된다 [V1 F6, A2 접수 모달].

4. 예약 — 두 세대의 모델

닥터팔레트 예약은 두 모델이 공존·교체됐다. 우리 설계는 이 차이를 알고 골라야 한다.

구분 v2.4 스케줄 모델(2022) 2024-10 이후 플래너 모델
자원 단위 Schedule(원장·검사 등) = 예약 그리드 컬럼 PlanCategory(시술·장비·의사명 자유) = 컬럼
시간 슬롯(간격 15/20/30분 × 정원 1~5) — 시각은 슬롯에서 선택 자유 시간(시작~종료, 슬롯에 묶이지 않음). 30분 눈금 표시만
운영시간 기간·요일 규칙 + 날짜 예외(이벤트/휴진) 화면 미관찰(카테고리에 운영시간 개념 보이지 않음)
상태 예약 · 접수 · 예약취소 요청 · 확정 · 접수 · 완료 · 취소(+노쇼 칩) · 거절 · 삭제
업무 블록 없음 업무 플랜(자리비움)
외부 채널 없음 네이버(2024-02) → 구글·여신티켓(2025)
근거 V5, V6 A2(news#124177982), A3, A4, A6 S20

VOC 표에 "슬롯 구간에 묶이지 않는 자유 시간 예약", "시작·종료 시간 설정", "플래너 시간 간격 변경"이 반영 항목으로 있다 → 슬롯 모델에서 자유 시간 모델로 의도적으로 옮겼다(확인, A2 플래너).

4-1 v2.4 스케줄 모델 [V5·V6 — 확인]

엔티티 필드
Schedule id, name, color(10색: 블루·그린·옐로우·레드·핑크·퍼플·라임·하늘·바이올렛·연두), visitPurposeIds[], kind(의사/검사 — 추정), active
SchedulePeriod scheduleId, startDate, endDate?(없음 = "스케줄 지속됨"), bookingOpenPolicy(환자 예약 오픈 시간, 기본 "항상"), slotMinutes(15 기본, 관찰 15·20·30), slotCapacity(신규 기본 5, 관찰 1·2·5), skipLegalHolidays(기본 ✓), crmNotify(기본 OFF)
WeeklyHours weekday(월일), enabled, ranges[≤2]{start,end}. 신규 기본 월금 09:00–13:00·14:00–18:00, 토 09:00–13:00, 일 해제
ScheduleDateOverride scheduleId, date, type(EVENT "E" 칩 — 단일 구간 / DISABLED 휴진 회색)
Slot(계산값) scheduleId, date, start, end, capacity, bookedCount — 슬롯 카드 "HH:MM-HH:MM · n"

4-2 Plan(예약·업무 플랜) — 2024~2025 통합

필드 설명 확신도 출처
id
type PATIENT(환자 플랜) · WORK(업무 플랜: 자리비움·메모) 확인 A2 플래너, A3
patientId? / guestName·guestBirthDate·guestSex 신환 예약은 환자 레코드 없이 게스트로 저장(빨간 점, 환자 검색 탭에 안 나오고 예약현황 탭으로만 검색) 확인(v2.4) V6 규칙
bookerSameAsPatient, bookerName, bookerPhone 예약자 ≠ 환자(보호자 대리) 확인 V5 R11, V6
date, startAt, endAt 2024부터 시작~종료 자유 확인 A2
categoryId 컬럼(시술·장비·의사) 확인 A2, A4
scheduleId v2.4 모델 확인(v2.4) V6
doctorId?, staffId?(담당자) 폼 필드 담당의 · 담당자 확인 A2 예약 폼
queueId?(대기리스트) 내원 시 들어갈 대기열(예 진료실1) 확인(필드) / 자동 배정 추정 A2 예약 폼
visitPurposeId, subPurposeIds[] 확인 V6, A2
questionnaireId? 발송할 문진 확인 A2
memo 0/600자. 메디톡에서 만들면 상담 메모가 자동으로 채워짐 확인 A3 예약 폼
suppressCrm ☐ CRM 메시지 보내지 않기 확인(체크박스) / 효과 추정 A2, A3
channel INTERNAL(○ 자체) · NAVER(N) · GOOGLE(G) · YEOSHIN · APP(보라 ◯ — 메디패스 추정) · PHONE(📞) 확인(아이콘) A2, A3
status 아래 상태 머신 확인 A3, A6 S20
cancelReason 자유 입력(선택), 사후 수정 가능. 플래너는 취소:노쇼 칩 확인 V6 S5, A2
colorOverride / 자동 색 카드 색 수동 지정(◐) + 색상 자동화 규칙(접수·완료·지각·대기상태) 확인(규칙 존재) / 규칙 상세 추정 A2, A4
vip 카드 VIP 배지(환자 태그 파생) 확인 A4
createdBy/At, updatedBy/At 추정
엔티티 필드 확신도 출처
PlanCategory name, color, hidden(눈 아이콘), order, 헤더 당일 건수 확인 A2, A4
PlanLog(최근 플랜) planId, action(등록·수정·취소·삭제·거절·확정·요청), actorId, at, channel 확인 A2, A4
PlanColorRule trigger(접수·완료·지각·대기상태), color 확인(메뉴·알리미) / 필드 추정 A4
ChartDraft(차트 초안) planId, plannedVisitDate, notes{consult, care, special}, clinicalNote, orders[], (수납 사전 작성) — 내원이력 초안 섹션, 차트 이동으로 정식 차트 전환 확인(화면) / 전환 시점 추정 A2 차트 초안, A4 내원이력
WorkTask/HospitalTask(병원 업무) date, body, authorId, editorIds[], done, highlighted — 홈·플래너 좌측 공용 확인 A4 ②-4, A3

ReservationStatus 상태 머신(2025 플래너 기준) [A3 플래너, A6 S20, A2 네이버 — 확인 / 전이 조건 일부 추정]

stateDiagram-v2
  [*] --> 요청 : 외부 채널 유입(네이버·구글·여신)
  [*] --> 확정 : 내부 등록(데스크·코디)
  요청 --> 확정 : 확정(수동 / 상품별 자동확정)
  요청 --> 거절 : 거절(모두 거절·개별)
  확정 --> 접수 : 내원 접수(태블릿·데스크)
  확정 --> 취소 : 예약취소(사유) / 노쇼
  요청 --> 취소 : 외부 취소 동기화(추정)
  접수 --> 완료 : 진료·수납 종료(추정: 내원 완료)
  취소 --> 확정 : 복구(미확인)
  확정 --> 삭제 : 플랜 삭제(권한 '플랜 삭제')
  완료 --> [*]
  거절 --> [*]
  • v2.4 목록 탭은 예약 / 접수 / 예약취소(+전체)뿐이었다 [V5 R10]. 2024-10 초기 카드 접두어는 대기 · 방문 · 취소 · 요청 · 업무였다가 2025-02부터 요청 · 확정 · 접수 · 완료 · 취소로 정리됐다 [A2, A4].
  • 노쇼는 독립 상태가 아니라 **취소 + 사유 칩(취소:노쇼)**으로 표현된다 [A2 — 확인]. 지각은 색 규칙 트리거로만 보인다 [A4].
  • 삭제는 취소와 구분되는 영구 삭제(VOC "예약 영구 삭제")이며 로그에 남는다 [A2].

4-3 외부 예약 채널

엔티티 필드 확신도 출처
PartnerIntegration partner(naver · google · yeoshin), status(미사용·사용중), apiKey, keyIssuedAt, scheduleMapping(연동스케줄) 확인(화면) / 매핑 의미 추정 A3 파트너사
NaverAccount serviceId, naverId, 스마트플레이스 이동 확인 A4 네이버
NaverProduct(예약상품, 구 비즈아이템) id, name, categoryId?(없으면 "플래너와 연동하려면 카테고리를 선택하세요."), autoConfirm 확인 A4 네이버
ExternalBooking partner, externalId, status(요청·확정·완료·거절/취소), product, category, bookerName, phone, bookedAt(KST 변환 — 구글은 국가별 타임존 자동 변환), requestedAt, requestNote, patientId?, planId? 확인 A3, A4
PartnerBillingEvent partner=google, bookingRequestId, fee=10,000(VAT 별도), month, cap 100,000 확인(요금) / 엔티티 추정 A3 구글

5. 접수·내원·대기열

5-1 Visit(접수 = 내원)

필드 설명 확신도 출처
id / receptionNo(접수번호) 통계·청구의 원천 연결키 확인 V4, V8 R5
patientId
careType 외래 · 입원 · 낮병동(2024-06 입원 토글 → 2025 세그먼트) 확인 A3 접수 모달, A2
receivedAt 기본 현재 시각, ✎ 수정 가능 — 나이·자격조회 판정 기준 시점 확인 A1, A2 청구
claimType 공단청구(기본) · 비청구 · 자보청구. 접수 후 변경 가능. (A5는 보건소·산재 경로도 제안) 확인 V1 R3, A1
insuranceType(자격구분) 건강보험 · 의료급여1종 … · 자동차보험 확인 V4, V9, A2
visitPurposeId, subPurposeIds[] 방문목적(필수, v2.4는 필수 아님으로 보이기도) + 세부목적(다중) 확인 A1(방문목적*), V1
doctorId 필수. 구환은 직전 담당의 기본값 확인 V1 R6
staffAssignments[] 역할별 담당 칩 상담/이름 관리/이름 간호/이름 코디/이름 확인 A2 차트 초안, A3 통합뷰
inflowTag 이벤트/강남언니 같은 유입 채널 태그 확인 A4, A2
questionnaireId? 접수 시 문진 지정(2023-06~) 확인 A1
chartTemplateId? 접수 시 차트템플릿 ▾ → 템플릿 적용 차트 자동 생성 확인 A1
receptionTags[] 접수태그(자유) 확인 A3
isEmergency, isPregnant ☐응급 ☐임신부. 임신부는 여성에게만 표시 확인 V1 R9, A3
receptionMemo 접수메모(100자 이내) 확인 A2
chartMemo 차트메모(차트구성 섹션) 확인(섹션명) A4 차트구성
visitKind(초진/재진) 내원이력 태그·명세서 분류의 원천 확인 V8 R15, A4
hasRemainingRx 내원이력 잔여처방 태그(빨간 아이콘) 확인(태그) / 의미 추정 A4 내원이력
channel 태블릿 · 데스크 · 예약 추정 V9 추정 엔티티
medicalAidApprovalNo 의료급여 진료확인번호 확인 A2, V9
durStatus 차트 헤더 DUR 점검(미점검) → DUR 통과 확인 V3 F4
isCompleted / completedAt 내원이력 날짜 옆 ✓ 추정 V9
isDraft 내원이력 초안 확인(배지) A4

5-2 QueueEntry(위치 × 상태)

필드 설명 확신도 출처
visitId, roomId 현재 위치 확인 V1, V2
status 아래 열거 확인 V9
order / sortIndex 기본 접수 순. 보내기 시 대상 룸 맨 뒤. 2025 드래그로 변경 확인 V2 R2, A3
statusChangedAt 통합뷰 ⏰ 1시간 30분 전 확인 A3
enteredAt, startedAt(진행중 경과 ⏱), completedAt 확인(표시) A3
VisitTransition 로그 from/to room, from/to status, at, by — 되돌리기 가능 추정(로그) / 되돌리기 확인 A1, V3 R17

QueueStatus(배지 색) [V1 R15, V9, A2, A3 — 확인]

값 색 의미
접수신청 빨강 외곽선 태블릿·앱 셀프 접수, 원무 확인 전
대기 주황 해당 룸 대기
우선대기 초록 먼저 부를 대상(정렬 반영 여부 미확인)
진행중 파랑 진료·처리 중(경과시간 표시)
완료 — 통합뷰 완료 시각(2025)

Visit/Queue 상태 머신 [A1 동선, V3 R17, V9, A3 — 확인, 보류는 우리 초안에만 있음]

stateDiagram-v2
  [*] --> 접수신청 : 태블릿·앱 셀프 접수(룸=태블릿접수)
  [*] --> 대기 : 데스크 접수(첫 상태 선택, 기본 대기)
  [*] --> 우선대기 : 데스크 접수(첫 상태=우선대기)
  접수신청 --> 대기 : 원무 확인·룸 배정
  대기 --> 우선대기 : 우선대기 지정
  우선대기 --> 대기
  대기 --> 진행중 : 진행하기 / 행 클릭
  우선대기 --> 진행중
  진행중 --> 대기 : 보내기(다른 룸, 맨 뒤)
  대기 --> 대기 : 보내기(룸 이동)
  진행중 --> 완료 : 병원에서 내보내기(귀가)
  대기 --> 완료 : 병원에서 내보내기
  완료 --> [*]
  • 보내기 = (다음 위치, 상태)를 한 번에 바꾼다. 현재 위치와 같은 목적지는 비활성 [V3 S5, V9 — 확인].
  • 대기 보드 대기 N = 필터로 고른 룸들의 인원 합(진행중·우선대기 포함) [V1 R14].
  • 초기 접수 상태를 사람이 고른다: 대기열* [진료실1▾][대기▾] [V1 R8].

5-3 ReceptionRequest(접수신청) / SelfCheckIn

필드 설명 확신도 출처
deviceId 태블릿 추정 A1
method QR(2022) · PHONE · RRN 확인 A1 태블릿, A6 S29
matchedPlanId? 휴대폰번호로 예약 매칭 → "해당 예약정보가 맞으신가요?" 확인 A6 S29, A1
patientId? 구환 매칭, 신환은 주민번호 경로 확인(경로) / 신환 등록 단계 미확인 A6
visitPurpose 내원목적 확인 V9 F2, A3
consents[] 필수·선택(마케팅·AI 녹취) — 선택 항목은 미리 체크하지 않음 확인(2026) A3
status 접수신청 → (원무 확인) 대기 / 거부(제가 예약한 내용이 아니에요) / 접수 취소 확인(버튼) / 전이 추정 A1, A6

6. 차트

엔티티 필드 확신도 출처
ChartSection(역할별 기록 칸) visitId, section(consult 상담 · care 관리 · caution 특이사항 · clinical 진료기록 · nursing 간호기록 · receptionMemo · chartMemo), body(서식 텍스트, 줄 색), authorId, updatedAt. 저장 버튼 없이 즉시 반영 확인 A4 역할별, V1 R21
ChartLayout(차트구성) scope(user? role? dept?), sections[] — 13종: 접수메모·차트메모·파일·진료기록·이미지·진단 및 처방·간호기록·액션·수납·문서발급·오더세트/차트템플릿·쿠폰·포인트 (+2025 할 일·티켓) 확인(항목) / 범위 미확인 A4, V2 R24
Diagnosis visitId, kcdCode(점 없는 대문자), name, nameEn, isPrimary(주 — 첫 줄 자동), isSuspected(임상적 추정/최종), order, onsetDate(서류용) 확인 V3 R2, A1 문서
OrderLine(진단 및 처방 줄) visitId, kind(아래), code, name/displayName, dose·timesPerDay·days(약 3칸, 기본 1 1 1), usage, count(수가·검사), coverage(급여·비급여, 비급여(과세)/(면세)), dispense(원내·원외), copayType(본인부담률), unitPrice, amount, surchargeLabel(영상의학과전문의판독), specialNotes[](JS010·JT014 …), pacsLinked, autoRule(스마트진찰료·스마트관리료, 연령 가산 문구), source(검색·오더세트·단축어·티켓), ticketRef, performerId 확인 V3, V7 R11, V9, A5 E-27
Task(할 일) patientId, visitId, orderLineId?, memo, assigneeIds, status(대기 ○ · 진행중 ◐ · 완료 ✔), startedAt, completedAt, duration, plannedStart/End?, source(manual · auto_order) 확인(2025-08) A3 할 일
VisitImage patientId, visitId, source(PC 업로드 · 웹캠 촬영 · 모바일 · 장비 DSLR/ENT), takenAt, uploaderId, fileRef, thumbRef — 내원당 30장 확인 V1 R18, A4, A3
Canvas(펜차트) 태블릿 펜 기록 확인(기능) / 필드 미확인 A1, A4
Recording / Timer visitId, fileUrl, duration / startedAt, endedAt(2025-02) 확인(업데이트 노트) A4
LabResult visitId, labGroup(원내검사실 · 수탁기관), itemName, value, judgement, reference, reportedAt, readingUrl(PACS 판독소견), status 확인 V2 R22
QuestionnaireResponse templateId, patientId, visitId?(본 진료건), submittedAt, answers[], editedBy/At(답변 편집 가능), 미응답 (무응답) 확인 A1 문진
Routine name(진료완료 · 일괄진료 · 문서완료 · DUR), steps[](DUR 점검 → 관리료 재산정 → 약 조제 전송 → 전자서명 …) — 순차 실행, 단계 상태 대기→진행→완료, 취소 가능 확인 A6 S12

OrderLine.kind(행 아이콘으로 구분) [V9, V3, A3 — 확인]: 진찰료/관리료(수가) · 약 · 주사 · 처치/행위 · 검사(영상·검체) · 치료재료 · 문서 · 예방접종 · 코드 오더(MS002 원내투약 주사제) · 지시·메모(가루약 처방) · 티켓 구매 / 티켓 사용.

Task 상태 머신 [A3 — 확인]

stateDiagram-v2
  [*] --> 대기 : 수동 등록 / 오더 추가 시 자동 등록(설정 ON)
  대기 --> 진행중 : 시작(경과시간 표시)
  진행중 --> 완료 : 완료(소요시간·완료시각 기록, 취소선)
  대기 --> 완료
  대기 --> [*] : 삭제

7. 라이브러리(마스터)

엔티티 필드 확신도 출처
ClaimMasterItem(EDI아이템, 벤더 공용·읽기 전용) claimCode, nameKo/En, itemClass(대/소), detailCode(주성분코드), price(고시가), manufacturer, kind, effectiveFrom/To, allowedSpecialNoteCodes[] 확인 V7 R2
UserItem(사용자아이템, 병원별) category(수가·약가·치료재료대), itemClass(대/소, 필수), claimCode(필수, 자유 문자열 — EDI 코드와 겹칠 수 있음), nameKo(필수), nameEn, mainIngredientCode, manufacturer, nonCoveredPrice(필수, 기본 0). category·itemClass·claimCode는 생성 후 불변 확인 V7 R3~R5
DocumentItem(문서아이템, 16종 카탈로그) nameKo, itemClass(진찰료/응급 및 회송료), templateRef 확인 V7 R7
VaccinationItem 탭만 확인 미확인 V7
OrderSetFolder / OrderSet / OrderSetLine 폴더(1단, 번호 접두 정렬) > 세트 > 줄. 줄 = lineType(상병·약·수가·영상·문서·검사), ref, displayName, isPrimaryDx, dose/dailyFreq/days/usage/dispensing, count, copayType, unitPrice(급여면 고시가 잠금), pacsLinked, specialNotes[]. 파생 totalUnitPrice = Σ unitPrice(수량 곱 없음). 공용 세트(붉은 십자, 시스템 배포) 확인 V7 R8~R13, V3
Shortcut(단축어) keyword(한글·영숫자), orderSetLineId(1:1) — 차트 / 호출 확인 V7 R15
QuickOrder 검색 탭 ⚡퀵오더 미확인 V3
ChartTemplate folder > template, 진료기록 본문 + 처방 줄. 차트 칩(SOAP·외래기록지·소아기록지), 접수 시 지정 확인 A1, V9
Phrase(자주 쓰는 문구) label(칩), body, color?, owner(개인/병원 — 미확인). 진료기록 하단 칩·/ 확인 V1, A6
TicketProduct code(TKnnnn), name, kind(single N회권 · choice_single 주차별 · choice_multi 옵션 풀), totalCount, price, taxType(비급여 과세), rounds[]{roundNo, options[]}, validityDays?(만료일 없음 가능) 확인(유형·칩) / 등록 화면 미공개 A3 티켓
CouponTemplate name(첫 방문 이벤트 · 주름 보톡스 1+1 · VIP 전용 · 지인 할인 10% · 생일쿠폰), method(비율 · 정액 추정), value, active. 유효기간·대상·중복 규칙 미공개 확인(이름·비율) / 나머지 미확인 A3, A4
Questionnaire(문진) name, items[{type(single·multi·scale 1~10·text), required, options}] — 라이브러리 > 문진 확인 A4 문진, A6
MessageTemplate folderId, name, channel(문자 SMS/LMS/MMS · 친구톡 · 알림톡), purpose(알림성 · 광고성 → 본문 앞 (광고)), title, body(예약어), images[≤3], surveyLinkId?, allowFallback(대체발송 허용), isSystem(알림톡 기본 템플릿 읽기 전용) 확인 A4 템플릿, V6
ConsultTemplate(메디톡 상담 매크로) title(해시태그형), bodies{ko, zh, ja, en} 확인 A3

8. 수납·원무

8-1 진료비·수납

엔티티 필드 확신도 출처
Charge(진료비 산정, 내원당 1) totalFee(진료비총액), insurerShare(공단부담금), copay(본인부담금), nonCovered(비급여), patientTotal(환자부담 총액 = 본인+비급여), autoInsuranceClaim(자보청구금), subsidy(지원금), discount(할인금), amountDue(받을 금액), roundingAdjustment(끝수처리 조정액) — 오더 입력 즉시 재계산 확인 V3 R8~R10, V4
Payment(수납 행) visitId, paidAt(MM.DD), method(카드 · 현금 · 할인금 · 선납금 · (2025) 포인트·쿠폰), amount, installment(카드 필수: 일시불/개월), cashReceipt(bool), bankTransfer(bool), idNumber(신분확인번호), approvalNo, terminalTxId?, kind(수납/환불) 확인 V3 S10, V9
Refund paymentId?, amount, refundedAt, method — 수납 패널 ▸ 환불 접힘 섹션 확인(섹션) / 입력 UI 미확인 A2, V4
Receivable(파생) 남은 금액 = 받을 금액 − Σ수납 (+ Σ환불) 확인(− 수납) / 환불 반영 추정 V2 R17, A2
DailySettlementReport date, 카드 승인·취소(건수·금액), 카드사별, 현금영수증 승인·취소 — 알림톡 발송(VAN사 부가서비스 추정) 확인(메시지) A2

수납(내원 단위) 상태 — 닥터팔레트는 명시 상태 배지를 보여주지 않고 남은 금액으로 판단한다(추정 상태 머신).

stateDiagram-v2
  [*] --> 미수납 : 오더 발생(받을 금액>0)
  미수납 --> 부분수납 : 수납 추가(합계 < 받을 금액)
  부분수납 --> 완납 : 남은 금액 = 0 (+수납 추가 버튼 숨김)
  미수납 --> 완납
  완납 --> 부분수납 : 오더 추가로 받을 금액 증가 / 환불
  부분수납 --> 미수 : 귀가(내보내기) 후에도 잔액 > 0 → 미수 목록
  미수 --> 완납 : 나중 날짜 수납(통계는 수납일 기준)

8-2 쿠폰·포인트·선납금 (2025)

엔티티 필드 확신도 출처
CouponApplication visitId, templateId?(없으면 직접입력), method(비율·정액), rate, targetOrderLineIds[](처방 줄에 걸림), baseAmount, discountAmount, appliedBy, appliedAt 확인 A3 쿠폰
PointLedger patientId, type(use · charge · refund, + earn/expire 추정), points, paidAmount?(충전 결제액), bonusPoints?(예 100,000원 → 110,000P), visitId?, by, at, balance 확인(사용·충전·환불 탭) A3 포인트
PrepaidLedger(선납금) patientId, 구분(입금/출금), amount, balance — 결제수단 선납금으로 차감 확인(잔액·수단) / 충전 UI 미확인 V4, A2

8-3 티켓(회차권)

엔티티 필드 확신도 출처
PatientTicket id, patientId, productId, purchaseVisitId(구매 오더 줄 TK1581 10회권 구매 … 비급여(과세) 350,000원), purchasedAt, price, couponDiscount, netPrice(패키지 가격), usedCount, totalCount, expiresAt?(만료일 없음 가능), status(사용중 · 완료 · 환불 — 탭 `사용 완료`) 확인
TicketUsage ticketId, visitId, roundNo, optionId?(선택형), orderLineId(TK… 사용 금액 없는 줄), usedAt, by 확인 A3
TicketExtension ticketId, oldExpiry, newExpiry, by, at(기간 연장) 확인(버튼) / 필드 추정 A3
TicketRefund ticketId, usedCount, remainingCount, netPrice, refundAmount(직원 직접 입력), by, at 확인 A3
RevenueRecognition ticketUsageId, recognizedAmount, recognizedAt — 사용 시점 매출, 미사용분 = 선수금 확인(주장) / 계산식 미공개 A3 news#166081947

PatientTicket 상태 머신 [A3 — 확인(탭·버튼) / 만료 처리 미확인]

stateDiagram-v2
  [*] --> 사용중 : 구매 오더 수납
  사용중 --> 사용중 : 칩 클릭(사용 n/N) · 기간 연장
  사용중 --> 완료 : usedCount = totalCount
  사용중 --> 환불 : 우클릭 '티켓 환불'(금액 수동)
  사용중 --> 만료 : expiresAt 경과(처리 방식 미확인)
  완료 --> [*]

9. 문서·전자서명

엔티티 필드 확신도 출처
IssuedDocument visitId, docType(처방전 약국/환자보관용 · 진단서 · 건강진단서 · 상해진단서 · 진료기록지 · 진료비계산서영수증 · 진료비세부내역서 · 건강검진증명서 · 진료확인서 …), status(미발급 → 발급완료), serialNo(연번호 No. = 발급시각 YYYYMMDDHHmm 접두 + 일련), applicant(신청인, 기본 환자), relation(환자와의 관계, 기본 본인), note(비고), formInputs{용도, 발병일, 소견, 입·퇴원일}, issuedAt, issuedBy, printLog 확인 V3 R13~R16
ConsentForm(태블릿 동의서) 서식, 환자 스냅샷, 진단명, 시술일자, 서명, status(임시저장 · 완료) 확인(화면 일부) A6 S19
PatientAppDocRequest userId, hospitalId, docType, requestedAt, status(요청 → 발급, 약 5분 비동기), issuedAt 확인 V9 F7
LabelPrint / NemonicPrintJob patientId, visitId, sections[상담, 진단 및 처방], printedAt 확인(출력 레이아웃) A2 네모닉, A4 ⋮

IssuedDocument 상태: (오더·자동 생성) 미발급 → 발급(번호 부여·확정) → 출력(인쇄/PDF, 반복 가능). 전체 발급 후 헤더 버튼이 전체 출력으로 바뀐다 → 발급과 출력은 별개 [V3 R13 — 확인(버튼) / 분리 해석 추정].


10. CRM·메시지

엔티티 필드 확신도 출처
NotificationSetting(v2.4 알림 메시지) trigger(RECEPTION_GUIDE · RESV_CREATED · RESV_CHANGED · RESV_CANCELLED · RESV_REMINDER), enabled(기본 OFF), showQueueNumber, includeQuestionnaireLink(예약 변경), sameDayEnabled + sameDayTime(오전 8/9시 예시), daysBeforeEnabled + daysBefore(1~5) 확인 V6, A1, A6 S23
AutoMessageRule(2025 자동발송 메시지) name, active, messageType(알림성·광고성), trigger(예약 변경 · 예약 완료 · 예약 취소 · 예약 내원일 · 접수), categoryIds[](카테고리별 다른 메시지), templateId, leadTime? 확인 A4 자동발송
CrmRule(2024 조건 기반) trigger(QUESTIONNAIRE · BIRTHDAY · PRESCRIPTION_ELAPSED(처방 후 N일, 예 보톡스 3개월) · SCHEDULE_RESERVATION(특정 스케줄 예약자만)), filters{orderCodes[], delayDays, scheduleIds[]}, templateBody, channel, sendTime, active 확인(4종 원문) A2 CRM
MessageDispatch(발송 1건) id, type, sourceRef(reservationId / receptionId / ruleId), recipientName, recipientPhone(마스킹 표시), channel(ALIMTALK · SMS · LMS · MMS · 친구톡), status(발송 중 · 발송성공 · 발송실패), requestedAt, sentAt, unitPrice, fallbackOf? 확인 V6, A1
MessagingBillingMonth yearMonth, totalExVat, totalIncVat, 채널별 금액·건수, sentCount(=성공), successCount, failCount 확인(검산 일치) V6 요금 검산
MessagePrice channel, unitPrice(알림톡 20 · SMS 25 · LMS 50), vatRate 10% 확인 V6 S11
CreditWallet / TopUp balance, bonus_balance / amount, bonus_rate(10~60%) — 2023-11 선불 충전 도입(후불 병행) 확인(보너스 표) / 소진 순서 미확인 A5
PatientGroup / Campaign name, rule 또는 members[] / groupId, templateId, sentAt, stats 확인(사례) / 그룹 방식 미확인 A4 그룹 발송
Conversation / Message(메디톡 플러스) channel(LINE · INSTAGRAM · WECHAT · WHATSAPP), externalUserId, patientId?(미등록환자), status(신규 · 상담중 · 보류 · 완료), assigneeId, tags[], inflow, memo, autoTranslate / direction, originalText, originalLang, translatedText, targetLang 확인(2025-12) A3 메디톡
SurveyQuestion / SurveyDispatch / SurveyResponse(만족도) type(staff · general), deptId, linkProcedures, scale / patientId, visitId / score 1~5, comment, staffId 확인 A3 만족도

MessageDispatch 상태 머신 [V6·A1 — 확인(3색 배지) / 대체발송 판정 추정]

stateDiagram-v2
  [*] --> 예약됨 : 트리거 발생(즉시) / 리마인더 시각 도래 대기
  예약됨 --> 발송중 : 발송 시각
  발송중 --> 발송성공 : 알림톡 성공(과금)
  발송중 --> 발송실패 : 실패(과금 제외)
  발송실패 --> 대체발송 : 카카오 미사용·실패 → SMS/LMS(fallbackOf)
  대체발송 --> 발송성공
  예약됨 --> 취소 : 예약 취소·CRM 제외 체크(추정)

11. 청구(보험)

엔티티 필드 확신도 출처
ClaimBatch(원청구서) unit(월청구 · 주청구), year, month, insuranceType(필수, 기본 건강보험), status, claimNo?(발급 시 10자리, 앞 6자리 진료연월), statementCount, totalMedicalFee, totalClaimAmount, eligibilityErrorCount, fileName({claimNo}.ghp), createdAt, issuedAt 확인 V8
ClaimStatement(명세서 = 환자 × 내원일) batchId, serialNo(명일련번호 5자리), patientId, visitDate, receptionNo, doctorId, totalFee, copay, claimAmount, excluded(+at/by), issues[] 확인 V8 R5
StatementIssue code(상병 미기재 · 주상병 미기재 …), message, deepLink(차트열기) 확인 V8
EligibilityIssue 헤더 보험자격 오류 N건 — 발급을 막지 않음 확인(건수) / 상세 미확인 V8
ChartReviewFinding(심사점검) visitId, category(상병점검 · 특정내역 · 중복 · 누락), targetOrderId, criteria{심사번호, 보험인정기준 원문}, recommendedDiagnoses[] 확인 V8 흐름 A

A5는 여기에 코드 기간 버전·규칙 엔진·명세서 상세(E-01~E-38)를 제안한다 — 우리 P3 범위다.

ClaimBatch 상태 머신 [V8 — 확인]

stateDiagram-v2
  [*] --> 생성중 : 원청구서 생성(비동기 수집)
  생성중 --> 작성중 : 수집 완료(건수·금액 채움)
  작성중 --> 작성중 : 제외(즉시 반영) · ↻ 재생성·재집계
  작성중 --> 발급완료 : 발급하기(확인창 없음, 청구번호·.ghp)
  발급완료 --> 발급완료 : 내려받기(재다운로드)
  작성중 --> [*] : 원청구서 삭제
  발급완료 --> [*] : 원청구서 삭제(발급 후에도 가능)

12. 통계·경영(저장 모델 관찰)

엔티티 필드 확신도 출처
MonthlyReport hospitalId, period, kpis, narrative[], charts[] — 월초 홈 봉투 카드 확인(화면) / 스냅샷 저장 추정 V4, V9
InsightWidget / Layout ownerId?, type, unit, position, visible — 배치바꾸기·✕ 확인 V4
WaitlistViewConfig mode(기본 · 확장형), lists{대기 · 예약 · 방문 · 통합}, visibleFields[] 확인 / 저장 범위 미확인 A3

통계 기준일(추정, V4 §8): 매출 = 진료일, 수납 = 수납일, 미수 = 진료일. 객단가 = 매출 ÷ 진료횟수(접수 건).


13. 우리 설계 초안(docs/design/domain-model.md v0.1)과의 차이·누락

판정: 반영됨 = 초안이 이미 담음 / 차이 = 초안과 관찰이 다름(결정 필요) / 누락 = 초안에 없음. 우선순위는 mvp-scope.md 기준(P1 MVP · P2 · P3). "권고"는 구현 직전 확정안 제안이다. 초안은 수정하지 않았다(읽기 전용).

13-1 차이 — 모델 형태가 다른 것 (결정 필요)

# 주제 닥터팔레트(as-is) 초안 v0.1 권고 우선
D-01 예약 시간 모델 2024-10에 슬롯 모델(v2.4)을 버리고 자유 시작~종료 + 카테고리 컬럼으로 전환. 슬롯·정원 개념은 플래너 화면에 없음 Schedule+SchedulePeriod(slotMinutes·slotCapacity·weeklyHours) 슬롯 모델 + Reservation.startMinute/durationMinutes 둘 다 수용: Reservation은 start/end(자유) 저장, 슬롯은 "제안 그리드·정원 경고"용 계산값으로만 사용. 운영시간·정원 없는 스케줄(카테고리형)도 허용(slotCapacity nullable) P1
D-02 예약 상태 요청 · 확정 · 접수 · 완료 · 취소 · 거절 · 삭제(+노쇼는 취소 사유 칩) reserved, confirmed, checkedIn, completed, cancelled, noShow requested, rejected 추가(외부 채널 P3이나 상태는 P1에 예약). noShow는 독립 상태로 유지하되 통계 호환 위해 cancelReason과 별도로 둔다. reserved vs confirmed 중복 여부 결정 — 권고: 내부 등록은 곧바로 confirmed, reserved 제거 P1
D-03 예약 자원 축 열 = 카테고리(시술·장비·의사), 담당의·담당자는 별도 필드. A6은 "열=스케줄, 색=카테고리" 가능성도 제기 Schedule(kind: doctor·procedure·equipment·counseling) 하나로 자원·색 겸함 Schedule 유지하되 Reservation.doctorMemberId?, staffMemberId?(담당자) 추가 — 열과 담당을 분리 P1
D-04 게스트(신환) 예약 환자 레코드 없이 게스트 필드. 2025엔 임시환자(isTemporary)도 있음 guest 필드 방식 게스트 방식 유지 + Patient.isGuest(초안에 있음)를 "임시환자"로 명확히 정의. 둘 중 하나로 통일 권고: 예약은 guest 필드, 태블릿·외부 유입은 임시환자 P1
D-05 대기 상태값 접수신청 · 대기 · 우선대기 · 진행중 · (완료). 보류 없음 requested, waiting, priority, inProgress, hold, done hold는 관찰 근거 없음 → 유지 여부 결정(권고: 제거하거나 P2). requested는 ReceptionRequest와 중복 — 접수신청을 QueueEntry 상태로 둘지 별도 수신함으로 둘지 하나로 P1
D-06 Visit 상태·종료 병원에서 내보내기가 명시적 종료 동작. 수납 완료와 무관하게 내보낼 수 있고 잔액은 미수로 남음 규칙 "수납 완료 + 마지막 룸 종료 → completed" 명시적 내보내기를 종료 트리거로 채택. 수납 완료는 조건이 아니라 경고(잔액 있으면 "미수로 남습니다" 확인) P1
D-07 청구유형 공단청구(기본) · 비청구 · 자보청구. 산재는 관찰 안 됨 ClaimType { uninsured, nhis, autoInsurance, industrial }, MVP 기본 uninsured(mvp-scope) 값 집합은 유지. 기본값은 우리 타깃(비급여 의원)에 맞게 uninsured 유지 — 닥터팔레트와 의도적 차이로 문서화 P1
D-08 결제수단 카드 · 현금 · 할인금 · 선납금(v2.4) — 할인금이 결제수단. 2025엔 포인트·쿠폰이 결제 전 차감 PayMethod { card, cash, transfer, prepaid, other } + 할인은 InvoiceAdjustment 초안 방식(할인=조정)이 회계상 옳음 → 유지. 단 현금의 하위 속성 bankTransfer(계좌이체)와 cashReceipt*를 초안처럼 분리 유지, UI는 닥터팔레트처럼 "수납 추가" 한 모달에서 처리 P1
D-09 수납 엔티티 경계 내원당 Charge 1개(발생금액) + 수납 행. Invoice 개념 없음. 회차권 판매도 오더 줄(구매) Invoice(내원 없이도 가능) + InvoiceLine(kind: order·ticketSale·prepaidCharge) 초안 유지(내원 없는 선납금 충전·티켓 판매 수용). 단 티켓 구매를 OrderLine 종류로도 입력할 수 있게(OrderKind.ticketPurchase) 하여 차트 흐름과 일치 P1
D-10 쿠폰 적용 단위 쿠폰은 특정 처방 줄(targetOrderLineIds)에 걸림. 템플릿 없이 직접입력(할인율+처방 선택) 가능 PatientCoupon(발급형) + InvoiceAdjustment(kind: coupon) 발급형은 유지하되 즉석 적용(직접입력) 경로와 adjustment.targetLineIds[] 추가. 닥터팔레트에는 "발급" 단계가 보이지 않음(선택만) — 발급형은 P2로 미뤄도 됨 P1
D-11 포인트 충전 충전 = 결제액 + 보너스 포인트(100,000원 → 110,000P). 선납금과 별도 원장 PointLedger(reason: earn·use·bonus·expire·refund·adjust), PrepaidLedger 분리 반영됨. PointLedger에 paidAmount(충전 결제액) 필드 추가 필요 P1
D-12 티켓 선택형 single · choice_single(주차별 구성) · choice_multi(옵션 풀, 쓴 옵션 사용불가) TicketKind{count, amount, period}, TicketSelection{fixed, choiceSingle, choiceMulti} 반영됨(선택 모드). choice_single은 회차별 구성(rounds[])이 필요 — TicketProduct.rounds: List<{roundNo, feeItemIds[]}> 추가. amount/period권은 관찰 근거 없음(P2) P1
D-13 티켓 매출 인식 식 "사용한 만큼만 매출" 주장, 계산식 미공개 recognizedAmount = 가격 ÷ 총회차 × count 초안 식 채택, netPrice(쿠폰 할인 후) 기준으로 명시. 마지막 회차는 잔액 보정(끝전) 규칙 추가 P1
D-14 차트 기록 칸 상담 · 관리 · 특이사항 · 진료기록 · 간호기록 + 접수메모 · 차트메모 NoteKind{clinical, counseling, care, nursing, procedure}, 특이사항은 Patient.specialNote procedure(시술기록)은 관찰 없음(진료기록에 씀) — 유지 여부 결정. receptionMemo는 Visit에 있음(반영), chartMemo 누락 P1
D-15 오더 줄 필드 copayType(본인부담률), specialNotes, pacsLinked, surchargeLabel, autoRule, source, displayName kind·coverage·dispense·dose… P1은 displayName, source(검색·세트·단축어·티켓) 추가. 나머지는 P3 P1/P3
D-16 문서 번호 발급시각 YYYYMMDDHHmm + 일련 serialNo 형식 규칙을 06 문서 BR로 확정. 발급(번호)과 출력(인쇄 횟수) 분리 — 초안 printCount 반영됨 P1
D-17 알림 트리거 접수 안내 · 예약 완료/변경/취소 · 당일/사전 리마인드(+ 2024 생일·처방 경과·스케줄별·문진) MessageTrigger 6종 + questionnaireLink·manual 반영됨. 2024 조건 규칙(birthday, prescriptionElapsed, 스케줄 필터)은 P2. MessageSetting에 scheduleIds/categoryIds 필터와 includeQuestionnaireLink 추가 P1/P2
D-18 발송 상태 발송 중 · 성공 · 실패(+대체발송) queued, sent, failed, fallbackSent, cancelled 반영됨. sending(발송 중) 추가 여부는 선택. 과금은 성공 건만(06 BR) P1
D-19 권한 모델 역할(그룹) × 모듈 × 세부 동작 체크박스, 멤버는 직군·부서 Role.permissions: List<String> 키 집합 반영됨(키 = 모듈.동작). 관찰된 세부 동작 중 chart.delete, nursing.read/write, coupon.read/write, point.read/write, patientNote.editOthers, planner.category, plan.delete, stats.insight 키 추가 P1

13-2 누락 — 초안에 없는 엔티티·필드

# 누락 항목 닥터팔레트 근거 권고 우선
M-01 Task(할 일) — 환자·내원·오더 연결, 수행자 다중, 대기→진행→완료, 소요시간 A3(news#167389387) mvp-scope P2 항목. 모델만 P1에 예약(ClinicTask와 별개) P2
M-02 VisitStaffAssignment(역할별 담당: 상담·관리·간호·코디) A2 차트 초안, A3 통합뷰 Visit.counselorMemberId만 있음 → List<{role, memberId}>로 일반화. 만족도·담당자별 통계의 원천 P1
M-03 Visit.inflowTag / acquisition 방문 단위 이벤트/강남언니 방문 태그 초안은 Patient.acquisitionChannelId(환자 단위)만 → 방문 단위 Visit.acquisitionChannelId? 추가 P1
M-04 Visit.careType(외래·입원·낮병동) A3 접수 모달 enum만 두고 P1은 외래 고정 P3
M-05 Visit.isEmergency, receptionTags[], chartTemplateId, questionnaireId A2·A3 접수 모달 isEmergency, chartTemplateId P1 추가, 나머지 P2 P1/P2
M-06 IdentityVerification(본인확인, 6개월 유효) A2(2024-05 의무화) 급여 진료 시 필수 → P3이지만 비급여도 신분 확인 기록 수요 있음. 모델 P3 P3
M-07 EligibilityCheck(자격조회 스냅샷) V1 R2 P3(어댑터) P3
M-08 PlanCategory / 업무 플랜(WorkBlock) A2 플래너 Schedule로 흡수하되 업무 블록(자리비움)용 Reservation.type = work 또는 StaffBlock 추가 P1
M-09 ChartDraft(차트 초안) — 내원 전 상담·오더 사전 작성 A2 news#124177982 ChartNote/OrderLine이 visitId 필수라 초안 불가 → reservationId 기반 초안(또는 Visit.status = draft) 필요 P2
M-10 PlanColorRule, Reservation.colorOverride는 있음 A4 색 자동 규칙은 P2 P2
M-11 ExternalBooking / PartnerIntegration / 상품 매핑(autoConfirm) A3·A4 초안은 source·externalRef만 → P3에 엔티티 추가, P1은 샌드박스 어댑터용 ExternalBooking 최소형 P3
M-12 ReceptionRequest.consents / matchedReservationId / method A1·A3·A6 초안 ReceptionRequest에 reservationId?, method(phone·rrn·qr), 동의 결과 연결 추가 P2
M-13 ConsentRecord 필드: required, channel = staff_verbal_attest, attestedBy, AI 녹취 동의 종류, "비동의도 기록" A3 news#171946700 PatientConsent에 required, attestedById? 추가, ConsentKind에 aiRecording 추가 P1(필드)/P3(AI)
M-14 LabResult(검사결과) V2 R22 초안에 없음. 수탁·PACS 연동 전제 → P3 P3
M-15 QuestionnaireResponse 편집 이력·본 진료건 연결 A1 초안 문진(P2)에 visitId, editedById 추가 P2
M-16 Routine 실행 이력 A6 S12 초안 Routine(P2)은 정의만 → 실행 로그 필요 시 추가 P2
M-17 WaitingScreen / Holiday 외 대기스크린 설정(요일 세트·마스킹·영상·음성호출) A6 S26~28 P2 P2
M-18 Refund 링크: 원 결제 참조 V4, A2 Payment.originalPaymentId 반영됨 ✓ —
M-19 Charge의 지원금·자보청구금·끝수처리 조정 V3, V4 Invoice.roundingAdjustment는 조정 줄로 반영(P3). subsidyAmount P3 P3
M-20 Payment.installmentMonths 필수(카드), idNumber(현금영수증 신분확인번호) V3 S10 installmentMonths 반영, cashReceiptNo는 신분확인번호 의미로 명시 P1
M-21 MessageTemplate: folder, images[≤3], allowFallback, 광고 prefix A4 템플릿 폴더·이미지는 P2, allowFallback P1 P1/P2
M-22 CreditWallet 보너스 잔액·충전 구간 A5 초안 MessageCredit(delta)만 → reason: bonus 추가(P2) P2
M-23 PatientGroup(세그먼트) A4 Campaign.segment(JSON)로 반영됨(P2) ✓ —
M-24 HospitalInfo 서류용 직인·의사 인장/서명 이미지·면허번호 V3 R14, A1 Staff.licenseNo 있음. 직인·인장 이미지 경로 누락 → ClinicSetting.sealImagePath, Staff.signatureImagePath 추가 P1
M-25 ChartLayout 저장 범위 A4 초안 ClinicSetting.chartPanelsByJob(직군별) → 관찰은 개인 설정 가능성 → MemberPreference(개인) + 직군 기본값 2단 P1
M-26 WaitlistViewConfig(확장형·통합뷰·표시 항목) A3 개인 설정으로 MemberPreference에 포함 P2
M-27 Department(부서) A3·A4 ClinicMember.jobType만 → department? 문자열 추가(만족도·권한 필터) P2
M-28 환자 이름 60자·임시환자 A4 이름 길이 60 제약 명시, isGuest → 임시환자 의미 P1
M-29 SecurityAdmin(IP 제한 예외) A4 IpAllowRule만 → "소유자·보안관리자는 IP 제한 예외" 규칙과 ClinicMember.isSecurityAdmin 추가 P1
M-30 ClaimBatch / ClaimStatement / 심사점검 V8 초안 없음(P3). 06 BR과 A5 E-01~E-38 참조 P3
M-31 Conversation(메디톡)·Survey(만족도) A3 초안 없음 — P3/P2 P2/P3
M-32 Recording/Timer, Canvas, 장비 이미지 source A4 MediaSource{pc, mobile, device} 반영, webcam 추가 권고. 녹음은 P2 P2

13-3 초안에만 있는 것 (닥터팔레트에서 관찰 안 됨 — 유지 판단)

항목 판단
ReservationEvent.diff(JSON) 닥터팔레트 최근 플랜은 액션만 보임. diff는 우리 강점(유지)
QueueStatus.hold 근거 없음 → 제거 또는 P2
NoteKind.procedure 근거 없음 → 진료기록과 통합 검토
DailyClosing(일마감) 닥터팔레트는 통계·알림톡 정산 리포트로 대체. 우리 P1 유지(원무 요구)
TicketKind.amount/period 관찰 없음 → P2
CouponPolicy.minAmount/maxDiscount/validDays 닥터팔레트 미공개 → 우리 정책으로 유지(합리적 확장)
ChartNote.version(낙관적 잠금) 닥터팔레트는 동시 편집 방식 비공개. 유지

출처 파일

  • 텍스트 분석: A1_news_2022_2023.md(외래접수·환자기록·수납·CRM·동선·태블릿·구현 시사점), A2_news_2023_2024.md(본인확인·접수 모달·수납 패널·네이버·플래너·차트 초안·CRM 규칙·CID·권한), A3_news_2025_2026.md(접수 모달·쿠폰·포인트·티켓·플래너·파트너사·메디톡·만족도·통합뷰·할 일·녹취 동의), A4_customer_stories.md(①·②·모듈별·권한 매트릭스·IP 제한), A5_billing_rules_and_market.md(②·③·1-5·1-7·4-4), A6_feature_pages_ui.md(S12·S16·S19·S20·S23·S24·S26~S29)
  • 영상 분석: V1_reception_treatment.md, V2_chart.md, V3_dxrx_documents.md, V4_stats_insight.md, V5_reservation_crm_part1.md, V6_reservation_crm_part2.md, V7_library.md, V8_claims.md, V9_intro.md — 각 '도메인 규칙·데이터' 절
  • 비교 대상: docs/design/domain-model.md(v0.1), docs/product/mvp-scope.md