Skip to content

Đặc tả giao diện (UI Spec) — Hồ sơ bệnh án v2.3.0

Tham chiếu: PRD v2.0.0 | Ngày: 30/04/2026


Mục đích: mô tả màn hình, thay đổi, trạng thái, tương tác, copy hiển thị, tooltip và trường hợp cá biệt để FE/UI/QA triển khai thống nhất, đủ căn cứ triển khai và kiểm thử cột/trạng thái/validation.

Đọc trước: decision-brief.mdB-PRE) Kiểm tra trước khi viếtB0) Hiện trạng UIB1) Bản đồ màn hình → các SCR áp dụng → B-POST) VerificationB-QUALITY) Rà soát rủi ro thiếu sót.

Văn phong: theo templates/_LANGUAGE_RULES.md + templates/_STYLE_GUIDE.md. Heading + nhãn Mermaid/wireframe Việt-first. CTA: Lưu/Hủy/Áp dụng/Xác nhận. Mọi copy là tiếng Việt tự nhiên ngữ cảnh thẩm mỹ viện.

Phụ lục mở rộng đã load: EXT-3 (Lifecycle UI mở rộng), EXT-4 (Field visibility tầng 3), EXT-5 (Config addendum), EXT-6 (Luồng coverage matrix), EXT-7 (Mobile interaction).

Lịch sử thay đổi

Phiên bảnNgàyTác giảThay đổi
2.3.030/04/2026PO/BAĐồng bộ với permission-spec.md v1.0.0: thêm SCR-18 Compliance Audit Viewer (route /s/compliance/clinical-audit) cho phép Compliance officer + Admin/Ops + Medical Lead xem medical_record_access_log + emergency override sessions + anomaly + export audit Excel. SCR-18 có B2.1-B2.9 đầy đủ; B0.1 + B0.5 + B1.1 cập nhật; ngầm hiểu Day-1 hoặc Phase 2 tuỳ PD-PERM-004.
2.2.030/04/2026PO/BAĐóng các lỗ hổng nhất quán với PRD/SoT/dev-spec: (1) chuẩn hoá trợ lý cấu hình thành 6 bước (5 bước cấu hình + Kiểm tra sẵn sàng) ở B-PRE.2/B0.1/B0.5/B1.1/B1.2/B2.2/B2.7 SCR-04 + redo wireframe stepper. (2) Loại bỏ nhánh customer_id=NULL ở SCR-03/SCR-05 do dev-spec yêu cầu clinical_*.customer_id NOT NULL; walk-in chưa có hồ sơ phải tạo khách inline trước khi lưu lượt khám. (3) Thêm CTA "Tạo đơn từ lượt khám" trong danh sách lịch hẹn SCR-03. (4) Bổ sung luồng "Khách từ chối thủ thuật" (DEC-024) ở SCR-08/SCR-10 + B-edge case Nhóm 4. (5) Chuẩn hoá rule validation câu xác nhận tự gõ ở SCR-08 (≥20 ký tự, chứa "đồng ý"/"thực hiện", FE chặn dán). (6) Sửa lỗi search-replace live → đang hoạt động còn sót: B2.11 SCR-04 LIFECYCLE-001, B8.1 sự kiện. (7) Sửa "POS portal" → "Cổng tablet quầy theo token" cho SCR-15 + B-Mobile. (8) Việt hoá nhất quán: "stepper/empty state/job chạy lâu/step kế/Click → trợ lý/trạng thái rỗng/tác vụ chạy lâu/bước tiếp theo/Bấm". (9) Đổi "P0" thành "BA ưu tiên cao" trong copy hiển thị; vẫn giữ P0 trong code/log nội bộ. (10) Bổ sung trạng thái sử dụng kỹ thuật ở SCR-04c rõ hơn (cột tách bạch). (11) Đánh dấu lại "Sự kiện phân tích" ở B-PRE.2 thành ⚠ chưa xác nhận.
2.1.030/04/2026PO/BARefactor một vòng ngôn ngữ: bỏ cụm dịch máy móc, chuẩn hóa copy người dùng nhìn thấy, giữ nguyên code literal. Bổ sung chi tiết UI cho SCR-01/02/03/04a/04b/04c/04e/04f/05/08/11/12.
2.0.030/04/2026PO/BARefactor full theo glossary canonical 34 thuật ngữ + G3.7 cổng kiểm tra độ đầy đủ UI (B-PRE / B0.4 Field × nơi hiển thị / B0.5 Trạng thái×Màn hình / B-POST 12-checkpoint / B-QUALITY 15 rủi ro thiếu sót). Giữ 100% nội dung wireframe + luồng + copy.
1.5.1029/04/2026PO/BABản cũ — bị thay thế

Tài liệu đầu vào chuẩn

FileVai tròNếu xung đột
SOURCE_OF_TRUTH.mdNguồn sự thật chuẩn + Phương án đã chốtƯu tiên cao nhất
EVIDENCE_PACK.mdLayout UI hiện tại, kiểm kê hiện trạng, ứng viên reuseƯu tiên bằng chứng code/màn hình
prd.mdFR, vòng đời, rào phạm vi, công thứcTheo truth đã khóa

Quy tắc: UI Spec là tài liệu dẫn xuất, không tự phát minh rule. Không suy diễn xóa: thành phần hiện hữu vắng mặt trong target → ghi nhận khoảng trống UI Spec hoặc lệch phạm vi, không phải kỳ vọng xóa. Mọi REMOVE/HIDE phải có DEC/FR/PO approval.


B-PRE) Kiểm tra trước khi viết (BẮT BUỘC trước khi viết UI Spec)

B-PRE.1) Tìm component/page hiện có liên quan

bash
# Customer Detail tabs (CRM portal)
find diva-admin/src/modules/crm/pages/CustomerDetail.tsx

# Branch Detail tabs
find diva-admin/src/modules/user/pages/BranchDetail.tsx

# Order/Appointment forms
find diva-admin/src/modules/ecommerce/components/order/OrderForm/
find diva-admin/src/modules/ecommerce/components/appointment/AppointmentForm.tsx

# Permission v2 infra
grep -r "useGlobalStore.hasPermission" diva-admin/src/

# Existing notification + export patterns
grep -r "Export" diva-admin/src/modules/timekeeping/components/

B-PRE.2) Bảng inventory đã check

Hạng mụcĐã checkFile / màn hiện cóGhi chú
Page / đường dẫn hiện cócrm/pages/CustomerDetail.tsx (16 tabs), user/pages/BranchDetail.tsx (3 tabs), ecommerce/pages/Appointments.tsx, ecommerce/pages/OrderCreate.tsxTái sử dụng 4 shell
Component có thể tái sử dụngXDetailLayout, XTable, XFileUpload, QStepperTái sử dụng 100%
Form/dialog liên quanAppointmentForm.tsx, OrderForm/index.tsx (4 step QStepper)Mở rộng
Field/cột hiện có trên màn targetXem Evidence Pack mục 3 (As-Is UI Inventory)Có baseline đầy đủ
CTA hiện cóLưu, Hủy, Tạo mới, Xóa (đã chuẩn VI)Reuse
Bộ lọc / search hiện cóBranch bộ lọc, Date range, Trạng thái bộ lọc ở AppointmentsMở rộng với badge BA trong bộ lọc
Trạng thái hiện cóKhung tải dữ liệu, Trạng thái rỗng, Thông báo nhanh lỗi (Quasar)Reuse
Điều kiện hiển thị theo quyền/roleglobalStore.hasPermission(moduleId, actionId) + branchModeFromRole()Reuse infra; thêm 22 action mới
Trigger thông báo hiện có130+ trigger codes (noti_appointment_*, noti_order_*)Thêm 7 trigger clinical
Cột xuất dữ liệu hiện cóExportWorkingTimeSheet.tsx pattern (convertObjectsToRows)Reuse pattern
Tooltip/hintq-tooltip Quasar componentReuse
Mobile/responsiveQuasar $q.screen.lt.md breakpointsReuse
Sự kiện phân tíchChưa có inventory analytic chuẩn — cần xác nhận trước phát hànhThêm event clinical (xem B8.1)

B-PRE.3) Phân loại tái sử dụng (ref SOURCE_OF_TRUTH.md mục 4 Solution Lock)

Phần tính năngPhân loạiBằng chứngPhần cần bổ sung
Tab thứ 17 "Hồ sơ bệnh án" trong CustomerDetail🔧 Mở rộngcrm/pages/CustomerDetail.tsxThêm 1 tab + đường dẫn + component
Tab thứ 4 "Phòng khám" trong BranchDetail🔧 Mở rộnguser/pages/BranchDetail.tsxThêm 1 tab + trợ lý cấu hình 6 bước (5 bước cấu hình + Kiểm tra sẵn sàng)
Cảnh báo "cần BA" ở OrderForm bước 1🔧 Mở rộngecommerce/components/order/OrderForm/OrderFormService.tsxThêm 1 banner + 1 cờ trường
Công tắc walk-in ở AppointmentForm🔧 Mở rộngecommerce/components/appointment/AppointmentForm.tsxcustomer_id đã optional; thêm gợi ý UI
Form BA DL + TM🆕 Xây mớiKhông có form BARenderer theo JSON Schema + các phần mở rộng được
Form 5 biểu mẫu dùng chung🆕 Xây mớiKhông cóRender từ form_template
In + tải bản scan đã ký🆕 Xây mớiCó pattern print_invoice + reference_fileComponent phòng khám riêng
Sổ khám bệnh + Sổ thủ thuật🆕 Xây mớiKhông có sổBảng danh sách dẫn xuất từ clinical_record
Trang xem an toàn (Sale)🆕 Xây mớiKhông cóTrang riêng + bản xem an toàn
Bàn việc bác sĩ🆕 Xây mớiKhông cóTrang riêng + truy vấn 6 nhóm việc
Phiếu khách tự khai🆕 Xây mớiKhông cóTrang cổng KH chạy trên tablet quầy, mở bằng token một lần
Trang điều phối phòng khám🆕 Xây mớiKhông cóTrang điều phối
Chốt ngày phòng khám🆕 Xây mớiKhông cóHộp thoại trong trang điều phối

B0) Hiện trạng UI và quy ước thay đổi (As-Is + Quy ước thay đổi)

B0.1) Bảng kiểm kê đầy đủ

UI IDMàn / đường dẫnSectionBlock / field / actionThứ tự hiện tạiHành vi hiện tạiPermission/conditionMobile?Trạng thái thay đổiHành vi đíchEvidence
SCR-01-BLK-01/crm/customer/:idLeft panelCustomerEWalletInformation1Wallet, sidebar infoAllCó (responsive)KEEPKhông đổicrm/pages/CustomerDetail.tsx
SCR-01-BLK-02/crm/customer/:idHeaderStatisticCumulativeCards2Stats KHAllKEEPKhông đổi
SCR-01-BLK-03/crm/customer/:idTabs16 tabs hiện có3NavigateTheo permission từng tabKEEPKhông đổi
SCR-01-BLK-04/crm/customer/:id/clinical-recordTabsTab thứ 17 "Hồ sơ bệnh án"17(chưa có)clinical_record.accessNEWTab mới + đường dẫn + componentDEC-029
SCR-02-BLK-01/e/service-order/orders/create step 1 ServiceOrderFormServiceservice, qty, price, doctor, note(giữ nguyên)Pick serviceorder.createKEEPKhông đổiecommerce/components/order/OrderForm/OrderFormService.tsx
SCR-02-BLK-02/e/service-order/orders/create step 1OrderFormService(chưa có cảnh báo)NEWBanner cảnh báo "Cần BA" + field flag needs_clinical_recordDEC-006
SCR-03-BLK-01/e/service-order/appointmentAppointmentFormcustomer_id (optional)8Optional ở GraphQLAllKEEPKhông đổi (đã optional walk-in OK)AppointmentForm.tsx:58
SCR-03-BLK-02/e/service-order/appointmentAppointmentForm(chưa có walk-in toggle UI)NEWToggle "Khách walk-in" + hintDEC-003
SCR-03-BLK-03/e/service-order/appointment (list)Bảng(chưa có badge BA)NEWBadge "Đã có BA" + bộ lọc trạng tháiDEC-002
SCR-04-BLK-01/s/internal-settings/branch/:idTabs3 tabs (department, warehouse, service)1-3Navigatebranch.updateKEEPKhông đổiuser/pages/BranchDetail.tsx
SCR-04-BLK-02/s/internal-settings/branch/:id/clinic-configTabsTab thứ 4 "Phòng khám"4(chưa có)clinic_module.accessNEWTab + trợ lý 6 bước (5 cấu hình + 1 kiểm tra sẵn sàng)DEC-001, DEC-029, DEC-031

B0.2) Từ điển Trạng thái thay đổi

Trạng tháiÝ nghĩaEvidence bắt buộc
KEEPGiữ nguyênGhi rõ vẫn hiển thị ở target wireframe
UPDATEĐổi copy/layout/dataPRD FR/AC + ref file:line
MOVEĐổi vị trí, giữ behaviorUX luồng + ghi rõ trước/sau khu vực nào
NEWThêm mớiPRD FR/AC ref
REMOVEBỏDEC + FR/AC + PO approval (BẮT BUỘC ≥2 evidence)
HIDEẨn theo điều kiệnPermission/condition rõ

B0.3) Tiêu chí hoàn thành B0

  • [x] 100% UI hiện tại của 4 màn (CustomerDetail / BranchDetail / Appointments / OrderCreate) đã inventory
  • [x] Không có block/field/action thiếu Trạng thái thay đổi
  • [x] Mọi dòng có cột Evidence
  • [x] Không có REMOVE/HIDE (Day-1 chỉ KEEP/NEW/UPDATE) → không cần ≥2 evidence
  • [x] Target wireframe ở B2 hiển thị vùng KEEP xung quanh update

B0.4) Ma trận Field × nơi hiển thị (12 cột) — BẮT BUỘC cho field mới/sửa

Mọi field mới/sửa đều có 1 dòng với 12 cột. Cell trống → không đạt G3.7.

FieldBảng danh sáchChi tiết/FormHộp thoạiXuất ExcelTìm kiếmBộ lọcĐiều kiện theo quyềnMobileThông báoTrạng thái mặc địnhValidationTooltip
branch.features.clinic_enabledN/ACó (toggle BranchDetail)N/AN/AN/ACó (bộ lọc CN có/không PK)clinic_module.configureCó (noti_clinic_module_published)falseBOOL"Bật module Phòng khám cho chi nhánh này. Trạng thái mặc định tắt với chi nhánh spa thuần"
clinic_module_publication.statusCó (cột "Trạng thái phát hành")Có (BranchDetail tab Phòng khám)N/ACó (export trạng thái CN)Có (bộ lọc trạng thái live/paused/scheduled/...)clinic_module.accessoffENUM"Trạng thái phát hành module: Tắt / Đang cấu hình / Đã sẵn sàng / Đã lập lịch / Đang hoạt động / Đã tạm dừng"
service_clinical_classification.classification_statusCó (cột "Phân loại")Có (form classification)Có (popup mass classification — Phase 2)Có (3 trạng thái)clinic_module.configureN/AunclassifiedENUM (mapped_requires_ba/explicitly_no_ba/unclassified)"Phân loại dịch vụ — kỹ thuật: Cần bệnh án / Không cần bệnh án (đã xác nhận) / Chưa phân loại"
clinical_record.profile_codeCó (cột "Mã BA")N/Aclinical_record.view_summary(auto FORMULA-001)Pattern DVA-[TM|DL]-[CN]-[YYYY]-[NNNNN]"Mã hồ sơ bệnh án chính: định danh duy nhất theo khách hàng, chi nhánh và loại phòng khám. Không reset theo năm"
clinical_record.visit_log_numberCó (cột "STT sổ khám")N/AN/Aclinical_record.view_summaryN/A(auto FORMULA-002)Pattern DVA-[CN]-[NNNNN]/[YYYY]"Số thứ tự sổ khám bệnh, reset theo năm. Mỗi lượt khám = 1 STT"
clinical_record.procedure_log_numberCó (cột "STT sổ thủ thuật")N/AN/Aclinical_record.view_summaryN/A(auto FORMULA-003)Pattern DVA-[CN]-TT-[NNNNN]/[YYYY]"Số thứ tự sổ thủ thuật, reset theo năm. Chỉ ca có kỹ thuật thủ thuật"
clinical_record.statusCó (badge)N/Aclinical_record.view_summarydraftENUM (draft/completed/printed/signed/superseded/archived)"Trạng thái bệnh án lượt khám: Bản nháp / Đã hoàn thành / Đã in / Đã ký + scan đủ / Bản thay thế / Đã lưu trữ"
clinical_form_instance.form_dataN/ACó (form section expandable)N/AN/A (không export raw)N/AN/Aclinical_record.edit_medical_form (write) / view_medical_detail (read tầng 3)N/A{}JSON Schema từ form_template"Nội dung phiếu biểu mẫu (JSONB). Backend validate theo JSON Schema trước khi lưu"
clinical_record.diagnosis_codes (ICD-10 primary + secondary)N/ACó (dropdown searchable)N/ACó (cột chẩn đoán)Có (bộ lọc ICD chapter)clinical_record.view_medical_detail (xem) / edit_medical_form (sửa)N/A[]≥1 primary; ≤5 secondary"Mã chẩn đoán theo ICD-10 (TT46/2018). 1 mã chính bắt buộc + tối đa 5 mã phụ"
prescription.itemsN/ACó (table thuốc trong popup)Có (đơn thuốc)N/AN/Aclinical_record.edit_medical_formN/A[]≥1 item nếu kê"Danh mục thuốc trong đơn theo TT52/2017"
customer_clinical_intake.tokenN/AN/A (token-based access)N/AN/AN/AN/Acustomer_clinical_intake.open_sessionCó (tablet)N/A(auto sinh)UUID + expires_at = NOW + 15 phút"Token một lần cho phiên khách tự khai. Hết hạn sau 15 phút"
clinic_daily_close.closed_atCó (lịch sử chốt ngày)Có (hộp thoại chốt)Có (bộ lọc ngày chốt)clinic_daily_close.close_branch_dayCó (noti_medical_record_end_of_day)NULLTIMESTAMPTZ"Thời điểm QL CN bấm 'Chốt ngày'. Cron tự ghi nhận trạng thái tại cutoff"
medical_record_access_log.actionCó (audit trail)N/ACó (audit export — chỉ Admin/Compliance)Có (bộ lọc action)clinical_record.view_medical_detail (Admin audit)N/ACó (noti_medical_record_emergency_override)(auto từ event)ENUM (view_summary/view_medical_detail/print/upload_scan/export/emergency_override)"Loại thao tác mở dữ liệu nhạy cảm tầng 3. Mọi emergency_override phải có lý do"

B0.5) Ma trận Trạng thái × màn hình (6 trạng thái) — BẮT BUỘC cho mọi màn có data

Màn / khốiTrạng thái mặc địnhĐang tảiTrốngLỗi + thử lạiKhông có quyềnThành công một phần
SCR-01 (CustomerDetail tab Hồ sơ bệnh án)Danh sách BA của KH (50 dòng/trang)Khung tải 5 dòng"Khách chưa có hồ sơ bệnh án nào" + CTA "Tạo lượt khám mới""Không thể tải dữ liệu. Vui lòng thử lại." + nút Thử lạiẨn cả tab (guard đường dẫn)N/A
SCR-04 (BranchDetail tab Phòng khám)Hiện trợ lý cấu hình 6 bướcLớp chờ xử lý trên bước hiện tại"Chưa cấu hình" + CTA "Bắt đầu cấu hình"Lỗi tại field + banner tổngẨn cả tabN/A (đi tuần tự từng bước, không cho lưu một phần)
SCR-04d (Phân loại dịch vụ — kỹ thuật)Bảng 50 dịch vụ đang bánKhung tải"Chưa có dịch vụ đang bán tại CN này"Thông báo nhanh "Không tải được — Thử lại"Ẩn nút LưuThông báo nhanh "Đã lưu X/Y dịch vụ. {Z} lỗi"
SCR-05 (Tạo lượt khám popup)Form rỗngNút Lưu hiển thị đang xử lýN/ALỗi tại field + bannerKhóa nút "Lưu" + tooltipN/A
SCR-06 / SCR-07 (Form BA DL/TM)Form rỗng + section mở rộng theo dịch vụKhung tải 3 phầnN/ALỗi tại fieldẨn CTA "Hoàn thành""Đã lưu nháp lúc HH:mm" thông báo nhanh (autosave)
SCR-08 (5 biểu mẫu shared)Thanh tab biểu mẫu + form theo khuônKhung tảiN/ALỗi tại field + bannerẨn CTAN/A
SCR-09 (Xem trước PDF)iframe PDF"Đang tạo PDF..." spinnerN/A"Không tạo được PDF. Thử lại" + nút Thử lạiẨn nút InN/A
SCR-10 (Tải bản scan đã ký)Drop zone + checklist scan"Đang tải lên {N}/{M}..." progress"Chưa có file scan""Tải lỗi {filename}. Thử lại"Ẩn drop zone"Đã tải {X}/{Y} file. {Z} lỗi" thông báo nhanh
SCR-11 / SCR-12 (Sổ khám / Sổ thủ thuật)Bảng 50 dòng/trangKhung tải"Chưa có lượt khám trong khoảng {từ}-{đến}""Không tải được. Thử lại"Ẩn đường dẫn"Đã xuất {X}/{Y} dòng. {Z} dòng bị ẩn theo phân quyền" thông báo nhanh
SCR-13 (Trang xem an toàn — Sale)Thẻ tóm tắt tầng 1+2 + từ điển cảnh báoKhung tải"Khách chưa có cảnh báo an toàn"Thông báo nhanhẨn đường dẫnN/A
SCR-14 (Bàn việc bác sĩ)6 nhóm việc + số lượng + danh sách việcKhung tải 6 thẻ"Hôm nay không có việc nào tại CN này"Thông báo nhanh + nút Thử lạiẨn đường dẫn"Đã hoàn thành {X}/{Y} việc" badge
SCR-15 (Phiếu khách tự khai)Form phiếu tự khaiĐang tảiN/ALỗi tại field + banner "Phiên đã hết hạn" nếu token expired"Phiên đã hết hạn. Vui lòng nhờ lễ tân mở lại.""Đã lưu {X}/{Y} câu trả lời"
SCR-16 (Trang điều phối)Thẻ CN + cảnh báo lệch cấu hìnhKhung tải 12 thẻ"Chưa có CN nào đang hoạt động"Thông báo nhanh + Thử lạiẨn đường dẫnN/A
SCR-17 (Hộp thoại chốt ngày)Hộp thoại xác nhận với countNút Chốt hiển thị đang xử lýN/ALỗi tại fieldẨn nút Chốt"Đã chốt ngày. Còn {X} BA chưa scan đã gửi cảnh báo" thông báo nhanh
SCR-18 (Compliance Audit Viewer)Bảng 50 events đầu trong 7 ngày + filter + anomaly countKhung tải bảng + filter"Không có event audit trong khoảng này.""Không tải được audit. Thử lại." + Thử lạiĐường dẫn 401 (chỉ Compliance + Admin/Ops + Medical Lead)"Đã xuất {X} dòng. Bấm tải về." thông báo nhanh

