Module · WS hub trao đổi sát hạch · 13/7/2026

sh-exchange — Trao đổi báo cáo sát hạch CSĐT ↔ PC08 MVP Painkiller NEW

Số hoá vòng khứ hồi thủ công với PC08: BC1 · BC2 (+công văn, DS hợp lệ, biên bản) đi — KQBC2 · SBD · tình trạng · SAT_HACH về. Giải 4 cái đau của Vĩnh An: kho file có cấu trúc · trạng thái vòng · đối soát tự động (582 hồ sơ đang soát bằng mắt) · lưu vết thanh tra. P1 không sinh XML — FPT vẫn là nguồn; sinh XML là P3 (module report phía WS trung tâm).

⚠️ Chưa có trong code — scaffold mới (store module opengate-app-sh-exchange). Nguồn nghiệp vụ: bộ hồ sơ ô tô thật 23–29/06/2026 (BC/FILE BC OTO/). Spec UI: màn hình tham khảo (4 màn).
1

Vị trí kiến trúc — WS hub riêng, center-aware

PC08 là đầu mối N trung tâm ↔ 1 PC08 → module nằm ở workspace hub riêng, không thuộc WS đào tạo của trung tâm nào. Vĩnh An là center đầu tiên; chạy đủ giá trị khi mới 1 center và PC08 chưa tham gia (CSĐT upload cả 2 chiều).

WS "trao-doi-sat-hach" (hub) ├─ center: 40023 Vĩnh An · 400xx TT khác… ← mọi BO gắn center_id ├─ batch / file / entry (vòng khứ hồi) ├─ Thành viên: NV các CSĐT (1 account join nhiều WS — CP membership) │ → data scope: CHỈ thấy center của mình │ (tương lai) cán bộ PC08 → thấy mọi center, trả file lên hub └─ P3: WS trung tâm (module report) sinh XML ──push API──▶ hub
sh-exchange (doc này)reportsh-gateway
PhíaCSĐT ↔ PC08 (file XML/xlsx đợt SH)CSĐT → Sở XD (sinh báo cáo theo mẫu)TT sát hạch → Cục CSGT (API QCVN 40)
WShub trao đổiWS trung tâmWS sát hạch (v3)
Nguồn dữ liệufile upload (P1) / API từ WS trung tâm (P3)student/course/dat cùng DBthiết bị chấm thi
2

Feature / BO / Action

FeatureBO chínhAction
centerTrung tâm đào tạo (CSĐT tham gia hub)viewcreateedit
batchĐợt sát hạch — 1 vòng khứ hồi với PC08viewcreateeditclosedelete
fileFile trao đổi (immutable, 2 chiều)viewuploaddownloaddelete
entryHồ sơ thí sinh trong đợt (parse từ XML)viewexport

Đối soát là màn hình của batch (đọc entry), không cần feature riêng.

3

Dữ liệu chính (mọi bảng có center_id)

BO · bảngTrường chính
Trung tâm
shx_center
Mã CSĐT (MA_CSDT=40023) · tên · mã cơ quan tỉnh (MA_SO_GTVT=40, legacy) · trạng thái
Đợt sát hạch
shx_batch
center_id · mã kỳ MA_KY_SH (điền khi KQ về) · ngày thi dự kiến/thực tế · các khóa trong đợt (shx_batch_khoa: mã khóa, hạng, số HS) · trạng thái vòng · số công văn (694/706)
File trao đổi
shx_file
batch_id · loại (BC1·BC2·CONG_VAN·DS_HOP_LE·BIEN_BAN·KQBC2·SBD·TINH_TRANG·SAT_HACH) · hướng (di/ve) · file gốc immutable (xml/zip/xlsx/docx/pdf) · kết quả parse jsonb (đã strip ảnh base64) · trạng thái parse · người upload + thời điểm
Hồ sơ trong đợt
shx_entry
batch_id · MA_DK+SO_HO_SO (khóa khớp xuyên suốt) · họ tên/ngày sinh/CCCD · khóa/hạng · trạng thái · KQ duyệt (KQ_BC2=1 hợp lệ · lý do từ chối) · SBD/lần SH · KQ thi (DA/RO + điểm L·M·H·Đ + nhận xét) · số GPLX/QĐ trúng tuyển
4