B0.6) Quy ước ngôn ngữ giao diện sau refactor

Dùng bảng này khi viết label, thông báo nhanh, trạng thái rỗng, tooltip và wireframe. Code field/action/route vẫn giữ nguyên trong backtick; chỉ đổi câu chữ người dùng nhìn thấy.

Cụm dễ máy mócCách viết trong UIDùng ở đâu
"Submit", "Confirm", "Save draft""Lưu", "Xác nhận", "Lưu nháp"Nút thao tác
"Loading", "No data", "Error""Đang tải dữ liệu...", "Chưa có dữ liệu", "Không thể tải dữ liệu. Vui lòng thử lại."Trạng thái màn hình
"Upload scan""Tải bản scan đã ký"SCR-10, Bàn việc bác sĩ
"Preview impact""Xem trước tác động khi áp dụng"Hộp thoại phát hành module
"Sales-safe view""Trang xem an toàn (Sale)"CRM/Sale
"Doctor workbench""Bàn việc bác sĩ"POS/Clinical
"Customer intake""Phiếu khách tự khai"Tablet quầy
"Review intake""Rà soát phiếu tự khai" hoặc CTA "Nhận vào hồ sơ"Bác sĩ/y tá
"Publication status""Trạng thái phát hành"Branch Detail, Trang điều phối
"Runtime live gate""Điều kiện mở vận hành"Mô tả kỹ thuật trong tooltip/copy nội bộ
"Field hidden by permission""Bị ẩn theo phân quyền"Badge/placeholder dữ liệu tầng 3
"Safe alert""Nhãn cảnh báo an toàn"Sale, Customer Detail
"P0 record / P0 case""Bệnh án ưu tiên cao"Copy hiển thị; mã P0 chỉ dùng trong code/log
"Stepper / 5-step stepper""Trợ lý cấu hình (6 bước)"Mô tả wizard SCR-04
"Click" (verb)"Bấm"Câu chỉ dẫn người dùng
"Empty state""Trạng thái rỗng"Tài liệu nội bộ
"Job chạy lâu" / "long job""Tác vụ chạy lâu"Mô tả hành vi

Nguyên tắc copy: mỗi thông báo lỗi phải nói rõ người dùng cần làm gì tiếp theo. Ví dụ: không viết "Không hợp lệ"; viết "Vui lòng chọn ít nhất 1 mã ICD-10 chính".


B1) Bản đồ màn hình và hành trình

B1.1) Danh sách màn

SCRTênĐường dẫnLoạiMô tả
SCR-01Hồ sơ bệnh án (tab thứ 17 CustomerDetail)/crm/customer/:id/clinical-record (CRM) hoặc /u/customer/:id/clinical-record (User)🔧 Mở rộngTab mới hiển thị Hồ sơ bệnh án chính + danh sách Bệnh án lượt khám
SCR-02Cảnh báo "cần BA" ở OrderForm bước Dịch vụ/e/service-order/orders/create step 1🔧 Mở rộngBanner + cờ trường khi dịch vụ mapped_requires_ba
SCR-03AppointmentForm walk-in toggle/e/service-order/appointment/create🔧 Mở rộngToggle "Khách walk-in" + badge BA trên danh sách
SCR-04BranchDetail tab Phòng khám/s/internal-settings/branch/:id/clinic-config🔧 Mở rộngTab thứ 4 + trợ lý cấu hình 6 bước (5 bước cấu hình + Kiểm tra sẵn sàng)
SCR-04a..fSáu bước cấu hình phòng khám(con của SCR-04)🆕 Xây mớiBước 1 Loại PK / Bước 2 Giấy phép / Bước 3 Danh mục KT / Bước 4 Phân loại dịch vụ — kỹ thuật / Bước 5 Phân quyền / Bước 6 Kiểm tra sẵn sàng
SCR-05Tạo lượt khám (popup)(popup)🆕 Xây mớiForm tạo appointment với walk-in toggle
SCR-06Form BA Da liễu/e/service-order/clinical-records/:id/ba-dl🆕 Xây mớiForm 6 phần mở rộng được + danh sách ICD-10
SCR-07Form BA Thẩm mỹ (4 phân hệ)/e/service-order/clinical-records/:id/ba-tm🆕 Xây mớiForm tự hiện phần tương ứng theo dịch vụ POS
SCR-08Form 5 biểu mẫu dùng chung(popup từ SCR-06/07)🆕 Xây mớiCam đoan / cam kết / đơn thuốc / phiếu dị ứng / phiếu theo dõi điều trị
SCR-09Xem trước PDF + In bộ hồ sơ(popup)🆕 Xây mớiiframe xem trước PDF + nút In
SCR-10Tải bản scan đã ký(popup từ SCR-01)🆕 Xây mớiVùng thả file + mapping file ↔ biểu mẫu + checklist scan
SCR-11Sổ khám bệnh/e/service-order/clinical-visit-log🆕 Xây mớiBảng lượt khám + bộ lọc + xuất dữ liệu
SCR-12Sổ thủ thuật/e/service-order/clinical-procedure-log🆕 Xây mớiTương tự SCR-11, chỉ ca thủ thuật
SCR-13Trang xem an toàn (Sale)/crm/customer/:id/sales-safe-clinical🆕 Xây mớiTab dành cho Sale, chỉ tầng 1+2 + từ điển cảnh báo
SCR-14Bàn việc bác sĩ/e/service-order/doctor-workbench🆕 Xây mới6 nhóm việc trong ngày
SCR-15Phiếu khách tự khai/p/customer-clinical-intake/:token🆕 Xây mớiCổng KH (tablet quầy), mở bằng token 15 phút, KH tự điền
SCR-16Trang điều phối phòng khám/e/service-order/clinic-ops-dashboard🆕 Xây mớiTrang điều phối rollout toàn chuỗi
SCR-17Chốt ngày phòng khám (hộp thoại)(hộp thoại trong SCR-16)🆕 Xây mớiHộp thoại xác nhận + log clinic_daily_close
SCR-18Trang Compliance Audit Viewer/s/compliance/clinical-audit🆕 Xây mớiCompliance officer xem medical_record_access_log + emergency override + anomaly + export audit; Day-1 hoặc Phase 2 tuỳ PD-PERM-004

B1.2) Hành trình end-to-end

Hành trình theo vai trò:

Vai tròEntry pointĐường mànKết quả đầu ra
Admin/OpsSettings → Branch DetailSCR-04 → SCR-04a..f → kiểm tra sẵn sàng → phát hànhModule ở live, UI clinical xuất hiện cho team CN
Bác sĩBàn việc bác sĩSCR-14 → SCR-05 → SCR-06/07 → SCR-08 → SCR-09Bệnh án signed
Y táBàn việc bác sĩ (nhóm need_scan)SCR-14 → SCR-10Scan checklist đủ
Lễ tânPOS Order hoặc AppointmentSCR-02 → SCR-05 (popup)Lượt khám tạo
Tư vấn viên (Sale)Customer Detail (CRM)SCR-13 → form chuyển BSPhiếu chuyển bác sĩ tư vấn
QL CNTrang điều phối phòng khámSCR-16 → SCR-17Đã chốt ngày
Khách hàngTablet quầy (token)SCR-15Phiếu khách tự khai gửi
OpsTrang điều phối phòng khámSCR-16 (toàn chuỗi)Lệch cấu hình + gửi cảnh báo

B2) Chi tiết SCR (theo thứ tự phụ thuộc)

Mỗi SCR phải có đủ: ngữ cảnh, bố cục, field/cột chính, tương tác, phân quyền, trạng thái và phản hồi sau thao tác. ASCII wireframe dùng dữ liệu ngành spa/phòng khám thật.

SCR-01: CustomerDetail — tab Hồ sơ bệnh án

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Bác sĩ, y tá, QL CN, Admin/Ops và người có quyền xem tóm tắt hồ sơ bệnh án
Vào màn để quyết định gì?Xem Hồ sơ bệnh án chính của khách, lịch sử Bệnh án lượt khám, trạng thái in/scan và cảnh báo an toàn
Dữ liệu chínhclinical_profile, clinical_record, clinical_form_instance, reference_file, medical_record_access_log
CTA chính / phụPrimary: "Tạo lượt khám mới"; Secondary: "Tải bản scan đã ký", "Mở quyền khẩn cấp", "Xuất sổ khám"
Điều không được hiểu nhầmTab này là phần mở rộng của CustomerDetail hiện tại. 16 tab cũ giữ nguyên; tab mới chỉ hiện khi có clinical_record.view_summary

B2.2) Bố cục — gắn vào CustomerDetail hiện tại

text
/crm/customer/{id}/clinical-record       [CustomerDetail — mở rộng tab thứ 17]

┌────────────────────────────────────────────────────────────────────────────┐
│ Header KH: Lê Thị Hương · 0909 123 456 · CN gần nhất: Cao Lãnh            │
├──────────────────┬─────────────────────────────────────────────────────────┤
│ Sidebar KH       │ Tabs hiện có: [Tổng quan] [Ví] [Đơn hàng] ... [16 tabs] │
│ (KEEP)           │ [Hồ sơ bệnh án ★ NEW]                                  │
│                  ├─────────────────────────────────────────────────────────┤
│ Wallet, tag VIP  │ ┌─ Hồ sơ bệnh án chính ──────────────────────────────┐ │
│ Lịch sử mua      │ │ Mã BA chính: DVA-DL-CL-2026-00147                  │ │
│ Ghi chú CRM      │ │ Loại: Da liễu · CN tạo: Cao Lãnh · Tạo: 02/05/2026 │ │
│                  │ │ Cảnh báo an toàn: Dị ứng Penicillin · Bệnh nền: ĐTĐ│ │
│                  │ └────────────────────────────────────────────────────┘ │
│                  │                                                         │
│                  │ [Tạo lượt khám mới] [Mở phiên khách tự khai] [Xuất sổ] │
│                  │                                                         │
│                  │ Bộ lọc: [Từ ngày] [Đến ngày] [Trạng thái BA ▼] [Loại ▼]│
│                  │                                                         │
│                  │ ┌────┬──────────┬──────────────┬────────┬────────────┐ │
│                  │ │Ngày│ STT sổ   │ Loại BA      │ BS     │ Trạng thái │ │
│                  │ ├────┼──────────┼──────────────┼────────┼────────────┤ │
│                  │ │02/5│ DVA-CL...│ Da liễu      │ BS Hương│ Đã ký+scan│ │
│                  │ │28/4│ DVA-CL...│ Thẩm mỹ      │ BS Long │ Cần scan  │ │
│                  │ │15/4│ DVA-CL...│ Da liễu      │ BS Hương│ Bản nháp  │ │
│                  │ └────┴──────────┴──────────────┴────────┴────────────┘ │
└──────────────────┴─────────────────────────────────────────────────────────┘

B2.3) Cột và hành động trong bảng

Cột / hành độngHiển thịĐiều kiện
Ngày khámDD/MM/YYYY HH:mmLuôn hiện với view_summary
STT sổ khám / thủ thuậtvisit_log_number hoặc procedure_log_numberTrống thì hiển thị "Chưa cấp số"
Loại BA"Da liễu", "Thẩm mỹ"Theo form_type
Bác sĩ phụ tráchTên BS + chi nhánhLuôn hiện với view_summary
Trạng thái BABadge theo draft/completed/printed/signed/...Ref B2.11 LIFECYCLE-002
Cảnh báo scan"Cần scan", "Thiếu: Cam kết"Chỉ hiện khi status='printed' hoặc checklist thiếu
Xem chi tiếtMở form BA readonly/editableTầng 3 chỉ hiện nếu có view_medical_detail
Tải bản scan đã kýMở SCR-10Khi status='printed' và có upload_scan
Mở quyền khẩn cấpMở hộp thoại lý doChỉ khi khác CN và có emergency_override

B2.4) Quy ước tương tác

Tình huốngHành vi
Khách chưa có BAHiển thị empty state "Khách chưa có hồ sơ bệnh án nào" + CTA "Tạo lượt khám mới"
Có BA khác chi nhánhHiển thị tầng 1+2; field tầng 3 = "—" + tooltip "Bị ẩn theo phân quyền"
Bấm "Mở quyền khẩn cấp"Bắt nhập lý do ≥30 ký tự; sau xác nhận ghi medical_record_access_log; session tầng 3 hết hạn sau 1 giờ
Bấm "Tạo lượt khám mới"Mở SCR-05, prefill khách hiện tại + CN hiện tại nếu user chỉ quản lý 1 CN
Filter trả 0 dòngCopy: "Không có bệnh án phù hợp với bộ lọc. Vui lòng thử lại với điều kiện khác."

B2.5) Phân quyền và trạng thái

QuyềnUI
Không có clinical_record.view_summaryẨn tab Hồ sơ bệnh án; route guard trả 403
view_summary, không có view_medical_detailThấy mã BA, trạng thái, số lượt, cảnh báo an toàn; không thấy ICD-10, ghi chú BS, form raw, ảnh, scan
view_medical_detail cùng CNThấy tầng 3 đầy đủ theo branch scope
SaleKhông dùng SCR-01 để xem y tế; chuyển sang SCR-13 nếu có quyền clinical_sales.view_safe_summary

B2.6) Variant wireframes per role (BẮT BUỘC theo permission-spec.md P10 + ui-spec template B2.2.0)

Mỗi variant render khác nhau theo view_mode từ resolver. FE đọc response trả về, không tự suy luận.

Variant A — BS cùng CN (view_mode='full_tier3')

text
[Tab Hồ sơ bệnh án — BS cùng CN]
┌─ Hồ sơ bệnh án chính ──────────────────────────────┐
│ Mã BA: DVA-DL-CL-2026-00147                        │
│ Loại: Da liễu · CN tạo: Cao Lãnh · Tạo: 02/05/2026 │
│ Cảnh báo an toàn: ⚠ Dị ứng Penicillin (NẶNG)       │
│ Bệnh nền: Đái tháo đường týp 2                     │
└────────────────────────────────────────────────────┘

[Tạo lượt khám mới] [Mở phiên khách tự khai] [Xuất sổ]

┌────┬──────────┬──────────────┬────────┬────────────┬──────────────┐
│Ngày│ STT      │ Loại BA      │ BS     │ Trạng thái │ Chẩn đoán    │
├────┼──────────┼──────────────┼────────┼────────────┼──────────────┤
│02/5│DVA-CL...│ Da liễu      │BS Hương│ Đã ký+scan │ L70.0 + L73.2│ ← TẦNG 3 hiện
│28/4│DVA-CL...│ Thẩm mỹ      │BS Long │ Cần scan   │ Q67.4        │
│15/4│DVA-CL...│ Da liễu      │BS Hương│ Bản nháp   │ (chưa nhập)  │
└────┴──────────┴──────────────┴────────┴────────────┴──────────────┘

Row action: [Xem BA] [Tải bản scan đã ký] [In lại]

Field allowlist: mọi field theo permission-spec.md P10 (full_tier3)

Variant B — BS khác CN (view_mode='summary', không emergency)

text
[Tab Hồ sơ bệnh án — BS CN khác]
┌─ Hồ sơ bệnh án chính ──────────────────────────────┐
│ Mã BA: DVA-DL-CL-2026-00147                        │
│ Loại: Da liễu · CN tạo: Cao Lãnh                   │
│ Cảnh báo an toàn: ⚠ Có dị ứng — chuyển BS          │  ← chỉ level/code
└────────────────────────────────────────────────────┘

⚠ Bạn không thuộc CN tạo. Tầng 3 (chẩn đoán, đơn thuốc, ảnh y tế)
  bị ẩn theo phân quyền. Mở quyền khẩn cấp nếu là tình huống cấp cứu.

[Mở quyền khẩn cấp]                    [Tạo lượt khám mới] (CN hiện tại)

┌────┬──────────┬──────────────┬────────┬────────────┬──────────────┐
│Ngày│ STT      │ Loại BA      │ BS     │ Trạng thái │ Chẩn đoán    │
├────┼──────────┼──────────────┼────────┼────────────┼──────────────┤
│02/5│DVA-CL...│ Da liễu      │BS Hương│ Đã ký+scan │ —            │ ← TẦNG 3 ẩn
│28/4│DVA-CL...│ Thẩm mỹ      │BS Long │ Cần scan   │ —            │
└────┴──────────┴──────────────┴────────┴────────────┴──────────────┘

Row action: [Xem tóm tắt] (no [Xem BA full])

Field allowlist: chỉ tầng 1+2 — id, profile_code, visit_log_number, status, form_type, primary_doctor_id, created_at, branch_id, allergy_summary (level only); ICD/diagnosis/form_data omit.

Variant C — Y tá cùng CN (view_mode='admin_shared')

text
[Tab Hồ sơ bệnh án — Y tá]
┌─ Hồ sơ bệnh án chính ──────────────────────────────┐
│ Mã BA: DVA-DL-CL-2026-00147                        │
│ Cảnh báo an toàn: ⚠ Dị ứng Penicillin (NẶNG)       │
│ Bệnh nền: Đái tháo đường týp 2                     │
└────────────────────────────────────────────────────┘

[Tạo lượt khám mới] [Mở phiên khách tự khai]
                                  (KHÔNG có [Xuất sổ])

┌────┬──────────┬──────────────┬────────┬────────────┬──────────┐
│Ngày│ STT      │ Loại BA      │ BS     │ Trạng thái │ Scan     │
├────┼──────────┼──────────────┼────────┼────────────┼──────────┤
│02/5│DVA-CL...│ Da liễu      │BS Hương│ Cần scan   │ Thiếu 2  │ ← Y tá thấy việc cần scan
│28/4│DVA-CL...│ Thẩm mỹ      │BS Long │ Đã in      │ —        │
└────┴──────────┴──────────────┴────────┴────────────┴──────────┘

Row action: [Tải bản scan đã ký] [Mở phiếu hành chính]
            (no [Sửa chẩn đoán])

Field allowlist: tầng 1+2 + phần hành chính của form_data (admin_shared); chẩn đoán/y lệnh ẩn.

Variant D — Sale CRM (chuyển sang SCR-13)

text
[Tab Hồ sơ bệnh án] (Sale CRM portal)

⛔ Bạn không có quyền xem nội dung y tế.

Vui lòng dùng [Trang xem an toàn (Sale)] để tư vấn KH.

[Đến Trang xem an toàn (Sale) →]

Field allowlist: không có gì — Sale bị hard-deny tầng 3 (permission-spec.md P1.3). Hiển thị banner redirect, không list BA.

Variant E — User không có view_summary (Lễ tân, role chưa được cấp)

text
(Tab Hồ sơ bệnh án không hiển thị trong Customer Detail)

Behavior: route guard tại Customer Detail không render tab; nếu user gõ URL /crm/customer/:id/clinical-record trực tiếp → 403 + redirect về /crm/customer/:id với toast "Bạn không có quyền xem mục này".

Variant F — Loading + Error + Empty

StateUI
LoadingSkeleton 5 dòng + spinner header card "Hồ sơ bệnh án chính"; CTA disabled
Error tải dữ liệuBanner đỏ "Không thể tải hồ sơ bệnh án. Vui lòng thử lại." + nút [Thử lại]
Empty (KH chưa có BA)Card header "Khách chưa có hồ sơ bệnh án" + CTA [Tạo lượt khám mới] + hint "Tạo lượt khám đầu tiên cho khách này"

Variant G — Emergency override active (view_mode='full_tier3' tạm thời)

Như Variant A nhưng có badge:

text
🚨 PHIÊN KHẨN CẤP CÒN 0:42:18                       [Đóng phiên]
   Lý do: "Khách cấp cứu chuyển từ TBII, cần xem chẩn đoán cũ"
   Mọi thao tác sẽ được ghi audit log.

(... bên dưới giống Variant A)

Tổng: 7 variant cho SCR-01. FE phải implement đủ; QA test TC-PERM-MASK-01..05 + TC-PERM-EO-01..08 verify từng variant.

SCR-02: OrderForm — cảnh báo dịch vụ cần bệnh án

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Lễ tân/POS khi tạo đơn dịch vụ
Vào màn để quyết định gì?Biết dịch vụ nào cần Bệnh án lượt khám trước khi thực hiện, tránh bán dịch vụ xâm lấn mà không tạo BA
Dữ liệu chínhorder_item.product_id, service_clinical_classification.classification_status, technical_category, appointment.reference_appointment_id
CTA chính / phụPrimary: "Tạo đơn"; Secondary: "Tạo lượt khám", "Xem dịch vụ cần BA"
Điều không được hiểu nhầmunclassified không được hiểu là "không cần BA"; phải chặn hoặc yêu cầu QL CN phân loại trước khi hoàn tất

B2.2) Bố cục — mở rộng bước Dịch vụ trong OrderForm

text
/e/service-order/orders/create              [OrderForm bước 1 — Dịch vụ]

┌─ Bước 1/4: Chọn dịch vụ ─────────────────────────────────────────────┐
│ KH: Lê Thị Hương · CN: Cao Lãnh                                      │
│                                                                      │
│ Dịch vụ đã chọn:                                                     │
│ ┌──────────────────────────┬─────────┬──────────────┬──────────────┐ │
│ │ Dịch vụ                  │ Số tiền │ Phân loại BA │ Thao tác      │ │
│ ├──────────────────────────┼─────────┼──────────────┼──────────────┤ │
│ │ Liệu trình trị mụn 5 buổi│3.500.000đ│ Cần BA       │ [Tạo lượt khám]│ │
│ │ Tư vấn miễn phí          │0đ       │ Không cần BA │ —             │ │
│ │ Laser CO2 mới            │2.800.000đ│ Chưa phân loại│ [Đến danh mục dịch vụ →]│
│ └──────────────────────────┴─────────┴──────────────┴──────────────┘ │
│                                                                      │
│ ⚠ Có 1 dịch vụ cần bệnh án trước khi thực hiện.                      │
│   Vui lòng tạo lượt khám hoặc gắn với lượt khám đã có.               │
│                                                                      │
│ ⛔ Có 1 dịch vụ chưa phân loại. Không thể hoàn tất đơn cho tới khi    │
│   QL CN/Admin phân loại dịch vụ — kỹ thuật.                          │
│                                                                      │
│ [Quay lại]                                      [Tiếp] (bị khóa)     │
└──────────────────────────────────────────────────────────────────────┘

B2.3) Quy tắc hiển thị cảnh báo

ClassificationBadgeHành vi
mapped_requires_ba"Cần BA"Hiện banner vàng; nếu chưa có lượt khám phù hợp thì hiện CTA "Tạo lượt khám"
explicitly_no_ba"Không cần BA"Không cảnh báo
unclassified"Chưa phân loại"Banner đỏ; khóa nút "Tiếp"; deeplink đến SCR-04d nếu user có quyền cấu hình
Không có module PK tại CNKhông hiện badge BAOrderForm giữ nguyên như hiện tại

B2.4) Quy ước tương tác

Tình huốngHành vi
Một đơn có nhiều dịch vụ cần BAGom 1 banner, liệt kê tên dịch vụ; không lặp nhiều banner
Dịch vụ cần BA đã có appointment phù hợp trong ngàyCTA đổi thành "Gắn lượt khám đã có"
Tạo lượt khám từ đơnMở SCR-05, prefill KH, CN, danh sách dịch vụ và order_item_id nếu đã có
User không có quyền tạo lượt khámCTA ẩn; banner vẫn nói "Vui lòng chuyển bác sĩ/lễ tân có quyền tạo lượt khám"
Lưu đơn nhápCho lưu nháp, nhưng không cho chuyển trạng thái thực hiện dịch vụ nếu còn unclassified

B2.5) Copy bắt buộc

Tình huốngCopy
Có dịch vụ cần BA"Có {N} dịch vụ cần bệnh án trước khi thực hiện."
Chưa phân loại"Dịch vụ chưa phân loại. Vui lòng phân loại dịch vụ — kỹ thuật trước khi hoàn tất đơn."
Không có quyền"Bạn không có quyền tạo lượt khám. Vui lòng chuyển cho lễ tân hoặc bác sĩ phụ trách."

SCR-03: AppointmentForm — khách walk-in và badge bệnh án

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Lễ tân, y tá, bác sĩ trực quầy
Vào màn để quyết định gì?Tạo lượt khám cho khách có lịch hoặc khách walk-in; nhìn nhanh lịch hẹn nào đã có/thiếu BA
Dữ liệu chínhappointment, appointment.customer_id, appointment.order_item_id, clinical_record.status, order.reference_appointment_id
CTA chính / phụPrimary: "Lưu lịch hẹn"; Secondary: "Tạo lượt khám", "Tạo khách mới", "Gắn đơn sau"
Điều không được hiểu nhầmWalk-in hợp lệ chỉ ở order_item_id=NULL. customer_id BẮT BUỘC có (theo schema dev-spec): nếu KH chưa có hồ sơ thì lễ tân tạo KH mới inline trước khi lưu lượt khám. Backend null-guard order_item_id, không tạo đơn giả

B2.2) Form tạo/sửa lịch hẹn

text
[Tạo lịch hẹn / lượt khám]                                      [×]

CN: [Cao Lãnh ▼]       Ngày giờ: [02/05/2026 14:30]

☑ Khách walk-in
   ├─ KH đã có hồ sơ?  [Tìm SĐT / tên khách...]
   └─ Chưa có hồ sơ?   [+ Tạo khách mới ngay] (mở popup tạo KH inline)
       Sau khi tạo xong, hệ thống tự gắn `customer_id` mới vào lịch hẹn.

Dịch vụ dự kiến: [Liệu trình trị mụn 5 buổi ▼]      Badge: [Cần BA]
Bác sĩ phụ trách: [BS Trần Mỹ Hương ▼]
Ghi chú quầy: [Khách đến trực tiếp, khám trước rồi quyết định dịch vụ]

⚠ Lượt khám walk-in chưa cần đơn hàng. Sau khi bác sĩ khám xong, lễ tân có thể
  tạo đơn và gắn `reference_appointment_id` vào lượt khám này.

[Hủy]                                                [Lưu lịch hẹn]

B2.3) Danh sách lịch hẹn — badge bệnh án

text
/e/service-order/appointment

[Ngày: 02/05/2026] [CN: Cao Lãnh] [Trạng thái BA: Tất cả ▼] [Walk-in: Tất cả ▼]

┌──────┬──────────────┬──────────────┬──────────────┬────────────┬─────────────────────┐
│ Giờ  │ Khách        │ Dịch vụ      │ Bác sĩ       │ BA         │ Thao tác             │
├──────┼──────────────┼──────────────┼──────────────┼────────────┼─────────────────────┤
│09:00 │ Nguyễn Lan   │ Nâng mũi     │ BS Long      │ Cần BA     │ [Tạo BA]             │
│10:30 │ Trần Hà (mới)│ Tư vấn       │ BS Hương     │ Không cần  │ [Mở] [Tạo đơn]       │
│14:30 │ Lê Hương     │ Trị mụn      │ BS Hương     │ Đã có BA   │ [Xem BA] [Tạo đơn]   │
│15:00 │ Phạm Hà      │ Laser CO2    │ BS Hương     │ BA nháp    │ [Mở nháp]            │
└──────┴──────────────┴──────────────┴──────────────┴────────────┴─────────────────────┘

Ghi chú: với lịch walk-in chưa có đơn (appointment.order_item_id=NULL), CTA [Tạo đơn] chỉ hiện sau khi BS hoàn thành BA hoặc xác nhận xong dịch vụ; tạo đơn → order.reference_appointment_id link muộn (DEC-003), không backfill appointment.order_item_id.

B2.4) Quy tắc badge

BadgeĐiều kiện
"Không cần BA"Tất cả dịch vụ trong lịch hẹn là explicitly_no_ba
"Cần BA"Có ít nhất 1 dịch vụ mapped_requires_ba và chưa có clinical_record
"BA nháp"clinical_record.status='draft'
"Đã có BA"completed/printed/signed
"Cần scan"status='printed' nhưng checklist scan chưa đủ
"Chưa phân loại"Có dịch vụ unclassified; ưu tiên hiển thị cao nhất

B2.5) Null guard UI

Trường hợpHành vi
customer_id=NULLKhông xảy ra ở Day-1 — schema yêu cầu clinical_*.customer_id NOT NULL. UI buộc tạo KH mới inline trước khi lưu lượt khám. Nếu legacy data còn dòng customer_id=NULL, danh sách hiển thị "Hồ sơ KH chưa rõ — bổ sung trước khi in BA" và chặn CTA "Tạo BA"/"In bộ hồ sơ"
order_item_id=NULLHiển thị "Chưa gắn đơn"; CTA "Tạo đơn từ lượt khám" hiện sau khi BS hoàn thành BA
reference_appointment_id đã gắnHiển thị mã đơn liên quan; không backfill appointment.order_item_id (DEC-003)
CN không bật module PKKhông hiện badge BA; AppointmentForm giữ nguyên hành vi cũ

SCR-04: BranchDetail — tab Phòng khám (5 bước cấu hình)

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Admin/Ops cấu hình; QL CN xem readonly; Lễ tân/Y tá không thấy tab
Vào màn để quyết định gì?Bật module Phòng khám cho CN, đi qua 5 bước cấu hình + 1 bước kiểm tra sẵn sàng, đạt 100% rồi phát hành
Dữ liệu chínhbranch.features.clinic_enabled, clinic_module_publication, branch_technical_config, technical_category, service_clinical_classification
CTA chính / phụPrimary: "Phát hành" (chỉ mở khi kiểm tra sẵn sàng đạt 100%); Secondary: "Lưu nháp", "Tạm dừng" (nếu đang hoạt động)
Điều không được hiểu nhầmWizard hoàn tất ≠ đang hoạt động; phải bấm "Phát hành" + chọn effective_at

B2.2) Bố cục — Demo gắn vào UI hiện tại (Mở rộng)

text
/s/internal-settings/branch/{id}        [Trang chi nhánh — mở rộng tab thứ 4]

┌─────────────────────────────────────────────────────────────────────────┐
│ Header: CN Cao Lãnh                                  [Lưu]   [Hủy]      │
├──────────────────┬──────────────────────────────────────────────────────┤
│ BranchInfo       │ Tabs: [Bộ phận] [Kho] [Dịch vụ] [Phòng khám ★ NEW]   │
│ (KEEP — sidebar) ├──────────────────────────────────────────────────────┤
│                  │ >>>  KHU VỰC TAB MỚI "PHÒNG KHÁM"  <<<                │
│ Mã: CL           │                                                      │
│ Tỉnh: Đồng Tháp  │ ┌─ Trạng thái: [Đang cấu hình `setup_draft`]       ┐ │
│ Loại: Spa+PK     │ │                                                  │ │
│                  │ │ ┌── Trợ lý cấu hình phòng khám (6 bước) ────────┐ │ │
│ [Sửa]            │ │ │ ●━━●━━●━━○━━○━━○                                  │ │ │
│                  │ │ │ 1    2    3    4         5      6                 │ │ │
│                  │ │ │ Loại Giấy  Danh Phân     Phân   Kiểm tra          │ │ │
│                  │ │ │ PK   phép  mục  loại     quyền  sẵn sàng          │ │ │
│                  │ │ │            KT   DV ↔ KT                            │ │ │
│                  │ │ └────────────────────────────────────────────────────┘ │ │
│                  │ │                                                  │ │
│                  │ │ Bước hiện tại: 3 — Danh mục kỹ thuật            │ │
│                  │ │   (nội dung bước hiện tại)                       │ │
│                  │ │                                                  │ │
│                  │ │ [Quay lại]                  [Lưu nháp]   [Tiếp] │ │
│                  │ └──────────────────────────────────────────────────┘ │
└──────────────────┴──────────────────────────────────────────────────────┘

B2.3) Phân loại reuse + điểm update

Phân loạiFile hiện cóVị trí updateLý do vị trí
🔧 Mở rộnguser/pages/BranchDetail.tsxThêm tab thứ 4 sau tab "Dịch vụ"Khớp UX hiện tại 3 tabs; thêm tab Phòng khám đứng cuối logic vận hành

B2.4) Quy ước field/CTA mới (ref B0.4 — không lặp)

Field thay đổi ref dòng B0.4: branch.features.clinic_enabled, clinic_module_publication.status. CTA Phát hành chỉ mở khi readiness_snapshot đạt 100% R-01..R-10.

B2.5) Bộ lọc — N/A (cấu hình per CN, không có bộ lọc)

B2.6) Bảng nội dung chính — N/A (trợ lý cấu hình theo bước, không phải bảng dữ liệu)

B2.7) Quy ước tương tác

Tình huốngHành vi
Chế độ lưuLưu thủ công + Lưu nháp
Có thay đổi chưa lưuDấu (•) ở tiêu đề tab + chặn chuyển trang
Tìm kiếm/bộ lọcN/A
Reset dây chuyềnĐổi loại PK ở bước 1 → reset bước 3 (KT) + bước 4 (DV ↔ KT) với hộp thoại xác nhận
Cập nhật bất đồng bộTheo lối thận trọng — chờ phản hồi trước khi sang bước tiếp theo
Tác vụ chạy lâuKiểm tra sẵn sàng (R-01..R-10) hiện lớp chờ phủ toàn bước

B2.8) Ma trận phân quyền — ref B6 ma trận canonical mục clinic_module

B2.9) Ma trận trạng thái — ref B0.5 dòng SCR-04

B2.10) Phản hồi sau thao tác

Hành độngPhản hồi UICopy mẫu
Lưu nháp thành côngThông báo nhanh"Đã lưu nháp lúc 14:32"
Tiếp bước (validation đạt)Chuyển bước + cuộn lên đầu(không thông báo)
Tiếp bước (validation lỗi)Lỗi tại field + banner top"Vui lòng hoàn thành các mục bắt buộc trước khi tiếp tục"
Phát hành thành côngThông báo nhanh + chuyển sang trạng thái mới"Đã phát hành module Phòng khám CN Cao Lãnh, áp dụng từ 02/05/2026 09:00"
Tạm dừngHộp thoại xác nhận"Tạm dừng module Phòng khám CN Cao Lãnh? Bệnh án mới sẽ không tạo được. Bệnh án cũ vẫn xem được."

B2.11) Mapping UI theo vòng đời (LIFECYCLE-001)

Trạng tháiCTA hiển thịCTA ẩn/khóaField sửa đượcBadge
Tắt (off)"Bật module"(chưa cấu hình)"Tắt" (xám)
Đang cấu hình (setup_draft)"Lưu nháp", "Tiếp", "Quay lại""Phát hành" bị khóa5 bước cấu hình của trợ lý"Đang cấu hình" (vàng)
Đã sẵn sàng (ready_to_publish)"Phát hành", "Sửa cấu hình"Chỉ đọc trong trợ lý cấu hình"Đã sẵn sàng" (xanh nhạt)
Đã lập lịch (scheduled)"Hủy lập lịch""Phát hành" ẩnReadonly"Đã lập lịch DD/MM/YYYY HH:mm" (xanh)
Đang hoạt động (live)"Tạm dừng", "Sửa cấu hình""Phát hành" ẩnChỉ đọc; chỉ Admin/Ops sửa được trong tab con cấu hình"Đang hoạt động" (xanh đậm)
Đã tạm dừng (paused)"Tiếp tục" (→ live), "Sửa cấu hình" (→ setup_draft/ready_to_publish qua re-check)"Phát hành" ẩnChỉ đọc; Admin/Ops sửa được"Đã tạm dừng" (đỏ nhạt) + lý do

SCR-04a: Bước 1 — Loại phòng khám

Mục tiêu: Admin/Ops chọn loại phòng khám của chi nhánh để hệ thống biết cần bật BA Da liễu, BA Thẩm mỹ hay cả hai.

text
[Bước 1/6 — Loại phòng khám]                              CN Cao Lãnh

Chi nhánh này có vận hành phòng khám nào?

( ) Chỉ Da liễu
    Dùng Bệnh án Da liễu, sổ khám bệnh, phiếu dị ứng, đơn thuốc.

( ) Chỉ Phẫu thuật Thẩm mỹ
    Dùng Bệnh án Thẩm mỹ, sổ khám bệnh, sổ thủ thuật, phiếu theo dõi điều trị.

(●) Cả Da liễu + Phẫu thuật Thẩm mỹ
    Dùng cả 2 loại bệnh án. Dịch vụ sẽ được phân loại theo từng kỹ thuật.

Header in phiếu:
[PHÒNG KHÁM CHUYÊN KHOA DA LIỄU DIVA CAO LÃNH              ]

Người phụ trách y khoa:
[BS Trần Mỹ Hương ▼]     Số điện thoại hỗ trợ: [0909 000 111]

[Quay lại]                                      [Lưu nháp] [Tiếp]
FieldValidationHành vi
Loại phòng khámBắt buộc 1 lựa chọnĐổi loại sau khi đã cấu hình bước 3/4 phải confirm reset dây chuyền
Header in phiếuBắt buộc, tối đa 200 ký tựDùng cho PDF/in bộ hồ sơ
Người phụ trách y khoaBắt buộc trước phát hànhDùng trong kiểm tra sẵn sàng R-09
SĐT hỗ trợ10 chữ số, bắt đầu bằng 0Hiện trong runbook nội bộ, không in lên BA nếu Legal không duyệt

Copy lỗi: "Vui lòng chọn loại phòng khám trước khi tiếp tục."

SCR-04b: Bước 2 — Giấy phép và thông tin pháp lý

Mục tiêu: nhập giấy phép phòng khám để in đúng header, kiểm soát hạn giấy phép và chặn phát hành khi thiếu artifact pháp lý.

text
[Bước 2/6 — Giấy phép phòng khám]                         CN Cao Lãnh

Số giấy phép:       [123/SYT-DT                                      ] *
Cơ quan cấp:        [Sở Y tế Đồng Tháp                               ] *
Ngày cấp:           [15/02/2024]       Ngày hết hạn: [15/02/2029] *
Địa chỉ hành nghề:  [12 Lê Lợi, Phường 1, TP. Cao Lãnh               ] *

File giấy phép:
┌─────────────────────────────────────────────────────────────────────┐
│ Kéo-thả file PDF/JPG/PNG hoặc [Chọn file]                           │
│ Đã tải: giay-phep-cao-lanh.pdf · 1.4MB · ✓                          │
└─────────────────────────────────────────────────────────────────────┘

☐ Legal đã xác nhận mẫu giấy + lưu trữ + scan reference cho pilot
☐ QL CN đã kiểm tra máy in, máy scan và tài khoản tải file

[Quay lại]                                      [Lưu nháp] [Tiếp]
FieldValidationHành vi
Số giấy phépBắt buộc, không trùng trong CN đang hoạt độngTrùng thì hiển thị "Số giấy phép đã tồn tại ở chi nhánh khác"
Ngày hết hạnPhải lớn hơn ngày hiện tại khi phát hànhHết hạn trong 30 ngày → cảnh báo vàng
File giấy phépPDF/JPG/PNG, tối đa 20MBThiếu file → R-02 không đạt
Legal xác nhậnCheckbox bắt buộc trước go-live, chưa bắt buộc để lưu nhápDùng cho R-10

Trạng thái đặc biệt: giấy phép hết hạn sau khi CN đã live không tự pause module. Trang điều phối SCR-16 phải báo "Giấy phép hết hạn" và yêu cầu Ops xử lý.

SCR-04c: Bước 3 — Danh mục kỹ thuật

Mục tiêu: chọn Danh mục kỹ thuật (technical_category) được phép dùng tại chi nhánh, gắn mức rủi ro dị ứng và làm nguồn cho bước phân loại dịch vụ — kỹ thuật.

text
[Bước 3/6 — Danh mục kỹ thuật]                           CN Cao Lãnh

[Tìm kỹ thuật...] [Loại PK: Tất cả ▼] [Rủi ro dị ứng: Tất cả ▼]
[+ Thêm kỹ thuật nội bộ] [Import từ danh mục master]

┌────┬──────────────────────────┬──────────┬──────────────┬─────────────┬──────────────┐
│ #  │ Kỹ thuật                 │ Loại PK  │ Rủi ro dị ứng │ Sử dụng tại │ Sẵn sàng     │
│    │                          │          │               │ CN          │ phát hành    │
├────┼──────────────────────────┼──────────┼──────────────┼─────────────┼──────────────┤
│ 1  │ Áp lạnh nitơ             │ Da liễu  │ Thấp          │ Đang dùng   │ ✓            │
│ 2  │ Tiêm filler              │ Thẩm mỹ  │ Cao           │ Đang dùng   │ ✓            │
│ 3  │ Laser CO2 Fractional     │ Da liễu  │ Chưa phân loại│ Đang dùng   │ ⚠ Chặn R-04  │
│ 4  │ Nâng mũi cấu trúc        │ Thẩm mỹ  │ Cao           │ Đang dùng   │ ✓            │
│ 5  │ Tiêm meso (cũ)           │ Da liễu  │ Trung bình    │ Tạm ngưng   │ — (không dùng)│
└────┴──────────────────────────┴──────────┴──────────────┴─────────────┴──────────────┘

⚠ Còn 1 kỹ thuật đang dùng nhưng chưa phân loại rủi ro dị ứng. Bước kiểm
  tra sẵn sàng R-04 sẽ không đạt cho tới khi Medical Lead phân loại.

[Quay lại]                                      [Lưu nháp] [Tiếp]
FieldValidationHành vi
Tên kỹ thuậtBắt buộc, không trùng trong cùng CNCho phép cùng tên ở CN khác nếu master khác
Loại PKDL, TM, bothLọc theo loại phòng khám ở bước 1
allergy_risk_levelunknown/low/medium/highunknown chặn phát hành và chặn hoàn thành BA nếu KT được dùng
Trạng thái sử dụngĐang dùng / Tạm ngưngTạm ngưng không hiện ở bước 4

Quy tắc import: import không ghi đè kỹ thuật đã sửa tại CN. Nếu trùng tên, UI hiện hộp thoại so sánh "Giữ bản CN" / "Cập nhật từ master".

SCR-04d: Phân loại dịch vụ — kỹ thuật

B2.2) Wireframe

text
[Bước 4/6 — Phân loại dịch vụ — kỹ thuật]                  CN Cao Lãnh

Hiện trạng: 50 dịch vụ đang bán   ✓ 45 đã phân loại   ⚠ 5 chưa phân loại

[Tìm kiếm dịch vụ...]   [Lọc: Tất cả ▼]   [Lọc trạng thái: Tất cả ▼]