Máy trạng thái

Đợt chuan_bi → da_gui (BC2+phụ lục) → da_duyet (KQBC2 về) → co_sbd → da_thi → co_ket_qua → dong (BC1 gắn mức KHÓA, upload bất kỳ lúc — không chặn vòng) Hồ sơ de_nghi → hop_le | tu_choi(lý do) → co_sbd → dat | rot (+điểm, SO_GPLX)

Trạng thái đợt suy ra từ file đã nhận (upload KQBC2 → tự chuyển da_duyet), cho phép sửa tay khi lệch.

5

Quy tắc nghiệp vụ · lộ trình · liên kết

Quy tắc nghiệp vụ

  • File đã upload không sửa/ghi đè — sai thì upload bản mới, bản cũ giữ vết (thanh tra)
  • Tự phân loại theo tên file + nội dung, KHÔNG theo root tag — quirk FPT: file BC2_* có root <BAO_CAO1>
  • Parse → khớp qua MA_DK+SO_HO_SO; KQBC2/SAT_HACH chỉ cập nhật entry có sẵn — không khớp → danh sách lệch, không tự tạo
  • Strip ảnh ANH_CHAN_DUNG (base64 .jp2) khỏi parse/preview — file gốc giữ nguyên
  • Giữ nguyên typo schema FPT (HANG_DE_NGHi_SH) — không "sửa cho đúng"
  • Data scope theo center (PII học viên) — tiên quyết khi ≥2 center
  • Mốc cứng DAT −10 · BC2 −7 ngày trước ngày thi → cảnh báo (P2)
  • Mã đơn vị (40023, 40) = cấu hình theo center, không hardcode

Lộ trình

  • P1 — đợt + upload → phân loại → parse → khớp entry · bảng đối soát (gửi/hợp lệ/từ chối+lý do/SBD/đạt‑rớt, highlight lệch) · dashboard đợt · kho file immutable · 1 center
  • P2 — cảnh báo mốc · export đối soát + thống kê đạt‑rớt theo khóa/hạng · sổ đã nộp · data scope multi-center
  • P3 — nhận XML qua API từ WS trung tâm (report sinh BC1/BC2 rồi push) · vai trò PC08 trả file trên hub · ký số

Liên kết chéo · ⚠ câu hỏi mở

  • report (WS trung tâm): P3 sinh XML → push hub; hub trả trạng thái về
  • sh-gateway: khác tuyến — tái dùng schema thông điệp nếu làm phía TT sát hạch
  • catalog: enum hạng · bảng mã KQ_BC2/KET_QUA_SH/L·M·H·Đ
  • CP: membership đa‑WS
  • ⚠ Kênh nhận file thực tế của Nga/Chi (cổng? email? USB?) → UX upload chiều về
  • ⚠ PC08 có tham gia hub? — giá trị bùng nổ khi có; chưa có vẫn chạy
  • ⚠ Ai vận hành WS hub — pháp lý PII nhiều trung tâm
  • ⚠ BC1 gửi đầu khóa hay gộp cùng đợt SH (như bộ 6/2026)?
5b

Onboard trung tâm ngoài Vĩnh An (multi-center · chốt 17/7)

Hub phục vụ nhiều CSĐT. Trung tâm khác vào hệ thống → KHÔNG web upload riêng; cho họ đăng nhập chính hub để vừa upload vừa xem trạng thái/đối soát của mình. PC08 tự onboard trong màn Quản lý trung tâm.