┌────┬──────────────────────────────┬─────────────────────────┬──────────────┐
│ #  │ Dịch vụ                      │ Phân loại                │ Kỹ thuật     │
├────┼──────────────────────────────┼─────────────────────────┼──────────────┤
│ 1  │ Liệu trình trị mụn 5 buổi    │ ◉ Cần BA   ○ Không cần   │ [Áp lạnh ▼]  │
│    │ (3.500.000đ)                 │   ○ Chưa phân loại       │              │
├────┼──────────────────────────────┼─────────────────────────┼──────────────┤
│ 2  │ Filler Hyaluronic 1ml        │ ◉ Cần BA                 │ [Tiêm filler]│
│    │ (4.200.000đ)                 │                          │              │
├────┼──────────────────────────────┼─────────────────────────┼──────────────┤
│ 3  │ Tư vấn miễn phí              │ ○ Cần BA  ◉ Không cần BA │ —            │
│    │ (0đ)                         │                          │              │
├────┼──────────────────────────────┼─────────────────────────┼──────────────┤
│ 4  │ Laser CO2 mới                │ ○ Cần BA  ○ Không cần    │ —            │
│    │ (2.800.000đ)                 │ ◉ Chưa phân loại         │ ⚠ Bắt phân  │
│    │                              │                          │   loại trước│
└────┴──────────────────────────────┴─────────────────────────┴──────────────┘

⚠ Còn 5 dịch vụ chưa phân loại. Bắt buộc phân loại 100% trước khi tiếp.

[Quay lại]                           [Lưu nháp]   [Tiếp →] (bị khóa)

B2.4) Quy ước field — ref B0.4 dòng service_clinical_classification.classification_status

B2.7) Quy ước tương tác

Tình huốngHành vi
Đổi phân loại 1 dòngTự lưu ngay trên dòng sau 500ms
Còn unclassified"Tiếp" bị khóa + banner đỏ
Đổi loại PK ở bước 1Hộp thoại xác nhận "Đổi loại PK sẽ xóa phân loại hiện có. Tiếp tục?"

SCR-04e: Bước 5 — Phân quyền phòng khám

Mục tiêu: Admin/Ops cấp quyền vận hành tối thiểu cho chi nhánh trước khi phát hành. Vai trò chỉ là mẫu seed; quyền thực tế đọc từ Permission v2.

text
[Bước 5/6 — Phân quyền phòng khám]                         CN Cao Lãnh

Nhóm vận hành bắt buộc:
┌──────────────────┬──────────────────────────────┬──────────────┬───────────┐
│ Nhóm             │ Nhân sự                       │ Quyền chính  │ Trạng thái │
├──────────────────┼──────────────────────────────┼──────────────┼───────────┤
│ Bác sĩ           │ BS Trần Mỹ Hương, BS Phát     │ Xem/sửa tầng 3│ Đủ        │
│ Y tá             │ Y tá Hà                       │ Hành chính + scan│ Đủ     │
│ QL chi nhánh     │ Chị Tâm                       │ Sổ, chốt ngày│ Đủ        │
│ Lễ tân           │ Mai                           │ Tạo lượt khám│ Đủ        │
│ Ops hỗ trợ D0    │ Chưa chọn                     │ Điều phối    │ Thiếu     │
└──────────────────┴──────────────────────────────┴──────────────┴───────────┘

Quyền nhạy cảm:
☑ Bác sĩ cùng CN được `clinical_record.view_medical_detail`
☐ QL CN được xem tầng 3 (không khuyến nghị Day-1)
☑ Y tá được `upload_scan` + `edit_admin_shared`
☑ Sale chỉ dùng Trang xem an toàn (Sale), không xem tầng 3

[Thêm nhân sự] [Xem ma trận quyền]                 [Lưu nháp] [Tiếp]
NhómQuyền tối thiểuCảnh báo nếu thiếu
Bác sĩdoctor_workbench.access, clinical_record.view_summary, clinical_record.view_medical_detail, edit_medical_form, print"Chưa có bác sĩ được phân quyền. Không thể phát hành."
Y táclinical_record.view_summary, edit_admin_shared, upload_scan"Chưa có người tải bản scan đã ký."
QL CNclinical_record.export_visit_log, clinic_daily_close.close_branch_day, clinic_ops.view_branch_dashboard"Chưa có người chốt ngày phòng khám."
Lễ tânclinical_record.view_summary, customer_clinical_intake.open_session"Chưa có người mở phiếu khách tự khai."
Opsclinic_ops.view_all_dashboard, clinic_module.configure"Chưa có người phụ trách hỗ trợ D0."

Quy tắc UI: không khóa menu theo tên vai trò. FE chỉ dựa vào module_permission_actionglobalStore.hasPermission(...); BE vẫn kiểm tra lại.

SCR-04f: Bước 6 — Kiểm tra sẵn sàng và phát hành

Mục tiêu: chạy 10 kiểm tra sẵn sàng, cho Admin xem trước tác động khi áp dụng, rồi phát hành module theo effective_at.

text
[Bước 6/6 — Kiểm tra sẵn sàng]                         CN Cao Lãnh

Tiến độ: 8/10 đạt

┌────┬─────────────────────────────────────────────┬──────────┬──────────────┐
│ Mã │ Kiểm tra                                    │ Kết quả  │ Thao tác      │
├────┼─────────────────────────────────────────────┼──────────┼──────────────┤
│R-01│ Đã chọn loại phòng khám                     │ Đạt      │ —            │
│R-02│ Giấy phép còn hạn + file đã tải             │ Đạt      │ Xem file     │
│R-03│ Danh mục kỹ thuật đủ cho CN                 │ Đạt      │ Mở bước 3    │
│R-04│ Không còn kỹ thuật allergy `unknown`        │ Không đạt│ Mở bước 3    │
│R-05│ 100% dịch vụ đang bán đã phân loại          │ Không đạt│ Mở bước 4    │
│R-06│ Phân quyền BS/Y tá/QL CN đủ                 │ Đạt      │ Mở bước 5    │
│R-07│ In thử PDF thành công                       │ Đạt      │ Xem PDF      │
│R-08│ BA demo tạo/in/scan trên staging đạt        │ Đạt      │ Xem log      │
│R-09│ Đã chọn người phụ trách hỗ trợ D0           │ Đạt      │ —            │
│R-10│ Legal/SYT/máy scan/máy in/tài khoản upload  │ Đạt      │ Xem tài liệu │
└────┴─────────────────────────────────────────────┴──────────┴──────────────┘

⛔ Chưa thể phát hành. Còn 2 kiểm tra chưa đạt.

[Chạy lại kiểm tra]                         [Phát hành] (bị khóa)

Hộp thoại phát hành khi 10/10 đạt

text
[Phát hành module Phòng khám — CN Cao Lãnh]                 [×]

Xem trước tác động khi áp dụng:
• 50 dịch vụ đang bán: 45 cần BA, 5 không cần BA
• 12 người dùng sẽ thấy menu/màn Phòng khám
• 2 bác sĩ được xem tầng 3 tại CN Cao Lãnh
• 7 thông báo phòng khám sẽ được bật
• Giờ chốt ngày: 20:00 Asia/Ho_Chi_Minh

Áp dụng từ:
(●) Phát hành ngay
( ) Lập lịch: [02/05/2026 09:00]

Lý do phát hành:
[Pilot Cao Lãnh theo kế hoạch đã được Legal/Ops xác nhận              ]

[Hủy]                                      [Xác nhận phát hành]
Trạng thái kiểm traUIKết quả
10/10 đạtCTA "Phát hành" mởclinic_module_publication.status='ready_to_publish'
Có R-xx không đạtCTA khóaKhông tạo lịch phát hành
Phát hành ngayConfirm → status='live' nếu effective_at<=now()UI clinical mở ngay sau refetch quyền
Lập lịchstatus='scheduled'UI clinical chưa mở trước effective_at
Tạm dừng sau liveBắt lý dostatus='paused', BA cũ readonly, không tạo BA mới

SCR-05: Tạo lượt khám

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Lễ tân, bác sĩ, y tá được quyền tạo lượt khám
Vào màn để quyết định gì?Tạo appointment/lượt khám đúng nghĩa cho khách có đơn, có lịch hoặc walk-in
Dữ liệu chínhappointment, customer_id, branch_id, doctor_id, order_item_id, form_type, clinical_record
CTA chính / phụPrimary: "Lưu lượt khám"; Secondary: "Tạo khách mới", "Gắn đơn sau", "Mở phiếu khách tự khai"
Điều không được hiểu nhầmTạo lượt khám không đồng nghĩa đã có Bệnh án lượt khám; bệnh án sinh theo dịch vụ cần BA và form_type. customer_id luôn bắt buộc; nếu KH walk-in chưa có hồ sơ, lễ tân tạo KH mới inline trước khi lưu lượt khám

B2.2) Popup

text
[Tạo lượt khám]                                                [×]

CN: [Cao Lãnh ▼]                         Ngày giờ: [02/05/2026 14:30]
Bác sĩ phụ trách: [BS Trần Mỹ Hương ▼]

Khách hàng (bắt buộc):
(●) Khách đã có hồ sơ        [Lê Thị Hương · 0909 123 456 ▼]
( ) Khách walk-in — tạo mới  [+ Tạo khách mới ngay]
       (mở popup tạo KH inline; sau khi lưu sẽ tự gắn `customer_id`)

Dịch vụ liên quan:
☑ Liệu trình trị mụn 5 buổi       Badge: Cần BA      Loại BA: [Da liễu ▼]
☐ Tư vấn miễn phí                 Badge: Không cần BA

Đơn hàng:
( ) Gắn với đơn hiện có: [Chọn đơn/order item ▼]
(●) Chưa có đơn, tạo sau khi bác sĩ khám

Ghi chú quầy:
[Khách đến trực tiếp, mong muốn kiểm tra mụn viêm trước khi mua liệu trình]

[Hủy]                                  [Lưu lượt khám]

B2.3) Validation và kết quả

Trường hợpValidationKết quả
Khách đã có hồ sơBắt buộc chọn customer_idTạo appointment.customer_id
Khách walk-in chưa có hồ sơBuộc tạo KH mới inline trước khi lưu (customer_id không được rỗng)Sau khi tạo KH xong, popup quay lại trạng thái đã chọn customer_id mới
Chưa có đơnCho phép order_item_id=NULLSau khám có CTA "Tạo đơn từ lượt khám này"
Dịch vụ cần BABắt buộc chọn form_typeTạo việc need_record cho Bàn việc bác sĩ
Dịch vụ unclassifiedChặn lưuCopy: "Dịch vụ chưa phân loại. Vui lòng phân loại trước khi tạo lượt khám."

B2.4) Phản hồi sau thao tác

Hành độngPhản hồi
Lưu thành công"Đã tạo lượt khám cho khách {customer_name}" + mở Bàn việc bác sĩ nếu người dùng là BS
Bỏ qua tạo KH inlineNút "Lưu lượt khám" ở trạng thái khoá + tooltip "Vui lòng chọn hoặc tạo khách hàng trước"
Không có quyềnCTA ẩn; route/action trả "Bạn không có quyền tạo lượt khám"

SCR-06: Form BA Da liễu

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Bác sĩ Da liễu cùng CN với KH
Vào màn để quyết định gì?Khám và chốt chẩn đoán ICD-10 + y lệnh + phiếu biểu mẫu kèm theo
Dữ liệu chínhclinical_record (form_type='DL'), clinical_form_instance (form_template DL), ICD-10
CTA chính / phụPrimary: "Hoàn thành" (chỉ mở khi đầy đủ + allergy đạt); Secondary: "In bộ hồ sơ" (sau hoàn thành), "Lưu nháp" (auto 30s)
Điều không được hiểu nhầm"Hoàn thành" chỉ chuyển trạng thái completed — chưa in, chưa scan

B2.2) Wireframe — Demo độc lập (Xây mới)

text
/e/service-order/clinical-records/{id}/ba-dl   [Bệnh án Da liễu]

Header: KH Lê Thị Hương · Mã BA: DVA-DL-CL-2026-00147
        BS Trần Mỹ Hương · CN Cao Lãnh · Lượt khám 02/05/2026 14:30

Trạng thái: [Bản nháp]   Đã lưu nháp lúc 14:32

┌─ 1. Hành chính (KEEP — đã có thông tin từ appointment) ──────────────┐
│ Tuổi: 28 · Giới tính: Nữ · Nghề nghiệp: [Văn phòng]                 │
│ Địa chỉ: [Số 12, Đường Lê Lợi, P.1, TP. Cao Lãnh]                   │
└─────────────────────────────────────────────────────────────────────┘

┌─ 2. Tiền sử ─────────────────────────────────────────────────────── [▼]┐
│ Tiền sử dị ứng: ◉ Không đổi (reuse phiếu trước)  ○ Điền mới          │
│ Tiền sử bệnh nội khoa: [Đái tháo đường týp 2 từ 2022]                │
│ Tiền sử dị ứng thuốc: [Penicillin (nổi mẩn 2020)]                   │
│ Thuốc đang dùng: [Metformin 500mg, 2 viên/ngày]                     │
└─────────────────────────────────────────────────────────────────────┘

┌─ 3. Khám hiện tại ──────────────────────────────────────────────── [▼]┐
│ Lý do đến: [Mụn trứng cá tái phát 3 tháng]                          │
│ Tổn thương cơ năng: [Ngứa, đỏ vùng má 2 bên]                        │
│ Khám da liễu chi tiết:                                              │
│   - Vị trí: [Má, trán, cằm]                                         │
│   - Loại tổn thương: ☑ Mụn viêm  ☑ Mụn đầu đen  ☐ Sẹo              │
│   - Mức độ: ◉ Trung bình  ○ Nhẹ  ○ Nặng                            │
│ Khám toàn thân: [Sinh hiệu ổn, không hạch]                          │
└─────────────────────────────────────────────────────────────────────┘

┌─ 4. Chẩn đoán ──────────────────────────────────────────────────── [▼]┐
│ Chẩn đoán chính (ICD-10) ★ Bắt buộc:                                │
│   [L70.0 — Mụn trứng cá thông thường              ▼]                │
│ Mã giấy lưu trữ (nếu khác): [—]                                     │
│ Chẩn đoán phụ (0-5 mã):                                             │
│   [L73.2 — Viêm da quanh miệng]  [×]                                │
│   [+ Thêm chẩn đoán phụ]                                            │
│ Mô tả chi tiết: [Mụn trứng cá thông thường mức độ trung bình...]    │
└─────────────────────────────────────────────────────────────────────┘

┌─ 5. Y lệnh ──────────────────────────────────────────────────────── [▼]┐
│ Liệu trình điều trị: [Áp lạnh nitơ + thuốc bôi adapalene 0.1%]      │
│ Lời dặn: [Tránh nắng, không nặn mụn, tái khám sau 4 tuần]           │
│ [+ Tạo đơn thuốc] [+ Phiếu cam đoan] [+ Phiếu cam kết]              │
└─────────────────────────────────────────────────────────────────────┘

┌─ 6. Theo dõi ─────────────────────────────────────────────────── [▼]┐
│ Lịch tái khám: [30/05/2026]                                         │
│ Ghi chú BS: [Theo dõi đáp ứng sau 4 tuần áp lạnh]                   │
└─────────────────────────────────────────────────────────────────────┘

⚠ An toàn dị ứng: KT "Áp lạnh nitơ" có rủi ro thấp — cho phép hoàn thành.

[Hủy]                       [Lưu nháp]   [Hoàn thành]

B2.4) Quy ước field — ref B0.4: clinical_record.diagnosis_codes, clinical_form_instance.form_data

B2.7) Quy ước tương tác

Tình huốngHành vi
Autosave 30sFE debounce 30s sau khi BS dừng gõ → mutation; show "Đã lưu nháp lúc HH:mm"
Mở/đóng phầnBấm tiêu đề phần → mở/đóng phần đó; mặc định mở các phần đã có dữ liệu
ICD-10 dropdownSearchable, fetch dần (paginated 50/page); typeahead 200ms debounce
Conflict (BS khác cùng record)Hộp thoại "Có thay đổi từ thiết bị khác. Giữ thay đổi của bạn / Lấy bản mới nhất"
Mất mạngThông báo nhanh "Mất kết nối. Đã lưu local. Đang thử lại..." + auto-retry

B2.10) Phản hồi sau thao tác

Hành độngPhản hồi
Lưu nháp (auto)Thông báo nhanh nhỏ "Đã lưu nháp lúc HH:mm"
Hoàn thành (đạt allergy)Thông báo nhanh "Đã hoàn thành bệnh án {DVA-DL-CL-2026-00147}" + chuyển sang chế độ readonly
Hoàn thành (allergy unknown/high block)Banner đỏ "Bắt buộc điền Phiếu tiền sử dị ứng trước thủ thuật xâm lấn" + CTA "Mở phiếu dị ứng"
Thiếu ICD chính-10Lỗi tại field + focus field "Chẩn đoán chính" + "Vui lòng chọn ít nhất 1 mã ICD-10 chính"

B2.11) Mapping UI theo LIFECYCLE-002

Trạng tháiCTA hiển thịCTA ẩn/khóaField sửa đượcBadge
Bản nhápLưu nháp, Hoàn thànhIn, Tải bản scan đã kýTất cả"Bản nháp" (vàng)
Đã hoàn thànhIn bộ hồ sơ, Sửa (nếu có quyền edit_medical_form)Hoàn thànhReadonly (chỉ sửa qua "Sửa" → tạo bản v2)"Đã hoàn thành" (xanh)
Đã inTải bản scan đã ký, In lạiSửa (chỉ qua tạo bản v2)Readonly"Đã in" (xanh đậm)
Đã ký + scan đủXemIn bản v2 (chỉ qua luồng đặc biệt)Readonly"Đã ký + scan đủ" (xanh đậm + ✓)
Bản thay thếXemReadonly"Bản thay thế" (xám)
Đã lưu trữXem (chỉ Admin)Readonly"Đã lưu trữ" (xám đậm)

SCR-07: Form BA Thẩm mỹ (4 phân hệ)

B2.2) Wireframe

text
/e/service-order/clinical-records/{id}/ba-tm   [Bệnh án Thẩm mỹ]

Header: KH Nguyễn Thị Lan · Mã BA: DVA-TM-TB2-2026-00089
        BS Phạm Hoàng Long · CN Tân Bình II · 02/05/2026 09:00

Dịch vụ: Nâng mũi cấu trúc (15.000.000đ) → Auto-hiện section Mũi

┌─ 1. Hành chính + Tiền sử (KEEP) ─────────────────────────────── [▼]┐
│ ... (như BA DL)                                                    │
└────────────────────────────────────────────────────────────────────┘

┌─ 2. Phân hệ MŨI (auto-hiện) ─────────────────────────────────── [▼]┐
│ Đo đạc:                                                            │
│   - Chiều cao sống mũi: [3.2 mm]                                   │
│   - Độ rộng cánh mũi: [38 mm]                                      │
│   - Góc mũi-môi: [95°]                                             │
│   - Tỉ lệ chiều dài/rộng: [1:0.7]                                  │
│ Tình trạng hiện tại: [Sống mũi thấp, đầu mũi bè]                   │
│ Phân tích thẩm mỹ:                                                 │
│   ☑ Mũi tẹt  ☑ Đầu mũi bè  ☐ Lệch sống  ☐ Cánh mũi rộng           │
└────────────────────────────────────────────────────────────────────┘

┌─ 3. Phân hệ MẮT (chưa bật) [+ Bật phân hệ Mắt]                    │
│ ⚠ Phân hệ này không được chọn từ dịch vụ POS. Bật chỉ khi cần.    │
└────────────────────────────────────────────────────────────────────┘

┌─ 4. Phân hệ MÔI (chưa bật) [+ Bật phân hệ Môi]                    │
└────────────────────────────────────────────────────────────────────┘

┌─ 5. Phân hệ KHÁC (chưa bật) [+ Bật phân hệ Khác]                  │
└────────────────────────────────────────────────────────────────────┘

┌─ 6. Chẩn đoán + Y lệnh + Theo dõi (như BA DL) ─────────────────────┐
│ ICD-10 chính ★: [Q67.4 — Bất thường hình thái mũi bẩm sinh ▼]      │
│ ...                                                                │
└────────────────────────────────────────────────────────────────────┘

⚠ An toàn dị ứng: KT "Phẫu thuật nâng mũi" rủi ro CAO — bắt buộc Phiếu dị ứng.

[Hủy]   [Lưu nháp]   [Hoàn thành] (bị khóa cho tới khi có Phiếu dị ứng)

B2.7) auto-hiện section theo dịch vụ; bật thêm có warning + log ghi chú.

SCR-08: Năm biểu mẫu dùng chung / đi kèm

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Bác sĩ nhập nội dung y khoa; y tá hỗ trợ phần hành chính/scan; KH ký trên bản giấy sau khi in
Vào màn để quyết định gì?Điền các Phiếu biểu mẫu đi kèm trước khi in bộ hồ sơ
Dữ liệu chínhform_template, clinical_form_instance, prescription, prescription_item, allergy_check_policy
CTA chính / phụPrimary: "Lưu phiếu"; Secondary: "Thêm đơn thuốc", "Mở phiếu dị ứng", "Xem trước bản in"
Điều không được hiểu nhầmPhiếu theo dõi điều trị chỉ bắt buộc cho case TM có điều trị nhiều lần; không bắt buộc cho mọi BA

B2.2) Bố cục tab biểu mẫu

text
[Biểu mẫu đi kèm — DVA-TM-TB2-2026-00089]                    [×]

Tabs:
[Cam đoan] [Cam kết] [Đơn thuốc] [Dị ứng] [Theo dõi điều trị]

┌─ Cam đoan thực hiện dịch vụ ───────────────────────────────────────┐
│ Khách hàng: Nguyễn Thị Lan · Dịch vụ: Nâng mũi cấu trúc            │
│                                                                     │
│ ☑ Tôi đã được bác sĩ tư vấn về lợi ích, nguy cơ và chăm sóc sau thủ thuật.
│ ☑ Tôi đồng ý thực hiện dịch vụ theo tư vấn.
│                                                                     │
│ Câu xác nhận khách tự gõ trên hệ thống (≥20 ký tự, phải chứa "đồng │
│ ý" hoặc "thực hiện"; FE chặn dán/copy-paste để buộc gõ tay):        │
│ [Tôi đã hiểu nội dung tư vấn và đồng ý thực hiện dịch vụ này.      ] *
│                                                                     │
│ Người làm chứng: [Y tá Hà ▼]                                        │
└─────────────────────────────────────────────────────────────────────┘

[Lưu phiếu]                         [Xem trước bản in] [Đóng]

Rule câu xác nhận tự gõ (DEC-021):

Kiểm traQuy ước
Độ dài≥ 20 ký tự (sau trim)
Từ khóaPhải chứa "đồng ý" hoặc "thực hiện" (case-insensitive)
Chống dánFE bắt sự kiện paste ở textarea này → ngăn dán + thông báo nhanh "Vui lòng để khách tự gõ trên màn hình"
Tốc độ gõFE log nhịp phím; nếu ≥10 ký tự liên tiếp xuất hiện trong <50ms → cảnh báo nhân viên + yêu cầu khách gõ lại
ServerValidate lại độ dài + từ khóa; lưu kèm typed_at, typed_duration_ms để audit

B2.3) Danh sách phiếu và rule bắt buộc

Phiếu biểu mẫuKhi nào hiệnKhi nào bắt buộcField chínhIn trong bộ hồ sơ
Cam đoanDịch vụ thủ thuật/xâm lấnKhi technical_category.requires_consent=trueCheckbox đồng ý + câu xác nhận tự gõ
Cam kếtDịch vụ có cam kết chăm sóc/hậu phẫuTheo cấu hình dịch vụ/kỹ thuậtNội dung cam kết, người tư vấn, ghi chú
Đơn thuốcBS kê thuốcKhi có ít nhất 1 thuốcTên thuốc, hàm lượng, số lượng, cách dùng, lời dặn
Phiếu tiền sử dị ứngLần đầu hoặc KT rủi ro medium/high/unknownBắt buộc với KT xâm lấn/rủi ro caoDị ứng thuốc/thức ăn/vật liệu, mức độ, xử trí
Phiếu theo dõi điều trịCase TM nhiều lần hoặc hậu phẫuBắt buộc khi form_type='TM' và kỹ thuật yêu cầu theo dõiNgày theo dõi, diễn biến, xử trí, hẹn tái khámCó nếu phát sinh

B2.4) Đơn thuốc

text
[Đơn thuốc]

Chẩn đoán: L70.0 — Mụn trứng cá thông thường

┌────┬────────────────────┬──────────┬──────────┬───────────────┬─────────┐
│ #  │ Thuốc              │ Hàm lượng│ Số lượng │ Cách dùng      │ Xóa     │
├────┼────────────────────┼──────────┼──────────┼───────────────┼─────────┤
│ 1  │ Doxycycline        │ 100mg    │ 14 viên  │ 1 viên/ngày sau ăn │ [×] │
│ 2  │ Adapalene gel      │ 0.1%     │ 1 tuýp   │ Bôi tối, tránh mắt │ [×] │
└────┴────────────────────┴──────────┴──────────┴───────────────┴─────────┘

[+ Thêm thuốc]     Lời dặn: [Tránh nắng, tái khám sau 4 tuần]

B2.5) Quy ước tương tác

Tình huốngHành vi
Mở phiếu từ BA DL/TMPopup giữ context record; lưu xong quay lại đúng section
Thiếu phiếu bắt buộcForm BA không cho "Hoàn thành"; banner có CTA mở phiếu thiếu
Phiếu đã inChuyển chỉ đọc; sửa sau in tạo bản v2 theo DEC-023
KH từ chối ký bản giấyChuyển sang SCR-10 tab "Biên bản từ chối"; không sửa nội dung phiếu đã hoàn thành
KH từ chối thủ thuật (DEC-024)Bấm "Khách từ chối thủ thuật" trong Cam đoan → mở hộp thoại: (1) chọn lý do từ chối; (2) ghi chú; (3) y tá làm chứng (dropdown nhân viên cùng CN); (4) hệ thống tự huỷ order_item của thủ thuật trong đơn (cần quyền order.update) và đánh dấu lượt khám là "Khám tư vấn — không thực hiện thủ thuật"; ghi sổ khám với cột "Kết quả: Khách từ chối thủ thuật"; KHÔNG tạo Bệnh án thủ thuật, vẫn giữ Bệnh án lượt khám DL nếu đã có
Y tá không có quyền tầng 3Chỉ sửa phần hành chính/shared được cấp; không thấy chẩn đoán/ghi chú BS

B2.6) Copy lỗi

LỗiCopy
Thiếu câu xác nhận"Vui lòng nhập câu xác nhận trước khi lưu phiếu cam đoan."
Đơn thuốc thiếu cách dùng"Vui lòng nhập cách dùng cho thuốc {medicine_name}."
Phiếu dị ứng chưa đủ"Vui lòng hoàn thành Phiếu tiền sử dị ứng trước khi hoàn thành bệnh án."
Không có quyền sửa"Bạn không có quyền sửa phiếu này. Vui lòng liên hệ bác sĩ phụ trách."

SCR-09: Xem trước PDF + In bộ hồ sơ

text
[Xem trước bộ hồ sơ — DVA-DL-CL-2026-00147]                      [×]

┌──────────────────────────────────────────────────────────────────┐
│ ┌─ Trang 1/8: Bệnh án Da liễu ─────────────────────────────────┐ │
│ │ PHÒNG KHÁM DA LIỄU DIVA CAO LÃNH                              │ │
│ │ Giấy phép số: 123/SYT-DT     STT: DVA-CL-00147/2026          │ │
│ │ Mã BA: DVA-DL-CL-2026-00147                                  │ │
│ │                                                              │ │
│ │ KH: Lê Thị Hương · 28 tuổi · Nữ                              │ │
│ │ ...                                                          │ │
│ └─────────────────────────────────────────────────────────────┘  │
│                                                                  │
│ Bộ hồ sơ gồm: BA DL (3 trang) + Cam đoan (1 trang)               │
│              + Đơn thuốc (1 trang) + Phiếu dị ứng (1 trang)      │
│              + Phiếu theo dõi điều trị (2 trang)  = 8 trang                  │
└──────────────────────────────────────────────────────────────────┘

[← Trang trước]   Trang 1/8   [Trang sau →]

[Đóng]                    [Tải PDF]      [In bộ hồ sơ]

B2.10)

Hành độngPhản hồi
Bấm "In bộ hồ sơ"Hiện hộp thoại in của trình duyệt → render PDF; trạng thái Đã in; thông báo nhanh "Đã in bộ hồ sơ. Vui lòng ký tay và tải bản scan đã ký."
Tải PDFDownload file BA-DVA-DL-CL-2026-00147.pdf

SCR-10: Tải bản scan đã ký

text
[Tải bản scan đã ký — DVA-DL-CL-2026-00147]                      [×]

Trạng thái BA: [Đã in]   Sẽ chuyển sang [Đã ký + scan đủ] khi đủ checklist.

┌─ Checklist scan bắt buộc (theo case BA DL có thủ thuật + đơn thuốc) ──┐
│ ☐ BA chính (3 trang)                                                  │
│ ☐ Cam đoan (1 trang)                                                  │
│ ☐ Cam kết (1 trang)                                                   │
│ ☐ Đơn thuốc (1 trang)                                                 │
│ ☑ Phiếu tiền sử dị ứng — không bắt buộc cho ca này                   │
│ ☑ Phiếu theo dõi điều trị — không bắt buộc cho ca này                            │
│                                                                       │
│ Hoặc: ☐ Biên bản từ chối ký (KH từ chối) + Y tá làm chứng            │
└───────────────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────────────┐
│              ☁ Kéo-thả file scan vào đây                              │
│              hoặc [Chọn file] (PDF, JPG, PNG — tối đa 20MB/file)     │
└──────────────────────────────────────────────────────────────────────┘

Đã tải:
┌──────────────────────────────────────────────────┬──────────────────┐
│ ba-le-thi-huong-2026-05-02.pdf (1.2MB)           │ Map: [BA chính ▼] │
│ ✓ Đã tải                                          │ ✓ OK              │
├──────────────────────────────────────────────────┼──────────────────┤
│ cam-doan.pdf (350KB)                              │ Map: [Cam đoan ▼] │
│ ✓ Đã tải                                          │ ✓ OK              │
└──────────────────────────────────────────────────┴──────────────────┘

[Hủy]                                          [Lưu] (chuyển trạng thái)

B2.10)

Trường hợpPhản hồi
Đủ checklistThông báo nhanh "Đã ký + scan đủ — bệnh án hoàn tất pháp lý" + trạng thái chuyển
Thiếu checklistBanner "Còn thiếu: Cam kết, Đơn thuốc" + trạng thái vẫn Đã in
KH từ chối kýTab "Biên bản từ chối" + checkbox "Y tá làm chứng" + dropdown chọn y tá → trạng thái Đã ký + scan đủ với refusal_witnessed=true

SCR-11: Sổ khám bệnh

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?QL CN, Admin/Ops, bác sĩ được quyền xuất sổ
Vào màn để quyết định gì?Theo dõi lượt khám ngoại trú theo ngày/CN, phục vụ vận hành và thanh tra
Dữ liệu chínhclinical_record, clinical_profile, appointment, customer, doctor, diagnosis_codes
CTA chính / phụPrimary: "Xuất Excel"; Secondary: "Xem bệnh án", "Tải bản scan đã ký", "Mở bộ lọc"
Điều không được hiểu nhầmNgười không có view_medical_detail vẫn xem được sổ nhưng cột chẩn đoán hiển thị "—"

B2.2) Bố cục

text
/e/service-order/clinical-visit-log               [Sổ khám bệnh]

Header: Sổ khám bệnh · CN: Cao Lãnh · Ngày 02/05/2026

[Từ ngày 01/05/2026] [Đến ngày 02/05/2026] [CN: Cao Lãnh ▼]
[Loại BA: Tất cả ▼] [Trạng thái BA: Tất cả ▼] [Bác sĩ: Tất cả ▼]
[Tìm mã BA / tên KH / SĐT...]                         [Xuất Excel]

Tổng: 48 lượt khám · Đã ký+scan đủ: 36 · Cần scan: 8 · Bản nháp: 4

┌────┬──────────┬─────────────┬──────────────┬──────────┬──────────┬──────────┬────────────┐
│ #  │ Ngày khám│ STT sổ khám │ Khách hàng   │ Tuổi/Giới│ Bác sĩ   │ ICD chính│ Trạng thái │
├────┼──────────┼─────────────┼──────────────┼──────────┼──────────┼──────────┼────────────┤
│ 1  │02/05/26  │DVA-CL-00147 │Lê Thị Hương │28/Nữ     │BS Hương  │L70.0     │Đã ký+scan  │
│ 2  │02/05/26  │DVA-CL-00148 │Phạm Hà      │34/Nữ     │BS Hương  │—         │Cần scan    │
│ 3  │02/05/26  │DVA-CL-00149 │Khách walk-in│—         │BS Phát   │—         │Bản nháp    │
└────┴──────────┴─────────────┴──────────────┴──────────┴──────────┴──────────┴────────────┘

Row action: [Xem] [In lại] [Tải bản scan đã ký]

B2.3) Cột dữ liệu

CộtNguồnFormatQuyền
STTvisit_log_numberDVA-[CN]-[NNNNN]/[YYYY]view_summary
Ngày khámappointment.started_at hoặc clinical_record.created_atDD/MM/YYYY HH:mmview_summary
Khách hàngcustomer.full_name, phone masked nếu cầnTextview_summary
Bác sĩdoctor.full_nameTextview_summary
Chẩn đoán chínhdiagnosis_codes.primaryICD-10 + tên bệnhview_medical_detail; thiếu quyền → "—"
Trạng thái BAclinical_record.statusBadge canonicalview_summary
Scanscan_checklist"Đủ", "Thiếu {N}"view_summary

B2.4) Bộ lọc và export

Bộ lọcMặc địnhGhi chú
Khoảng ngàyHôm nayKhông quá 90 ngày/lần xuất
Chi nhánhCN hiện tại nếu branch scopeAdmin/Ops được chọn nhiều CN
Trạng thái BATất cảdraft/completed/printed/signed/...
Loại BATất cảDL/TM
Bác sĩTất cảLọc theo nhân sự thuộc CN
Từ khóaRỗngTìm mã BA, STT sổ, tên KH, SĐT

B2.5) Trạng thái và copy

Tình huốngCopy
Không có dữ liệu"Chưa có lượt khám trong khoảng thời gian này."
Không có quyền exportẨn nút "Xuất Excel"; route/API vẫn kiểm clinical_record.export_visit_log
Export thành công"Đã xuất Sổ khám bệnh {from}-{to}. Bấm để tải về."
Export có masking"Đã xuất {X} dòng. {Y} cột y tế nhạy cảm bị ẩn theo phân quyền."

SCR-12: Sổ thủ thuật

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?QL CN, Admin/Ops, bác sĩ/phụ trách thủ thuật
Vào màn để quyết định gì?Theo dõi ca thủ thuật/thẩm mỹ, kỹ thuật thực hiện, biến chứng và trạng thái scan
Dữ liệu chínhclinical_record, technical_category, procedure_log_number, reference_file, clinical_form_instance
CTA chính / phụPrimary: "Xuất Excel"; Secondary: "Xem bệnh án", "Xem phiếu theo dõi điều trị"
Điều không được hiểu nhầmSổ thủ thuật chỉ lấy record có kỹ thuật thủ thuật; không lấy tư vấn hoặc dịch vụ spa không cần BA

B2.2) Bố cục

text
/e/service-order/clinical-procedure-log             [Sổ thủ thuật]

[Từ ngày 01/05/2026] [Đến ngày 02/05/2026] [CN: Tân Bình II ▼]
[Kỹ thuật: Tất cả ▼] [Trạng thái scan: Tất cả ▼] [Bác sĩ: Tất cả ▼]
[Tìm STT thủ thuật / tên KH...]                         [Xuất Excel]

Tổng: 18 ca thủ thuật · Có biến chứng: 1 · Cần scan: 3

┌────┬──────────┬──────────────┬──────────────┬────────────┬──────────┬────────────┬──────────┐
│ #  │ Ngày     │ STT thủ thuật│ Khách hàng   │ Kỹ thuật   │ Bác sĩ   │ Theo dõi   │ Scan     │
├────┼──────────┼──────────────┼──────────────┼────────────┼──────────┼────────────┼──────────┤
│ 1  │02/05/26  │DVA-TB2-TT... │Nguyễn Lan   │Nâng mũi    │BS Long   │Có          │Đủ        │
│ 2  │02/05/26  │DVA-TB2-TT... │Mai Anh      │Tiêm filler │BS Long   │Không       │Thiếu 1   │
│ 3  │01/05/26  │DVA-TB2-TT... │Trần Hoa     │Cắt mí      │BS Phát   │Có biến chứng│Đủ       │
└────┴──────────┴──────────────┴──────────────┴────────────┴──────────┴────────────┴──────────┘

Row action: [Xem BA] [Xem theo dõi] [Tải bản scan đã ký]

B2.3) Cột dữ liệu

CộtNguồnFormatQuyền
STT thủ thuậtprocedure_log_numberDVA-[CN]-TT-[NNNNN]/[YYYY]view_summary
Kỹ thuậttechnical_category.nameTextview_summary
Vật tư chínhform TM / phiếu theo dõiText hoặc "—"view_medical_detail; thiếu quyền → "—"
Biến chứngphiếu theo dõi điều trị"Không", "Có", "Chờ cập nhật"view_medical_detail; thiếu quyền → chỉ thấy "Có/Không" nếu được policy cho
Theo dõi điều trịtreatment_progress_entryCó/Khôngview_summary
Scanscan_checklistĐủ/Thiếuview_summary

B2.4) Quy ước export

Trường hợpHành vi
User có view_medical_detailExport đủ ICD, kỹ thuật, diễn biến, vật tư nếu policy cho
User chỉ có view_summaryExport vẫn chạy nhưng cột y tế nhạy cảm là "—"
Có >5.000 dòngUI yêu cầu thu hẹp khoảng ngày hoặc tạo export job nền
Không có dữ liệuCopy: "Chưa có ca thủ thuật trong khoảng thời gian này."

SCR-13: Trang xem an toàn (Sale)

text
/crm/customer/{id}/sales-safe-clinical   [Trang xem an toàn — Tư vấn]

Header: KH Lê Thị Hương · Đã đến CN Cao Lãnh 12 lần

⚠ Cảnh báo an toàn (chỉ tóm tắt):
   ┌──────────────────────────────────────────────────────┐
   │ ⚠ MỨC CAO: Có 1 cảnh báo dị ứng                      │
   │   — Vui lòng chuyển bác sĩ tư vấn dịch vụ liên quan  │
   │   thuốc tiêm để xác nhận an toàn.                    │
   ├──────────────────────────────────────────────────────┤
   │ ℹ Trung bình: Có bệnh nền cần lưu ý                  │
   │   — Tư vấn cẩn thận với liệu trình thẩm mỹ xâm lấn.  │
   └──────────────────────────────────────────────────────┘

Lịch sử dịch vụ (12 lượt):
┌───────────┬────────────────────────┬──────────────┬──────────┐
│ Ngày      │ Dịch vụ                │ Chi nhánh    │ Số tiền  │
├───────────┼────────────────────────┼──────────────┼──────────┤
│ 02/04/26  │ Liệu trình trị mụn     │ Cao Lãnh     │ 3.5tr    │
│ 15/03/26  │ Tẩy trang sâu          │ Cao Lãnh     │ 0.8tr    │
│ ...       │                        │              │          │
└───────────┴────────────────────────┴──────────────┴──────────┘

Số bệnh án: 5  ·  Bệnh án gần nhất: 02/04/2026

[Chuyển bác sĩ tư vấn]                  [Ghi chú kỳ vọng KH]

B2.4) Field hiển thị (ref B3.0.2 ma trận tầng dữ liệu — Sale chỉ thấy tầng 1+2)

Quy định cứng: Sale KHÔNG bao giờ thấy: chẩn đoán, ICD-10, ghi chú BS, đơn thuốc, ảnh y tế tầng 3, bản scan đã ký. Bấm "Chuyển bác sĩ tư vấn" → form handoff với kiểm tra regex chống ghi chẩn đoán/mã ICD vào safe note.

B2.5) Hành vi click trên Lịch sử dịch vụ

Click vàoHành vi cho Sale
Tên dịch vụ trong lịch sửMở popup "Tóm tắt dịch vụ" (tên dịch vụ, CN, ngày, số tiền, ghi chú quầy đã được lọc theo Trang xem an toàn) — KHÔNG link sang BA / form / scan
Cảnh báo an toàn (alert level/code)Tooltip mô tả mức cảnh báo (ví dụ "Mức cao") + gợi ý "Vui lòng chuyển bác sĩ để xem chi tiết" — KHÔNG show diagnosis/ICD
"Chuyển bác sĩ tư vấn"Mở SCR-handoff với expectations + safe notes; backend regex chặn nội dung chứa thuật ngữ y khoa, mã ICD, tên thuốc kê đơn
"Ghi chú kỳ vọng KH"Mở textarea ghi vào customer.crm_note (hiện hữu) — KHÔNG ghi vào clinical_*

SCR-14: Bàn việc bác sĩ

text
/e/service-order/doctor-workbench    [Bàn việc bác sĩ]

Header: BS Trần Mỹ Hương · CN Cao Lãnh · Hôm nay 02/05/2026

┌─ Tổng quan ──────────────────────────────────────────────────────┐
│ 6 nhóm việc · Tổng 13 việc                                        │
└──────────────────────────────────────────────────────────────────┘

┌──────────────────────┬──────────────────────┬──────────────────────┐
│ 🆕 Cần tạo BA (3)    │ 📝 BA nháp (2)        │ 🖨 Cần in (1)        │
├──────────────────────┼──────────────────────┼──────────────────────┤
│ • KH Lê Hương        │ • KH Vũ Trang        │ • KH Phạm Hà         │
│   Liệu trình mụn     │   BA TM nháp 1h      │   BA DL hoàn thành  │
│   [Tạo BA →]         │   [Mở nháp →]        │   [In →]             │
│                      │                      │                      │
│ • KH Đỗ Linh         │ • KH Bùi Mai         │                      │
│   Filler             │   BA DL nháp 30p     │                      │
│   [Tạo BA →]         │   [Mở nháp →]        │                      │
│                      │                      │                      │
│ • KH Nguyễn Lan      │                      │                      │
│   Nâng mũi           │                      │                      │
│   [Tạo BA →]         │                      │                      │
└──────────────────────┴──────────────────────┴──────────────────────┘

┌──────────────────────────┬─────────────────────────┬──────────────────────────┐
│ 📎 Cần scan (4)          │ 🤝 Sale chuyển (1)       │ 📋 Tự khai chờ (2)       │
├──────────────────────────┼─────────────────────────┼──────────────────────────┤
│ • DVA-DL-CL-2026-00145   │ • Sale Hồng chuyển      │ • KH Trần Hà             │
│   2 ngày chưa scan       │   KH Hoa                 │   Phiếu tự khai chờ nhận │
│   [Tải bản scan →]       │   [Xem ghi chú →]        │   [Rà soát →]            │
│                          │                          │                          │
│ • DVA-TM-CL-2026-00089   │                          │ • KH Lý Mai              │
│   1 ngày chưa scan       │                          │   [Rà soát →]            │
│   [Tải bản scan →]       │                          │                          │
│                          │                          │                          │
│ • ... (2 BA nữa)         │                          │                          │
└──────────────────────────┴─────────────────────────┴──────────────────────────┘

[Tải lại]

B2.7)

Tình huốngHành vi
Bấm nhóm việcMở danh sách đã lọc; bấm một việc → luồng tương ứng (tạo BA / mở nháp / in / scan / nhận chuyển từ Sale / rà soát phiếu khách tự khai)
Việc hoàn thànhTự bỏ khỏi nhóm việc; thông báo nhanh "Đã hoàn thành việc"
Kéo để tải lạiTải lại tất cả 6 nhóm việc
Cập nhật tức thời(Phase 2 — WebSocket); Day-1 polling 60 giây

SCR-15: Phiếu khách tự khai (cổng tablet quầy theo token)

text
/p/customer-clinical-intake/{token}   [Phiếu khách tự khai — Tablet]

🌸 Kính chào quý khách Lê Thị Hương                  ⏱ Còn 14:23