PC08 → Quản lý trung tâm → dòng center 400xx → "Mời trung tâm" → hub gọi CP tạo invitation { username: "400xx" (= mã CSDT), email (nếu có), TTL 7 ngày } → hiện link + copy → PC08 gửi link qua ZALO cho người đại diện trung tâm → trung tâm mở link: đặt tên + mật khẩu → account username = 400xx → login sathach.sunstech.vn → tự nhận ROLE MẶC ĐỊNH của WS (= quyền trung tâm) → shexchange auto-bind center theo username == ma_csdt → chỉ thấy dữ liệu center mình
#Quyết địnhLý do
O1Đăng nhập chung hub (không web riêng)Trung tâm cần xem trạng thái duyệt/đối soát, không chỉ upload mù; không nuôi 2 hệ auth
O2Username = mã CSDT — tài khoản đơn vịĐịnh danh ổn định, khớp ma_csdt trong XML. ⚠ audit ghi "40023 upload" không rõ nhân viên nào — chấp nhận ở quy mô này; sau này mời thêm account cá nhân (shexchange_center_user nhiều‑nhiều sẵn)
O3Role gán theo DEFAULT của WS lúc joinEngine ensureDefaultAssignment sẵn có; role mặc định (workspace-member) = quyền trung tâm (7 quyền): center.view · batch.view · file.view/upload/download · entry.view/export — chỉ dữ liệu của mình. KHÔNG: tạo/sửa/đóng đợt (PC08 tạo đợt gán cho TT), sửa hồ sơ (đính chính=PC08), quản lý/xóa center, xóa file
O4Scope theo center (tiên quyết khi ≥2 center — PII)Binding user↔center; có binding → tự lọc center_id mình; PC08/owner (không binding) → thấy tất cả; auto-bind lần đầu theo username == ma_csdt
O5Link mời an toànBearer token: TTL 7 ngày, one-time, thu hồi/gửi lại trong màn Quản lý trung tâm; gửi đúng Zalo người đại diện

Vòng đời mời (hiện trên màn Quản lý trung tâm): chưa mời → đã gửi link (còn hạn/hết hạn) → đã kích hoạt + copy · thu hồi · gửi lại. Phân biệt P3: onboard này = trung tâm đăng nhập hub upload tay; trung tâm mua OpenGate làm WS đào tạo riêng (như Vĩnh An) thì nâng lên tự push XML qua API (P3, §lộ trình).

6

Ma trận phân quyền (→ manifest & seed role)

Khối permissions[] dán vào manifest.json; bảng dưới là gán quyền theo vai trò của WS hub. Permission key đầy đủ: sh-exchange.exchange.<feature>.<action>.

[ { "group": "exchange", "feature": "center", "label": "Trung tâm đào tạo", "actions": ["view", "create", "edit"] }, { "group": "exchange", "feature": "batch", "label": "Đợt sát hạch", "actions": ["view", "create", "edit", "close", "delete"] }, { "group": "exchange", "feature": "file", "label": "File trao đổi", "actions": ["view", "upload", "download", "delete"] }, { "group": "exchange", "feature": "entry", "label": "Hồ sơ trong đợt", "actions": ["view", "export"] } ]

⚠️ Action đặc thù (upload, close) cần có trong validator manifest — như generate của report.

2 vai trò thực tế (chốt 17/7): PC08 (cơ quan quản lý — toàn quyền, thấy MỌI center) và Trung tâm (role mặc định WS — giới hạn, chỉ thấy center của mình qua scope).

Feature · ActionPC08 (cơ quan quản lý)Trung tâm (mặc định)
center.viewR mọi centerR chỉ của mình
center.create/edit · mời TTW
batch.viewR tất cảR đợt của mình
batch.createW (tạo đợt gán TT)
batch.edit/close/deleteW
file.view/downloadRR của mình
file.uploadW cả 2 chiềuW báo cáo của mình
file.deleteW
entry.view/exportRR của mình
entry.edit (đính chính)W

PC08 = full module (15 quyền). Trung tâm = 7 quyền: center.view · batch.view · file.view/upload/download · entry.view/export. Cách ly chéo bằng binding shexchange_center_user (auto-bind username==ma_csdt); PC08 không binding → thấy tất cả. Đã chốt: PC08 tạo đợt (TT không batch.create); chưa chặn hướng upload.