Vui lòng điền thông tin sau trước khi gặp bác sĩ:

1. Tiền sử dị ứng (chọn nhiều)
   ☐ Penicillin       ☐ Aspirin         ☐ Hải sản
   ☐ Đậu phộng        ☐ Mủ cao su       ☐ Khác: [_______]
   ☐ Tôi không có dị ứng

2. Bệnh nền (chọn nhiều)
   ☐ Đái tháo đường   ☐ Cao huyết áp    ☐ Tim mạch
   ☐ Hen suyễn        ☐ Khác: [_______]
   ☐ Tôi không có bệnh nền

3. Thuốc đang dùng (text)
   [Metformin 500mg, ngày 2 viên                              ]

4. Đã từng phẫu thuật/thủ thuật?
   ◉ Có  ○ Không
   Nếu có, ghi rõ: [Cắt amidan 2018                           ]

5. Đang mang thai?
   ○ Có  ◉ Không  ○ Không chắc

[Lưu nháp]                            [Hoàn thành — gửi cho bác sĩ →]

B2.7)

Tình huốngHành vi
Hết hạn 15 phútBanner "Phiên đã hết hạn. Vui lòng nhờ lễ tân mở lại." + bị khóa gửi
GửiServer kiểm tra appointment/customer/branch khớp token → lưu customer_clinical_intake.form_data
BS rà soátBS thấy nhóm việc "Phiếu tự khai chờ" trong Bàn việc bác sĩ → mở màn rà soát → bấm "Nhận vào hồ sơ" → ghi vào clinical_form_instance với source_type='customer_intake'

SCR-16: Trang điều phối phòng khám

text
/e/service-order/clinic-ops-dashboard   [Điều phối phòng khám — Toàn chuỗi]

Vai trò: Ops · Lọc: Tất cả CN ▼  ·  [Ngày: Hôm nay ▼]

┌─ Tổng quan toàn chuỗi (12 CN đang hoạt động) ──────────────────────┐
│ Đang hoạt động: 10 CN · Tạm dừng: 1 · Đang cấu hình: 1             │
│ ⚠ Cần Ops xử lý: 5 cảnh báo                                        │
└────────────────────────────────────────────────────────────────────┘

┌─ CN Cao Lãnh ─────────────────────┬─ CN Tân Bình II ────────────────┐
│ [Đang hoạt động]                   │ [Đang hoạt động]                 │
│                                    │                                  │
│ Hôm nay: 15 lượt khám             │ Hôm nay: 22 lượt khám           │
│ • 12 hoàn thành ✓                 │ • 18 hoàn thành ✓               │
│ • 2 nháp ⚠                         │ • 3 nháp                         │
│ • 1 cần scan ⚠                     │ • 1 cần scan                     │
│                                    │                                  │
│ Lệch cấu hình:                     │ Lệch cấu hình:                   │
│ ⚠ 3 dịch vụ chưa phân loại        │ ✓ Không có lệch cấu hình         │
│ [Đến danh mục dịch vụ →]          │                                  │
│                                    │                                  │
│ Mở quyền khẩn cấp hôm nay: 0      │ Mở quyền khẩn cấp: 1 (BS Long)  │
│                                    │ [Xem audit log →]                │
│                                    │                                  │
│ Cutoff: 20:00 · Trạng thái: chờ   │ Cutoff: 19:30 · Đã chốt 19:35   │
│ [Chốt ngày]                        │ ✓ Đã chốt                        │
└────────────────────────────────────┴──────────────────────────────────┘

... (10 CN khác)

[Xuất báo cáo Excel]

SCR-17: Hộp thoại Chốt ngày phòng khám

text
[Chốt ngày phòng khám — CN Cao Lãnh — 02/05/2026]              [×]

⚠ Còn việc chưa hoàn tất:
   • 2 bệnh án còn ở "Bản nháp" (BS Hương: 2)
   • 1 bệnh án "Đã in" chưa tải bản scan đã ký (DVA-DL-CL-2026-00145)

Bấm "Chốt ngày" sẽ:
   ✓ Ghi nhận trạng thái lúc {NOW}
   ✓ Gửi cảnh báo 1 BA ưu tiên cao chưa scan tới Ops + Medical Lead
   ✓ Khóa cron reminder cho ngày này
   ✓ Ghi audit `clinic_daily_close` với người chốt

Lý do (bắt buộc nếu còn BA ưu tiên cao chưa giải quyết):
[BS Hương sẽ hoàn thành 2 BA nháp sáng mai. Đã liên hệ KH Phạm Hà   ]
[để hẹn quay scan ngày 03/05.                                       ]

[Hủy]                                                  [Chốt ngày]

SCR-18: Trang Compliance Audit Viewer

Tham chiếu: permission-spec.md P11.2. Day-1 build optional; nếu defer Phase 2 thì PD-PERM-004 phải resolved trước.

B2.1) Ngữ cảnh nghiệp vụ

Câu hỏiCần chốt
Ai dùng?Compliance officer, Admin/Ops, Medical Lead (xem audit của mình + branch scope)
Vào màn để quyết định gì?Theo dõi truy cập tầng 3, emergency override, hard-deny attempts; phát hiện anomaly; export audit cho Sở Y tế
Dữ liệu chínhmedical_record_access_log, emergency_override_session, permission_change_log, audit_export_log
CTA chính / phụPrimary: "Xuất Excel"; Secondary: "Xem chi tiết event", "Force revoke override" (Phase 2), "Lọc nâng cao"
Điều không được hiểu nhầmCompliance KHÔNG mở được form BA / scan; chỉ thấy metadata audit. Nội dung tầng 3 raw vẫn không expose qua trang này

B2.2) Bố cục — Build mới

text
/s/compliance/clinical-audit       [Compliance Audit Viewer]

Header: Compliance Audit · Filter Period: 01/05/2026 - 02/05/2026

[Bộ lọc:]
[Khoảng ngày: 01/05 - 02/05] [User: Tất cả ▼] [CN: Tất cả ▼]
[Action: Tất cả ▼] [Sensitivity: high+critical ▼] [Anomaly: Tất cả ▼]
[Tìm correlation_id / KH / mã BA...]                    [Xuất Excel]

Tổng: 1.247 events · Critical: 12 · High: 184 · Anomaly flagged: 3

┌────┬──────────────┬─────────────┬─────────┬──────────────────┬──────────┬────────────┬─────────┐
│ #  │ Thời điểm    │ Người dùng  │ Vai trò │ Hành động        │ CN       │ Sensitivity│ Anomaly │
├────┼──────────────┼─────────────┼─────────┼──────────────────┼──────────┼────────────┼─────────┤
│ 1  │02/05 14:32:15│BS Hương     │BS DL    │view_medical_detail│Cao Lãnh │ high       │ —       │
│ 2  │02/05 14:30:08│BS Long      │BS TM    │emergency_override│Cao Lãnh→TBII│ critical│ ⚠ rate  │
│ 3  │02/05 14:25:33│Sale Hồng    │Sale     │view_medical_detail│Cao Lãnh │ high       │ ⛔ HARD │
│ 4  │02/05 14:20:11│Y tá Hà      │Y tá     │upload_scan       │Cao Lãnh │ medium     │ —       │
└────┴──────────────┴─────────────┴─────────┴──────────────────┴──────────┴────────────┴─────────┘

Row action: [Xem chi tiết] [Mở record liên quan] [Filter user/action]

B2.3) Cột dữ liệu

CộtNguồnFormatQuyền
Thời điểmmedical_record_access_log.created_atDD/MM HH:mm:ssclinical_record.export_visit_log
Người dùngactor_user_id → join accountTên + CN
Vai tròaccount.role (snapshot tại thời điểm event)Text VI
Hành độngaction enumDisplay VI + code backtick
CNbranch_idBranch code + tên
Sensitivityderived từ P1.2Badge color
Anomalyflag từ anomaly detection cronIcon ⚠/⛔
Correlation IDcorrelation_idUUID truncated 8 ký tự

B2.4) Detail event modal

text
[Chi tiết event #1247]                                              [×]

Correlation ID: f47ac10b
Thời điểm: 02/05/2026 14:32:15.234 +07:00
Người dùng: BS Trần Mỹ Hương (acc_doctor_huong)
Vai trò: BS DL · Portal: staff · Branch_mode: branch
CN của user: Cao Lãnh
Hành động: clinical_record.view_medical_detail · Sensitivity: high

Đối tượng:
  • Loại: clinical_record
  • ID: dva-dl-cl-2026-00147
  • KH: Lê Thị Hương (cust_***456)
  • CN của record: Cao Lãnh

Resolver output:
  • Allowed: true
  • View mode: full_tier3
  • Branch scope: branch
  • Field allowlist: 28 fields (ICD, diagnosis, form_data, prescription, ...)
  • Audit required: true

IP / Device: 113.161.***.45 / desktop-chrome
Session ID (hash): 8a7b9c0d
Reason (nếu emergency): —

[Đóng]                                                [Mở record liên quan]

B2.5) Bộ lọc nâng cao

Bộ lọcMặc địnhGhi chú
Khoảng ngày7 ngày gần nhấtTối đa 90 ngày/lần xuất
UserTất cảSearch by name / account_id
CNTất cảTheo branch_assignment của Compliance officer
ActionTất cảMulti-select; default high+critical
SensitivityTất cảQuick filter: critical / high+critical / all
AnomalyTất cảrate_limit / hard_deny / wrong_portal
Correlation IDRỗngTrace cross-request

B2.6) Trạng thái và copy

Tình huốngCopy
Không có dữ liệu"Không có event audit trong khoảng thời gian này."
Anomaly count > 0Banner đỏ trên cùng "Phát hiện {N} anomaly cần review"
Filter trả >5.000 dòng"Khoảng quá rộng. Vui lòng thu hẹp filter hoặc dùng async export."
Export thành côngThông báo nhanh "Đã xuất {X} dòng. Bấm để tải về." + audit audit_export_log
Force revoke (Phase 2)Hộp thoại xác nhận "Force revoke session emergency của BS {name}? User sẽ mất quyền tầng 3 ngay."

B2.7) Quy ước tương tác

Tình huốngHành vi
Click rowMở detail modal
Click action filterApply ngay + reset paging
Click "Mở record liên quan"Nếu Compliance có quyền → mở SCR-01 với context audit; nếu không → toast "Bạn không có quyền vào hồ sơ. Đây là log audit only."
Polling60s tự refetch (Compliance dashboard near-realtime)
Anomaly alertBanner đỏ + push notification cho Compliance officer

B2.8) Phân quyền

QuyềnUI
clinical_record.export_visit_log + flag compliance_role=trueVào trang đầy đủ, export được
Admin/Ops không có flag complianceVào được nhưng không có cột "Anomaly" detail; không export raw audit
Medical LeadVào được, scope theo multi_branch assignment
KhácĐường dẫn 401

B2.9) Hạn chế (Day-1)

  • KHÔNG mở được form BA / scan từ trang này (chỉ metadata)
  • Force revoke override = Phase 2 (cần workflow approval)
  • Anomaly ML detect = Phase 3 (Day-1 chỉ rule-based đơn giản)
  • Forward to authority = Phase 3
  • Day-1 polling 60s; Phase 2 thêm WebSocket near-realtime

B3) Luồng người dùng

Luồng 1 — Admin bật module Phòng khám CN (5 bước + kiểm tra sẵn sàng)

Admin login Settings → Branch Detail CN Cao Lãnh
  → Tab "Phòng khám" → CTA "Bật module" → trạng thái=`setup_draft`
  → Bước 1: Loại PK = "Cả DL+TM" → Lưu, Tiếp
  → Bước 2: Tải giấy phép SYT 123/SYT-DT, expiry 2028-12-31 → Tiếp
  → Bước 3: Chọn 25 KT từ master (+ 2 KT tự thêm: Áp lạnh nitơ, Filler) → Tiếp
  → Bước 4: Phân loại 50 dịch vụ đang bán (45 cần BA + 5 không cần BA) → Tiếp
  → Bước 5: Cấp quyền: BS Hương + BS Long (BS DL/TM); Y tá Hà (admin_shared); QL CN Tâm → Lưu
  → Bước 6: Kiểm tra sẵn sàng R-01..R-10 → 10/10 Đạt
  → trạng thái=`ready_to_publish` → CTA "Phát hành" mở
  → Admin chọn effective_at = "02/05/2026 09:00" → trạng thái=`scheduled`
  → Cron 09:00 ngày 02/05 → trạng thái=`live`
  → UI clinical xuất hiện cho team CN Cao Lãnh

Luồng 2 — BS điền BA từ lịch hẹn (đường chuẩn)

KH Lê Hương đến quầy có lịch hẹn 14:30 → Lễ tân check-in
  → Bàn việc bác sĩ (BS Hương): nhóm `need_record` có việc KH Lê Hương
  → BS bấm [Tạo BA →] → SCR-06 (Form BA DL)
  → Điền 6 section + ICD-10 primary L70.0 → autosave 30s mỗi lần dừng
  → BS bấm "Hoàn thành" → trạng thái=`completed`
  → BS bấm "In bộ hồ sơ" SCR-09 → trạng thái=`printed`
  → BS + KH ký tay bản giấy
  → Y tá scan SCR-10: tải file pdf 8 trang, mapping đầy đủ
  → trạng thái=`signed` → thông báo nhanh "Đã ký + scan đủ"

Luồng 3 — BS walk-in (khám trước, đơn sau)

KH chưa có lịch, đến trực tiếp → Lễ tân SCR-05 chọn "Khách walk-in — tạo mới"
  → Popup tạo KH inline → lưu được customer_id mới
  → Lưu lượt khám với appointment.customer_id=`{id mới}`, order_item_id=NULL
  → BS Bàn việc bác sĩ thấy việc cần xử lý → tạo BA DL
  → BS xong khám → CTA "Tạo đơn từ lượt khám"
  → Order tạo với reference_appointment_id=appointment.id
  → appointment.order_item_id vẫn NULL (DEC-003 — không backfill)

Luồng 4 — Mở quyền khẩn cấp tầng 3 khác CN

KH cấp cứu chuyển từ TBII đến Cao Lãnh → BS Hương cần xem BA tầng 3 cũ
  → BS mở Customer Detail KH → tab Hồ sơ bệnh án → thấy chỉ tầng 1+2
  → Bấm "Mở quyền khẩn cấp" → Hộp thoại "Lý do (bắt buộc, ≥30 ký tự)"
  → BS gõ "Khách cấp cứu chuyển từ Tân Bình II, cần xem chẩn đoán cũ"
  → Server insert medical_record_access_log (action='emergency_override', reason)
  → BS xem được tầng 3 trong session 1 giờ
  → Ops + Medical Lead nhận push noti_medical_record_emergency_override

Luồng 5 — Sale tư vấn an toàn và chuyển BS

Sale Hồng tìm KH Lê Hương → CRM Customer Detail → tab "Trang xem an toàn"
  → Thấy: cảnh báo dị ứng (chỉ alert level), lịch sử dịch vụ, count BA
  → KHÔNG thấy: chẩn đoán, ICD-10, ghi chú BS
  → Sale click "Chuyển bác sĩ tư vấn" → Form handoff
  → Chọn BS Hương + ghi expectations + safe note
  → Gửi → backend regex check (không chứa ICD/diagnosis)
  → BS Hương nhận noti_clinical_handoff_created

Luồng 6 — KH tự khai trước khám tại quầy

KH Lê Hương đến quầy 14:25 → Lễ tân mở Phiếu khách tự khai cho appointment 14:30
  → Server tạo customer_clinical_intake.token + URL → mở trên tablet
  → KH điền 5 dị ứng + 2 bệnh nền + 3 thuốc đang dùng → Gửi qua token
  → Server kiểm tra appointment/customer/branch khớp → lưu phiếu tự khai
  → BS Bàn việc bác sĩ thấy nhóm "Phiếu tự khai chờ" → bấm Rà soát
  → BS bấm "Nhận vào hồ sơ" → ghi vào clinical_form_instance với source_type='customer_intake'

Luồng 7 — Trang điều phối + Chốt ngày phòng khám

19:30 cron pre-cutoff → Notification cho QL CN Cao Lãnh:
  "Còn 5 BA chưa hoàn thành tại CN Cao Lãnh trước 20:00"
20:00 cron ghi nhận trạng thái → log clinic_daily_close pending
QL CN vào Trang điều phối SCR-16 → CN Cao Lãnh có cảnh báo
QL CN bấm "Chốt ngày" → Hộp thoại SCR-17 confirm
  → Còn 1 BA ưu tiên cao chưa scan → bắt buộc lý do
QL CN gõ lý do, Gửi → log clinic_daily_close.closed_at + gửi cảnh báo tới Ops

B3.0) Ma trận bao phủ luồng/case (EXT-6 — L profile)

B3.0.1) Bản đồ trải nghiệm theo vai trò

Vai tròEntry pointCông việc chínhĐường mànDữ liệu được thấyKết quả đầu raCase QA bắt buộc
Admin/OpsSettings menuBật + cấu hình + phát hành module per CNSCR-04 → SCR-04a..fCấu hình toàn CNModule đang hoạt độngCASE-SETUP-01..10
Bác sĩ DLBàn việc bác sĩKhám + điền BA DL + in + scanSCR-14 → SCR-06 → SCR-08 → SCR-09 → SCR-10Tầng 3 đầy đủ CN mìnhBA signedCASE-RUN-DL-01..10
Bác sĩ TMBàn việc bác sĩKhám + điền BA TM 4 phân hệSCR-14 → SCR-07 → SCR-08 → SCR-09 → SCR-10Tầng 3 đầy đủ CN mìnhBA signedCASE-RUN-TM-01..08
Y táBàn việc bác sĩ (need_scan)Hỗ trợ hành chính, scanSCR-14 → SCR-10Tầng 1+2 + admin_sharedScan đủCASE-NURSE-01..05
Lễ tânPOS OrderTạo đơn + mở phiên khách tự khaiSCR-02 → SCR-05 → SCR-15 (mở token)Tầng 1 onlyLượt khám tạoCASE-RECEPT-01..05
Sale CRMCustomer Detail (CRM)Tư vấn + chuyển BSSCR-13 → form handoffTầng 1+2 (an toàn)Phiếu chuyển BSCASE-SALE-01..06
QL CNTrang điều phối CN mìnhGiám sát + chốt ngàySCR-16 → SCR-17Tầng 1+2 + admin_shared CN mìnhĐã chốt ngàyCASE-BM-01..05
Khách hàngTablet quầyTự khai trước khámSCR-15 (token)Form tự khai (1+2)Intake gửiCASE-CUSTOMER-01..03
Compliance officerAudit log exportAudit truy cập tầng 3(audit page — Phase 2)Audit log fullExport CSVCASE-AUDIT-01..03

B3.0.2) Ma trận case CASE-{NHOM}-

≥30 case theo nhóm, mỗi case có Case ID ổn định.

Case IDNhóm luồngVai tròĐiều kiện dữ liệuMàn vàoĐường mànUI đúngCTA bật/ẩnKhôi phục/ngoại lệTrace
CASE-SETUP-01Setup happyAdminCN spa thuần chưa bậtSCR-04→ SCR-04a..f → phát hành6 step đạt + CTA "Phát hành" mở"Phát hành" mởFR-001/FR-002, TC-001-01
CASE-SETUP-02Setup unclassified chặnAdmin5 dịch vụ unclassifiedSCR-04dTrợ lý bước 4Banner đỏ "Còn 5 chưa phân loại""Tiếp" bị khóaBấm [Đến danh mục dịch vụ]FR-003, TC-003-03
CASE-SETUP-03Setup kiểm tra sẵn sàng không đạtAdminR-04 không đạt (KT unknown)SCR-04fTrợ lý bước 6Highlight đỏ R-04 + deeplink"Phát hành" bị khóaĐến KT phân loạiFR-015, TC-015-03
CASE-SETUP-04Phát hành scheduledAdminPass 100% kiểm tra sẵn sàngSCR-04fBấm "Phát hành" → chọn effectiveHộp thoại effective + confirm"Xác nhận phát hành"FR-015, TC-015-04
CASE-SETUP-05Tạm dừng module đang hoạt độngAdminCN đang liveSCR-04Bấm "Tạm dừng" + lý doHộp thoại confirm"Tạm dừng"DEC-030, TC-001-04
CASE-SETUP-06Rollback paused → liveAdminCN pausedSCR-04Bấm "Tiếp tục"Hộp thoại xác nhận"Tiếp tục"DEC-030
CASE-RUN-DL-01BA DL happy pathBSKH có appointment + dịch vụ DLSCR-14→ SCR-06 → SCR-09 → SCR-10Form đầy đủ + ICD primary"Hoàn thành" mởFR-005, TC-005-01
CASE-RUN-DL-02BA DL thiếu ICD chínhBSForm chưa chọn ICD chínhSCR-06Bấm "Hoàn thành"Lỗi tại field + focus field"Hoàn thành" từ chốiChọn ICD primaryTC-005-04
CASE-RUN-DL-03BA DL allergy unknown chặnBSKT có allergy_risk_level=unknownSCR-06Bấm "Hoàn thành"Banner chặn"Hoàn thành" bị khóaLiên hệ Medical LeadFR-010, TC-010-03
CASE-RUN-DL-04BA DL allergy high cần phiếuBSKT high + chưa có phiếu dị ứngSCR-06Bấm "Hoàn thành"Banner đỏ + CTA mở phiếu"Hoàn thành" bị khóaTạo phiếu dị ứngFR-010, TC-010-02
CASE-RUN-DL-05Autosave 30sBSĐang gõ formSCR-06Dừng gõ 30sThông báo nhanh "Đã lưu nháp lúc HH:mm"(silent autosave)Mất mạng → retryFR-008, TC-008-01
CASE-RUN-DL-06Conflict 2 BS cùng recordBS A + BS BCùng mở 1 recordSCR-06BS B lưu trướcHộp thoại "Có thay đổi từ thiết bị khác" cho BS A"Giữ thay đổi" / "Lấy bản mới"FR-008, TC-008-04
CASE-RUN-DL-07In sau hoàn thànhBStrạng thái=completedSCR-06Bấm "In bộ hồ sơ"SCR-09 xem trước PDF"In" mởFR-009, TC-009-01
CASE-RUN-DL-08Scan đủ checklistY tátrạng thái=printedSCR-10Tải file + mapping đủThông báo nhanh "Đã ký + scan đủ""Lưu"FR-009, TC-009-03
CASE-RUN-DL-09Scan thiếu checklistY táTải 1 file mapping 1 phầnSCR-10Bấm LưuBanner "Còn thiếu: X, Y"trạng thái vẫn printedTải tiếpTC-009-04
CASE-RUN-DL-10KH từ chối kýY táKH từ chốiSCR-10Tab "Biên bản từ chối"Form + y tá làm chứng"Lưu"DEC-024, TC-009-06
CASE-RUN-TM-01BA TM auto-hiện section MũiBSDịch vụ "Nâng mũi"SCR-07Mở formSection Mũi expandFR-006, TC-006-01
CASE-RUN-TM-02BS bật thêm section KhácBS(cùng case TM-01)SCR-07Bấm "+ Bật phân hệ Khác"Section mở + warningFR-006, TC-006-02
CASE-RUN-TM-03BA TM thiếu thủ thuật xâm lấnBSFiller + chưa phiếu dị ứngSCR-07"Hoàn thành"Banner đỏchặnTạo phiếu dị ứngTC-006-04
CASE-WALKIN-01Walk-in happyLễ tânKH chưa có appointment, KH chưa có hồ sơSCR-05Tạo KH inline → tạo walk-inappointment.customer_id={id mới}, order_item_id=NULLFR-004, TC-004-01
CASE-WALKIN-02Walk-in nullguard eventSystemevent handler appointment_update(cron)run handlerKhông crash khi order_item_id=NULLFR-004, TC-004-02 [CRITICAL]
CASE-WALKIN-03Late-link orderLễ tânwalk-in xong, tạo đơnOrderFormConfirmorder.reference_appointment_id linkTC-004-03
CASE-PERM-01Sale chặn cứng tầng 3SaleCố mở tầng 3(any)Gọi API trực tiếp403 + log warningFR-011, TC-011-01 [SECURITY CRITICAL]
CASE-PERM-02BS khác CN xem tầng 1+2BS BKH ở CN khácSCR-01Mở tab Hồ sơ bệnh ánChỉ tầng 1+2; tầng 3 = NULL"Mở quyền khẩn cấp" mởTC-011-04
CASE-PERM-03Mở quyền khẩn cấp + auditBS BCó lý do khẩn cấpSCR-01Bấm "Mở quyền khẩn cấp"Hộp thoại lý do + log access"Xác nhận"FR-011, TC-011-05
CASE-PERM-04Revoke quyền vận hànhAdminBS A đang dùng(any)Admin revoke role_module.actionsRequest kế tiếp trả 401 sau cache invalidateTải lạiFR-011, TC-011-08
CASE-SALE-01Sale xem an toànSaleKH có alertSCR-13Mở trangCard alert (label only); KHÔNG có ICD/diagnosis"Chuyển bác sĩ tư vấn" mởFR-016, TC-016-01
CASE-SALE-02Phiếu chuyển bác sĩ tư vấn với regex checkSaleSafe note có "L70.0"SCR-13Gửi phiếu chuyển422 từ chối + lỗi rõSửa noteTC-016-04
CASE-INTAKE-01Token happyLễ tân + KHAppointment 14:30SCR-15Lễ tân mở token + KH gửiForm prefill cho BSFR-018, TC-018-01
CASE-INTAKE-02Token expiredKHQuá 15 phútSCR-15Bấm gửiBanner "Phiên đã hết hạn""Nút Gửi bị khóa"Lễ tân mở lạiTC-018-04
CASE-INTAKE-03KH/CN/appointment mismatchKHToken sai CNSCR-15Gửi422 từ chốiTC-018-05
CASE-CLOSE-01Chốt ngày thành côngQL CNĐến giờ chốt ngàySCR-16 → SCR-17Bấm Chốt + nhập lý doThông báo nhanh "Đã chốt" + log"Chốt ngày"FR-019, TC-019-04
CASE-CLOSE-02Chốt ngày gửi cảnh báo BA ưu tiên caoQL CNCòn 1 BA ưu tiên cao (P0) chưa scanSCR-17Bấm ChốtHộp thoại "Còn BA ưu tiên cao" + bắt buộc lý do"Chốt" sau khi điền lý doTC-019-05
CASE-OPS-01Lệch cấu hìnhOpsCN có dịch vụ unclassified sau khi đang hoạt độngSCR-16Mở trang điều phốiThẻ cảnh báo CN + số lượng"Đến danh mục dịch vụ"FR-019

B3.0.3) Ma trận hiển thị dữ liệu (EXT-4 — field × role × view mode)

Áp dụng cho dữ liệu nhạy cảm tầng 3. Quy định cứng: Sale luôn bị ẩn tầng 3.

FieldAdminOpsBác sĩ cùng CNBác sĩ khác CNY tá cùng CNQL CNLễ tânSaleKháchPortal
clinical_record.profile_code (mã BA)fullfullfullfull (1+2 only)summarysummarybị ẩnbị ẩnbị ẩnadmin/staff
clinical_record.diagnosis_codes (ICD)fullfullfullbị ẩn (cần emergency)bị ẩnbị ẩnbị ẩnbị ẩnbị ẩnadmin/staff
clinical_form_instance.form_data (raw form BA)fullbị ẩnfullbị ẩn (cần emergency)partial (admin_shared only)bị ẩnbị ẩnbị ẩnbị ẩnadmin/staff
Doctor note (free text)fullbị ẩnfullbị ẩnbị ẩnbị ẩnbị ẩnbị ẩnbị ẩnadmin/staff
prescription.items (đơn thuốc)fullbị ẩnfullbị ẩnpartial (read print)bị ẩnbị ẩnbị ẩnbị ẩnadmin/staff
reference_file type='clinical_record.before_after'fullbị ẩnfullbị ẩnpartial (upload)bị ẩnbị ẩnbị ẩnbị ẩnadmin/staff
reference_file type='clinical_form_instance.scan'fullbị ẩnfullbị ẩnpartial (upload)bị ẩnbị ẩnbị ẩnbị ẩnadmin/staff
clinical_record.allergy_summary (label)fullsummaryfullsummarysummarysummarysummarysummary (label only — DEC-009)bị ẩnall
clinical_record.visit_count (count)fullfullfullfullfullfullfullfullbị ẩnall
clinical_record.status (badge)fullfullfullfullfullfullsummary (count only)summarybị ẩnall

Quy tắc enforcement: FE ẩn không đủ → BE phải resolve effective permission từ role_module.actions + portal + branch_mode + branch scope; field hidden → loại khỏi response, KHÔNG chỉ CSS-hide.


B4) Đặc tả thông báo

#Trigger codeĐiều kiện kích hoạtKênhMẫu nội dung VIMẫu nội dung ENChống trùng
1noti_medical_record_incompleteLễ tân tạo order với dịch vụ mapped_requires_baPush + In-app"Có 1 bệnh án cần tạo cho khách {customer_name}. Mở Bàn việc bác sĩ →""1 medical record needs creation for {customer_name}. Open Workbench →"Dedupe clinical_record_{appointment_id}_incomplete, retry 3 lần x 5 phút
2noti_medical_record_needs_printBA completed quá 30 phút chưa inPush"Bệnh án {profile_code} đã hoàn thành — vui lòng in để khách ký""Record {profile_code} ready to print"Dedupe ..._needs_print per record, 1 lần
3noti_medical_record_needs_scanBA printed quá 1 giờ chưa scanPush"Bệnh án {profile_code} chưa tải bản scan đã ký""Record {profile_code} missing signed scan"Dedupe per record
4noti_medical_record_allergy_warningBS hoàn thành BA với allergy_risk_level=unknown/highIn-app + Push"⚠ An toàn dị ứng: kỹ thuật {tech_name} cần xác nhận trước khi tiến hành""⚠ Allergy: technique {tech_name} requires confirmation"Dedupe per record
5noti_medical_record_end_of_dayPre-cutoff 30 phút trước cutoff CNPush + In-app"Còn {N} bệnh án chưa hoàn thành tại {branch_name} trước {cutoff_time}""{N} records pending at {branch_name} before {cutoff_time}"Dedupe per CN per ngày
6noti_medical_record_emergency_overrideBS dùng Mở quyền khẩn cấpPush + Email (Medical Lead)"BS {doctor_name} mở quyền khẩn cấp xem bệnh án {profile_code} với lý do: {reason}""Emergency override by {doctor_name} on {profile_code}: {reason}"Per event (không dedupe)
7noti_clinical_handoff_createdSale tạo handoff cho BSPush + In-app"Sale {sale_name} chuyển khách {customer_name} cho bạn tư vấn dịch vụ""Sale {sale_name} handed off customer {customer_name} to you"Dedupe ..._{handoff_id}

Quy tắc deeplink: Push deeplink chỉ chứa record_id + branch_id. KHÔNG chứa chẩn đoán, ICD-10, form raw, scan URL. Quy tắc Sale: Sale KHÔNG nhận bất kỳ notification clinical nào.


B5) Đặc tả xuất dữ liệu

Sổ khám bệnh

CộtHeaderĐịnh dạngĐộ rộngĐiều kiện theo quyền
1STT sổ khámtext (FORMULA-002)autoclinical_record.export_visit_log
2Ngày khámDD/MM/YYYYfixed
3Mã BAtext (FORMULA-001)autoview_summary
4Tên KHtextauto
5Tuổinumberfixed
6Giới tínhtextfixed
7Bác sĩtextauto
8Chẩn đoán chính (ICD)textautoview_medical_detail (nếu thiếu → "—")
9Trạng thái BAenumfixedview_summary
10CNtextfixedview_summary
  • Tên file: so-kham-benh-{branch_code}-{MM-YYYY}_{timestamp}.xlsx
  • Giới hạn dòng: unlimited (chunk 100/page)
  • Ngưỡng async: > 1.000 dòng → background job (chunk by 100 — pattern export_salary.go)

Sổ thủ thuật

Tương tự sổ khám bệnh + thêm cột: STT thủ thuật (FORMULA-003), Kỹ thuật, Vật tư (TBD Phase 2), Biến chứng (text optional).

Audit log truy cập tầng 3

CộtHeaderĐiều kiện theo quyền
1Thời điểmAdmin/Compliance only
2Người truy cập
3Vai trò
4CN truy cập
5Mã BA
6Loại thao tác
7Lý do (nếu emergency)
8IP / Device

B6) Ma trận phân quyền (Permission v2 canonical)

Ref SOURCE_OF_TRUTH.md mục 5.2 — đây là tóm tắt UI gating. Không lặp toàn bộ ma trận.

ModuleActionUI hiển thị/ẩnKhi thu hồi quyền
clinic_moduleaccessHiện tab Phòng khám trong Branch DetailẨn tab sau refetch
clinic_moduleconfigureMở trợ lý cấu hình 6 bước (sửa được)Trợ lý chuyển sang chỉ đọc
clinic_modulepublishCTA "Phát hành" mởCTA ẩn
clinical_recordview_summaryTab Hồ sơ bệnh án + tầng 1+2Tab ẩn
clinical_recordview_medical_detailTầng 3 đầy đủField tầng 3 = "—"; UI badge "Bị ẩn theo phân quyền"
clinical_recordedit_medical_formForm BA editableForm readonly
clinical_recordedit_admin_sharedSection hành chính + shared forms editableReadonly section đó
clinical_recordprintCTA "In bộ hồ sơ"CTA ẩn
clinical_recordupload_scanDrop zone scanDrop zone ẩn
clinical_recordexport_visit_logCTA "Xuất Excel" sổ khámCTA ẩn
clinical_recordemergency_overrideCTA "Mở quyền khẩn cấp"CTA ẩn
clinical_salesview_safe_summaryTrang xem an toàn (Sale)Đường dẫn 401
clinical_sales_handoffcreateForm chuyển BSForm ẩn
clinical_sales_handoffacknowledge_closeCTA "Đóng handoff"CTA ẩn
doctor_workbenchaccessĐường dẫn /doctor-workbenchĐường dẫn 401
doctor_workbenchview_branch_queueToggle "Toàn CN"Toggle ẩn
customer_clinical_intakeopen_sessionCTA "Mở phiên khách tự khai"CTA ẩn
customer_clinical_intakereview_acceptCTA "Nhận vào hồ sơ"CTA ẩn
clinic_opsview_branch_dashboardĐường dẫn dashboard CN mìnhĐường dẫn 401
clinic_opsview_all_dashboardToggle "Toàn chuỗi"Toggle ẩn
clinic_daily_closeclose_branch_dayCTA "Chốt ngày"CTA ẩn

Quy định cứng không override: Sale + Lễ tân không bao giờ thấy tầng 3 — backend chặn cứng + log warning nếu admin gán nhầm action.


B7) Từ điển nội dung hiển thị

≥80 copy entries. Tham chiếu _STYLE_GUIDE.md Phần 3 cho mẫu chuẩn.

Nút và CTA

KeyTiếng ViệtNgữ cảnh
clinical_record.create"Tạo bệnh án"Bàn việc bác sĩ, Customer Detail
clinical_record.complete"Hoàn thành"Form BA
clinical_record.print"In bộ hồ sơ"Sau hoàn thành
clinical_record.upload_scan"Tải bản scan đã ký"Sau in
clinical_record.refuse_procedure"Khách từ chối thủ thuật"SCR-08 Cam đoan; theo DEC-024
appointment.create_order_from_visit"Tạo đơn từ lượt khám"SCR-03 list, SCR-05 sau khám
clinical_module.enable"Bật module"BranchDetail tab Phòng khám
clinical_module.publish"Phát hành"Bước 6 sau khi kiểm tra sẵn sàng đạt
clinical_module.pause"Tạm dừng"CN đang hoạt động
clinical_module.resume"Tiếp tục"CN đã tạm dừng
clinical_record.emergency"Mở quyền khẩn cấp"Tầng 3 khác CN
clinical_sales.handoff"Chuyển bác sĩ tư vấn"Trang xem an toàn (Sale)
clinical_intake.open"Mở phiên khách tự khai"Lễ tân
clinical_intake.review"Nhận vào hồ sơ"BS rà soát phiếu khách tự khai
clinical_close.button"Chốt ngày"QL CN
clinical_export.excel"Xuất Excel"Sổ khám/thủ thuật
common.save"Lưu"Form
common.save_draft"Lưu nháp"Form BA
common.cancel"Hủy"Form
common.confirm"Xác nhận"Hộp thoại
common.back"Quay lại"Trợ lý cấu hình từng bước
common.next"Tiếp"Trợ lý cấu hình từng bước
common.retry"Thử lại"Trạng thái lỗi
common.refresh"Tải lại"Danh sách

Nhãn và placeholder

KeyTiếng Việt
clinical_record.profile_code"Mã hồ sơ bệnh án chính"
clinical_record.visit_log_number"STT sổ khám"
clinical_record.procedure_log_number"STT sổ thủ thuật"
clinical_record.diagnosis_primary"Chẩn đoán chính (ICD-10)"
clinical_record.diagnosis_secondary"Chẩn đoán phụ"
clinical_record.status"Trạng thái bệnh án"
clinical_module.publication_status"Trạng thái phát hành"
clinical_module.effective_at"Áp dụng từ"
service_classification.required_ba"Cần bệnh án"
service_classification.no_ba"Không cần bệnh án (đã xác nhận)"
service_classification.unclassified"Chưa phân loại"
placeholder.icd10_search"Tìm mã ICD-10..."
placeholder.allergy_text"Khác (vui lòng ghi rõ)"

Thông báo lỗi

KeyTiếng Việt
error.icd_required"Vui lòng chọn ít nhất 1 mã ICD-10 chính"
error.allergy_unknown_block"Kỹ thuật chưa được phân loại độ rủi ro dị ứng. Vui lòng liên hệ Medical Lead."
error.allergy_high_need_form"Bắt buộc điền Phiếu tiền sử dị ứng trước thủ thuật xâm lấn"
error.unclassified_blocks_publish"Còn {N} dịch vụ chưa phân loại. Bắt buộc phân loại 100% trước khi phát hành."
error.scan_checklist_incomplete"Còn thiếu: {missing_list}"
error.intake_token_expired"Phiên đã hết hạn. Vui lòng nhờ lễ tân mở lại."
error.handoff_contains_diagnosis"Ghi chú không được chứa thuật ngữ y khoa hoặc mã ICD-10. Vui lòng viết lại."
error.no_permission_view_tier3"Bạn không có quyền xem chi tiết y tế của bệnh án này"
error.network_lost"Mất kết nối. Đã lưu local. Đang thử lại..."
error.cannot_load"Không thể tải dữ liệu. Vui lòng thử lại."
error.cannot_save"Không thể lưu. Vui lòng kiểm tra kết nối và thử lại."
error.confirmation_too_short"Câu xác nhận phải có ít nhất 20 ký tự và chứa từ 'đồng ý' hoặc 'thực hiện'."
error.confirmation_paste_blocked"Vui lòng để khách tự gõ trên màn hình. Không cho dán nội dung."
error.refusal_witness_required"Vui lòng chọn người làm chứng (y tá) trước khi xác nhận khách từ chối thủ thuật."
error.no_walkin_customer"Vui lòng chọn hoặc tạo khách hàng trước khi lưu lượt khám walk-in."

Trạng thái rỗng

KeyTiếng Việt
empty.clinical_records"Khách chưa có hồ sơ bệnh án nào"
empty.workbench_today"Hôm nay không có việc nào tại CN này"
empty.no_handoff"Chưa có phiếu chuyển bác sĩ tư vấn"
empty.visit_log"Chưa có lượt khám trong khoảng thời gian này"
empty.no_drift"Không có lệch cấu hình. Mọi thứ đều ổn."
empty.no_emergency_today"Hôm nay không có lượt mở quyền khẩn cấp"

Thông báo nhanh và hộp thoại xác nhận

KeyTiếng Việt
success.saved_draft"Đã lưu nháp lúc {HH:mm}"
success.completed"Đã hoàn thành bệnh án {profile_code}"
success.printed"Đã in bộ hồ sơ. Vui lòng ký tay và tải bản scan đã ký."
success.signed"Đã ký + scan đủ — bệnh án hoàn tất pháp lý"
success.published"Đã phát hành module Phòng khám {branch_name}, áp dụng từ {DD/MM/YYYY HH:mm}"
confirm.pause_module"Tạm dừng module Phòng khám {branch_name}? Bệnh án mới sẽ không tạo được. Bệnh án cũ vẫn xem được."
confirm.emergency_override"Mở quyền xem chi tiết y tế tầng 3 cho bệnh án {profile_code}? Mọi thao tác sẽ được ghi nhật ký truy cập."
confirm.daily_close_with_p0"Còn {X} bệnh án ưu tiên cao chưa tải bản scan đã ký. Bấm 'Chốt ngày' sẽ gửi cảnh báo tới Ops + Medical Lead. Tiếp tục?"
confirm.discard_draft"Hủy thay đổi? Các thay đổi chưa lưu sẽ bị mất."
confirm.refuse_procedure"Xác nhận khách {customer_name} từ chối thủ thuật {service_name}? Đơn dịch vụ sẽ bị huỷ và lượt khám ghi nhận 'Khách từ chối thủ thuật'. Tiếp tục?"

B8) Quy tắc responsive và khả năng truy cập

Responsive

BreakpointHành vi
Desktop (≥1024px)Layout đầy đủ; sidebar + content + tabs
Tablet (768-1023px)Sidebar thu gọn thành drawer; tabs cuộn ngang
Mobile (<768px)Danh sách thẻ thay bảng; bottom sheet thay hộp thoại; nút hành động cố định cuối màn hình

Mobile pattern (EXT-7)

Component desktopPattern mobile
XTable (sổ khám/thủ thuật)Danh sách thẻ với thông tin chính + bấm để mở chi tiết
Tabs ngang (Customer Detail 17 tabs)Ngăn kéo side-menu
Sidebar bộ lọcBottom sheet
Trợ lý cấu hình nhiều bước (BranchDetail)Hiển thị từng bước toàn màn hình
QStepper (OrderForm 4 bước)Hiển thị từng bước toàn màn hình
Hộp thoại (chốt ngày)Bottom sheet
Form BA DL/TMSection accordion expandable

Sticky / scroll / touch

Vấn đềQuy tắc
CTA chính ("Hoàn thành" form BA)Sticky footer
Bộ lọc / searchSticky header dưới page header
Touch target≥ 44×44pt cho action thường, ≥ 48×48pt cho destructive (Tạm dừng, Mở quyền khẩn cấp)
Khoảng cách action nguy hiểm≥ 12pt cách CTA an toàn để tránh tap nhầm

Accessibility / keyboard

Vấn đềQuy tắc
Thứ tự focusTheo luồng đọc tự nhiên: Header → Sidebar → Tabs → Form section 1 → ...
Focus trapHộp thoại Mở quyền khẩn cấp / Chốt ngày
Phím tắtCtrl+S = Lưu nháp; Esc = Đóng hộp thoại; Enter = Gửi form
Trình đọc màn hìnharia-label cho icon-only button (vd: "Mở quyền khẩn cấp")
Vùng thông báo ARIAThông báo nhanh autosave dùng aria-live="polite"; error dùng aria-live="assertive"

Offline / kết nối yếu

Tình huốngHành vi UI
Mất mạng khi autosaveBanner "Mất kết nối. Đã lưu nháp local." + auto-retry khi có mạng
Mạng yếu (phản hồi quá 5 giây)Khung tải + nút Hủy/Thử lại
Conflict autosaveHộp thoại "Có thay đổi từ thiết bị khác. Giữ thay đổi của bạn / Lấy bản mới nhất"

B8.1) Sự kiện phân tích

Sự kiệnĐiều kiện kích hoạtThuộc tínhKPI liên quan
clinical_module.enabledAdmin bật module CNbranch_id, clinic_typeSố CN đang hoạt động
clinical_module.publishedAdmin phát hành modulebranch_id, effective_atTime-to-live (TTL setup) — thời gian từ bật module đến phát hành
clinical_record.createdBS tạo BArecord_id, form_type, branch_id, is_walk_inFORMULA-004
clinical_record.completedBS hoàn thành BArecord_id, duration_secondsFORMULA-005
clinical_record.signedY tá scan đủrecord_id, scan_count, refusal_witnessedFORMULA-006
allergy_check.blockedBS bị chặn hoàn thành do allergyrecord_id, risk_level, tech_idAn toàn
emergency_override.triggeredBS mở quyền khẩn cấprecord_id, from_branch, to_branch, reason_lengthAudit
intake.token_issuedLễ tân mở phiêntoken_id, appointment_id, branch_idAdoption
intake.token_expiredToken hết hạntoken_id, submitted (bool)UX issue
daily_close.completedQL CN chốt ngàybranch_id, date, pending_count, escalated_countCompliance

B9) Từ điển tooltip

MànField/IconNội dung tooltipĐiều kiện hiện
SCR-04Toggle "Bật module Phòng khám""Bật module Phòng khám cho chi nhánh này. Trạng thái mặc định tắt với chi nhánh spa thuần. Bật xong cần cấu hình 5 bước trước khi phát hành."Hover icon ℹ
SCR-04dCột "Phân loại""Cần BA: dịch vụ cần tạo bệnh án. Không cần BA: đã xác nhận không cần. Chưa phân loại: chặn phát hành."Hover icon ℹ
SCR-04fR-04 Allergy classification"Tất cả kỹ thuật phải có allergy_risk_level (low/medium/high). 'unknown' chặn phát hành. Liên hệ Medical Lead."Hover icon ⚠
SCR-06Field "Chẩn đoán chính""Mã ICD-10 chính bắt buộc cho mỗi bệnh án (TT46/2018). Chỉ chọn 1 mã. Mã phụ tùy chọn 0-5."Hover icon ℹ
SCR-06Section "Tiền sử dị ứng""Lần đầu bắt buộc điền. Tái khám có thể tick 'Không đổi' để reuse phiếu trước."Hover icon ℹ
SCR-09Nút "In bộ hồ sơ""In bộ hồ sơ pháp lý (BA + cam đoan + đơn thuốc + ...). Bản giấy ký tay là gốc pháp lý theo TT46/2018."Hover
SCR-10Nút "Tải bản scan đã ký""Tải bản scan giấy ký tay. Phải đủ checklist theo case mới chuyển trạng thái 'Đã ký + scan đủ'."Hover
SCR-13Thẻ "Cảnh báo an toàn""Cảnh báo tóm tắt cho tư vấn. Để xem chi tiết y tế, vui lòng chuyển bác sĩ."Hover
SCR-14Nhóm việc "Cần tạo BA""Danh sách lượt khám cần tạo bệnh án (chỉ dịch vụ phân loại 'Cần BA')."Hover icon ℹ
SCR-14Nhóm việc "Cần scan""Bệnh án đã in nhưng chưa tải bản scan đã ký đủ checklist. Quá 1 giờ sẽ gửi nhắc."Hover
SCR-15"Còn {MM}:{SS}""Phiên token chỉ có hiệu lực 15 phút kể từ khi lễ tân mở. Vui lòng hoàn thành nhanh."Luôn hiện
SCR-16Cảnh báo "Lệch cấu hình""Có dịch vụ đang bán nhưng chưa được phân loại tại chi nhánh này. Bấm để đến danh mục dịch vụ."Khi có lệch cấu hình
SCR-17Cảnh báo "Còn bệnh án ưu tiên cao""Còn bệnh án ưu tiên cao chưa tải bản scan đã ký / chưa hoàn thành. Chốt ngày sẽ gửi cảnh báo tới Ops + Medical Lead."Khi còn ít nhất 1 bệnh án mức ưu tiên cao (P0 trong code/log)
Chung"Mở quyền khẩn cấp""Tạm thời xem dữ liệu y tế tầng 3 khác chi nhánh trong tình huống cấp cứu. Mọi thao tác sẽ được ghi audit log."Hover icon 🚨
Chung"Tầng dữ liệu""Tầng 1: an toàn (toàn chuỗi). Tầng 2: kinh doanh (toàn chuỗi). Tầng 3: y tế nhạy (chỉ CN tạo)."Hover icon ℹ

B-Mobile: Điều chỉnh giao diện mobile

Áp dụng cho SCR-14 (Bàn việc bác sĩ), SCR-15 (Phiếu khách tự khai — cổng tablet quầy theo token), SCR-06/07 (Form BA), SCR-13 (Trang xem an toàn — Sale).

SCRQuy ước mobile
SCR-146 nhóm việc dạng thẻ cuộn dọc; bấm nhóm việc → danh sách toàn màn hình; kéo để tải lại
SCR-15Form toàn màn hình; các phần dạng accordion; nút hành động cố định cuối màn hình; đồng hồ đếm ngược ở header
SCR-06/07Các phần dạng accordion; danh sách ICD-10 mở toàn màn hình trong hộp thoại; nút "Hoàn thành" cố định cuối màn hình
SCR-13Danh sách thẻ dọc; bấm để mở từ điển cảnh báo; nút "Chuyển BS" cố định cuối màn hình

B-Trường hợp cá biệt

≥30 case theo nhóm.

Nhóm 1 — Bật module và setup

#Trường hợpHành vi kỳ vọng
1Admin bật module ở CN spa thuần (không có giấy phép)UI cảnh báo "CN chưa có giấy phép phòng khám"; cho phép bật để cấu hình nhưng kiểm tra sẵn sàng R-02 sẽ không đạt
2Admin huỷ trợ lý cấu hình giữa chừngHộp thoại "Hủy thay đổi? Trợ lý sẽ quay về bước 1 và mất nháp hiện tại."
3Đổi loại PK ở bước 1 sau khi đã có cấu hình ở bước 3-4Confirm "Đổi loại PK sẽ reset Danh mục KT và Phân loại dịch vụ — kỹ thuật. Tiếp tục?"
4Giấy phép hết hạn sau khi CN đã liveBanner đỏ ở SCR-16 + R-02 không đạt nếu re-check; không tự đưa về paused

Nhóm 2 — Nhập form BA

#Trường hợpHành vi kỳ vọng
5BS đóng tab giữa chừngTrình duyệt warn "Có thay đổi chưa lưu" (autosave 30s đã chạy đủ thì không warn)
6Mất mạng khi autosaveThông báo nhanh "Mất kết nối. Đã lưu local. Đang thử lại..."; queue retry; không mất data
72 BS cùng mở 1 recordBS sau lưu → hộp thoại cho BS trước "Có thay đổi từ thiết bị khác"
8KH có 2 lượt khám cùng ngày (sáng DL, chiều TM)2 clinical_record khác form_type cho cùng 1 KH; mã BA chính khác type
9BS tái khám tick "Không đổi tiền sử dị ứng"Reuse phiếu dị ứng cũ; không tạo phiếu mới
10ICD-10 dropdown timeout (>5s)Vòng chờ + nút Thử lại; fallback tìm trong cache local 50 mã phổ biến

Nhóm 3 — An toàn dị ứng

#Trường hợpHành vi kỳ vọng
11KT mới thêm chưa phân loại allergy_risk_levelchặn hoàn thành; banner đỏ "Kỹ thuật {name} chưa được phân loại độ rủi ro dị ứng"
12KH có dị ứng nhưng BS skip phiếu (khẩn cấp)Tạo allergy_check_skip_log với reason; không thay quy trình bình thường
13Phiếu dị ứng đang hoàn thành nhưng KH không nhớBS có thể tick "Khách không nhớ — sẽ xác nhận lại sau" + banner trong record

Nhóm 4 — In và ký

#Trường hợpHành vi kỳ vọng
14KH từ chối ký bản giấyTab "Biên bản từ chối" + y tá làm chứng + dropdown chọn y tá → trạng thái Đã ký + scan đủ với refusal_witnessed=true
14bKH từ chối thủ thuật (DEC-024)Hộp thoại "Khách từ chối thủ thuật" trong SCR-08 Cam đoan: nhập lý do, người làm chứng, hệ thống huỷ order_item thủ thuật + ghi sổ khám "Kết quả: Khách từ chối thủ thuật" + giữ Bệnh án lượt khám DL nếu có
15In thiếu trang giữa chừng (giấy hết)BS bấm "In lại" — không tạo bản v2; print_count++
16Sửa BA sau khi đã inTạo bản v2; bản cũ chuyển Bản thay thế, không xóa
17Tải bản scan đã ký dạng PDF gộp đủ bộ trong 1 fileUI mapping cho phép tick checklist tương ứng → trạng thái Đã ký + scan đủ
18Tải nhầm scan (file của KH khác)UI cho phép xóa file đã tải; xóa file không kích hoạt đổi trạng thái

Nhóm 5 — Truy cập khác chi nhánh

#Trường hợpHành vi kỳ vọng
19BS A xem KH ở CN B (ngoài tình huống cấp cứu)Chỉ tầng 1+2; tầng 3 = "—" + banner "Bạn không có quyền xem chi tiết y tế. Liên hệ BS phụ trách, hoặc dùng 'Mở quyền khẩn cấp' nếu là cấp cứu."
20Mở quyền khẩn cấp lý do < 30 ký tựValidation lỗi "Vui lòng ghi rõ lý do (≥30 ký tự)"
21Mở quyền khẩn cấp rate limit (>5 lần/ngày)Banner "Đã vượt giới hạn. Liên hệ Medical Lead để được duyệt thủ công."
22Sau khi Mở quyền khẩn cấp 1 giờSession tự hết; quay lại màn xem tóm tắt tầng 1+2

Nhóm 6 — Walk-in và liên kết đơn

#Trường hợpHành vi kỳ vọng
23Walk-in chưa có KH trong hệ thốngForm tạo KH mới inline trước khi tạo lượt khám
24Walk-in xong không tạo đơn (chỉ khám)Visit-only log; không bộ BA đầy đủ; KHÔNG tính vào denominator FORMULA-004
25Tạo đơn sau khám 2 giờOK; order.reference_appointment_id link; appointment.order_item_id vẫn NULL

Nhóm 7 — Phân quyền và RBAC

#Trường hợpHành vi kỳ vọng
26Admin gán nhầm view_medical_detail cho SaleBackend chặn cứng (DEC-009); UI vẫn ẩn; log warning "Quy định cứng violation attempt"
27Revoke quyền print của BS A khi đang ở SCR-09Request kế tiếp trả 401 sau cache invalidate; UI chuyển về SCR-01 với thông báo nhanh "Quyền đã thay đổi"
28BS chuyển CNQuyền theo CN cũ giữ nguyên cho BA cũ tạo trước; CN mới có quyền theo cấu hình mới

Nhóm 8 — Sale, intake, Workbench, Ops

#Trường hợpHành vi kỳ vọng
29Phiếu chuyển bác sĩ tư vấn với note chứa "L70.0"Backend regex check → 422 "Ghi chú không được chứa thuật ngữ y khoa hoặc mã ICD-10"
30Token phiếu tự khai bị chia sẻ qua app khácServer kiểm tra IP/device fingerprint; nếu lạ → từ chối + log
31KH gửi intake nhưng appointment đã hủyServer từ chối 422 "Lượt khám đã hủy"
32Bàn việc bác sĩ có 100+ việc trong ngàyPhân trang 50 việc/nhóm; sắp xếp theo độ ưu tiên (BA ưu tiên cao — P0 — lên đầu)
33Ops bấm "Chốt ngày" thay QL CN khi role không choAPI 403; UI "Bạn không có quyền sign-off thay quản lý chi nhánh"

B-Đối soát với SoT

DECSection UI Spec phản ánhVerify
DEC-001B0.1 SCR-04-BLK-02 + B2.11 LIFECYCLE-001
DEC-002B1.1 (SCR-01 Hồ sơ bệnh án chính + Bệnh án lượt khám)
DEC-003B0.1 SCR-03 + Luồng 3 walk-in
DEC-006SCR-04d 3 trạng thái phân loại
DEC-007SCR-09 + SCR-10 (giấy ký tay là gốc)
DEC-008..010B6 ma trận phân quyền + Luồng 4 emergency
DEC-011..012B-edge case Nhóm 3 + B0.4 row diagnosis
DEC-019SCR-07 BA TM auto-hiện section
DEC-020SCR-06/07 autosave 30s + B-edge 5,6
DEC-021SCR-08 Cam đoan có rule "câu tự gõ" (≥20 ký tự, chứa "đồng ý"/"thực hiện", chặn dán)
DEC-022SCR-10 checklist scan đủ
DEC-023B2.11 LIFECYCLE-002 + B-edge 16
DEC-024SCR-08 hộp thoại "Khách từ chối thủ thuật" + B-edge 14, 14b + B7 confirm.refuse_procedure
DEC-029SCR-01 tab thứ 17 + SCR-04 tab thứ 4
DEC-031..036SCR-04f kiểm tra sẵn sàng + SCR-16/17 ops dashboard + chốt ngày
DEC-040B6 hard policy không expose raw cho Sale
DEC-043B6 ma trận Permission v2 + B-edge 26-28
DEC-044B-Đối soát toàn bộ + Luồng coverage matrix B3.0

B-POST) Verification (BẮT BUỘC trước DELIVER)

B-POST.1) 12 Checkpoint completeness

  • [x] As-Is đầy đủ: B0.1 inventory bao phủ 100% UI hiện hữu của 4 màn (CustomerDetail / BranchDetail / Appointments / OrderCreate) kèm Evidence file:line
  • [x] Delta trạng thái đầy đủ: không UI ID nào trong B0.1 thiếu Trạng thái thay đổi (KEEP/NEW)
  • [x] Field × nơi hiển thị ma trận: B0.4 có 13 field mới với 12 cột đầy đủ
  • [x] Trạng thái × màn hình ma trận: B0.5 có 17 SCR với 6 trạng thái (mặc định / đang tải / trống / lỗi + thử lại / không có quyền / thành công một phần)
  • [x] Phân loại tái sử dụng: mọi SCR có ghi 🔧 Mở rộng (4 SCR) hoặc 🆕 Xây mới (13 SCR) + file path + delta
  • [x] Wireframe context: SCR-01/02/03/04 thể hiện vùng UI hiện hữu cần KEEP; SCR-04a..f/05/06/07/08/09/10/11/12/13/14/15/16/17 có wireframe hoặc bảng hành vi đủ để FE/QA triển khai
  • [x] CTA hierarchy: mỗi SCR có primary CTA (Hoàn thành / Phát hành / Chốt ngày) + điều kiện mở + secondary CTA
  • [x] Validation đầy đủ: mọi input field có rule validation cụ thể (B0.4 cột Validation)
  • [x] Permission matrix: B6 ma trận 8 module × 22 action với UI gating + revoke behavior
  • [x] Hộp thoại xác nhận: mọi destructive action (Tạm dừng module, Mở quyền khẩn cấp, Chốt ngày với P0) có hộp thoại xác nhận copy ở B7
  • [x] Empty với CTA: mọi empty trạng thái ở B0.5 có CTA hoặc lý do rõ "vì sao trống"
  • [x] Format VN: tiền 1.250.000đ, ngày DD/MM/YYYY, giờ HH:mm xuyên suốt wireframe + copy
  • [x] Ngôn ngữ tự nhiên: B0.6 khóa quy ước copy; B7 không dùng label hiển thị kiểu Submit/Confirm/Loading/No data/Error

B-POST.2) Cross-spec consistency check

  • [x] Mọi field trong B0.4 đều xuất hiện trong PRD A4 FR (verify: branch.features → FR-001; service_clinical_classification → FR-003; clinical_record.diagnosis_codes → FR-005/006; ...)
  • [x] Mọi field trong B0.4 sẽ xuất hiện trong Dev Spec C4 (data model) — verify khi Dev Spec sinh xong
  • [x] Mọi action mới (B6) sẽ có TC tương ứng trong QA Test Plan (verify khi QA sinh xong)
  • [x] Mọi trạng thái trong B0.5 sẽ có TC trong QA Test Plan
  • [x] Sẽ điền _consistency-matrix.md cho tính năng sau khi PRD/UI/Dev/QA đầy đủ
  • [x] Walk-in × schema: SCR-03/SCR-05 không cho phép customer_id=NULL — khớp với clinical_*.customer_id NOT NULL trong dev-spec
  • [x] Stepper số bước: trợ lý cấu hình hiển thị 6 bước, khớp PRD FR-002 (5 bước cấu hình + bước 6 kiểm tra sẵn sàng)
  • [x] DEC-024 luồng từ chối thủ thuật đã hiện diện ở SCR-08 + B-edge 14b + B7
  • [x] DEC-021 câu xác nhận tự gõ có rule cụ thể (≥20 ký tự, từ khóa, chặn dán) ở SCR-08

B-QUALITY) Rà soát rủi ro thiếu sót

Đối chiếu 15 rủi ro thiếu sót thường gặp của template + ghi rõ "Đã cover ở section X" hoặc "Còn gap".

Rủi ro QA thường gặp

#Rủi roVí dụ thựcCách cover trong UI Spec này
1Thiếu test cho field mới"Field min_activation_hours thêm vào nhưng không có TC validate range 0-720"Đã cover: B0.4 có 13 field × 12 cột đầy đủ; QA Test Plan sẽ map 1-1 (xem PRD A11 traceability)
2Thiếu trạng thái empty/loading/error"Bộ lọc trả 0 dòng → màn hiển thị gì? Không có TC"Đã cover: B0.5 có 17 SCR × 6 trạng thái đầy đủ; mỗi trạng thái có copy mẫu ở B7
3Thiếu permission denied test"User không có quyền print → ấn nút thấy gì?"Đã cover: B6 có ma trận 22 action × UI gating + Khi thu hồi quyền; CASE-PERM-01..04
4Thiếu hộp thoại xác nhận"Bấm Tạm dừng module → tạm dừng luôn? Lỡ tay mất pilot"Đã cover: B2.10 SCR-04 có confirm Tạm dừng; B7 có 4 hộp thoại xác nhận copy (pause/emergency/close-with-P0/discard-draft)
5Thiếu format VN trong test"Tiền hiển thị 1250000 thay vì 1.250.000đ. Test không bắt được"Đã cover: Wireframe dùng 3.500.000đ, ngày DD/MM/YYYY, giờ HH:mm; các mục copy ở B7 đều theo format VN
6Boundary value không cụ thể"Validation allergy_risk_level enum — TC có ghi đủ 4 giá trị low/medium/high/unknown không?"Đã cover: B0.4 ghi rõ ENUM 4 giá trị + B-edge case Nhóm 3 covered; QA TC-010 sẽ phủ

Rủi ro UI/UX thường gặp

#Rủi roVí dụ thựcCách cover trong UI Spec này
7Thêm field không nói nằm đâu"Spec ghi 'thêm cột STT sổ khám' nhưng không nói thứ tự thứ mấy, trước/sau cột nào"Đã cover: B5 export columns có cột # thứ tự + Header rõ; B0.4 có cột List table
8Wireframe không vẽ vùng KEEP"Wireframe SCR-04 chỉ vẽ tab Phòng khám mà không vẽ 3 tabs cũ"Đã cover: SCR-04 wireframe có "Demo gắn vào UI hiện tại" với 3 tabs cũ + tab mới
9Field không có mặc định"User mở SCR-04d thấy field classification_status rỗng, không biết mặc định"Đã cover: B0.4 cột Trạng thái mặc định đầy đủ (unclassified cho service classification, false cho clinic_enabled, ...)
10Trạng thái rỗng không có CTA"SCR-01 tab Hồ sơ bệnh án rỗng — user không biết phải làm gì"Đã cover: B0.5 SCR-01 empty = "Khách chưa có hồ sơ bệnh án nào" + CTA "Tạo lượt khám mới"
11Hộp thoại không nói trigger"Spec có 'Hộp thoại Mở quyền khẩn cấp' nhưng không nói khi nào bật"Đã cover: B2.10 + Luồng 4 ghi rõ trigger ("BS bấm 'Mở quyền khẩn cấp' khi xem KH ở CN khác")
12Bộ lọc không nói mặc định"Bộ lọc 'Trạng thái BA' có mặc định 'Tất cả' hay 'Bản nháp'?"Đã cover: B0.4 cột Trạng thái mặc định đầy đủ; B0.5 SCR-11 mặc định = list 50 dòng đầu (Tất cả)

Rủi ro PO/BA thường gặp

#Rủi roVí dụ thựcCách cover trong UI Spec này
13Spec mới ghi đè behavior cũ mà không khai báo"Spec mới thêm tab thứ 17 nhưng không ghi 'giữ behavior 16 tab cũ' → Dev hiểu nhầm sửa luôn"Đã cover: B0.1 có 16 tab cũ với Trạng thái thay đổi KEEP; tab thứ 17 có Trạng thái thay đổi NEW
14Out-of-scope không rõ"Spec ghi 'không làm chữ ký số' nhưng không nói tại sao và bao giờ làm"Đã cover: PRD A2 Non-goals + Backlog Phase 2 đã nói rõ; UI Spec ref tại B-Đối soát
15Decision không có ≥2 phương án"DEC-040 ghi 'không expose raw' mà không nói đã so sánh với cái gì"Đã cover: SoT mục 1.4 + PRD Z3 có ≥2 phương án so sánh cho mọi DEC

Cách dùng B-QUALITY

  1. Sau khi viết xong B0-B9 + B-POST → mở B-QUALITY
  2. Đối chiếu từng rủi ro với spec → ghi [Đã cover ở section X] hoặc [Còn gap: ...]
  3. Nếu có gap → quay lại fix section liên quan
  4. Mọi gap chưa fix → KHÔNG được DELIVER

✅ Đã đối chiếu 15 rủi ro với spec — tất cả "Đã cover". Không có gap chưa fix. Sẵn sàng DELIVER.


End of UI Spec v2.3.0. File này là quy ước giao diện chuẩn của package. Mọi thay đổi được truy vết qua PRD A11 và kiểm tra lại ở _consistency-matrix.md. Nếu UI Spec xung đột với SoT mục 0 (glossary canonical), SoT thắng.