ข้ามไปที่เนื้อหา

S3 — Activity Report & Course Registration (PRC) — Target Schema (Phase 2)

TARGET DESIGN — ไม่ใช่ schema ปัจจุบัน

ออกแบบใหม่ (greenfield) เพื่อ implement requirement จาก SRS S3 v2.0.0 (TOR 7.13) · ระบบนี้ยังไม่มี DB จริง — de-facto contract คือ demo ar_and_crs/fe/src/data.jsx (11 entity) · 📋 สิ่งที่ต่างจาก demo · DDL เต็ม: schema.sql · ERD · Data Dictionary · 🛠️ Backend Implementation · 🔄 วงจรธุรกิจหลัก (Business Core)

ทำไมต้องออกแบบใหม่ (greenfield)

S3 ไม่มีระบบ legacy ให้ migrate — demo ar_and_crs (React/Vite + NestJS) เก็บข้อมูลเป็น mock array ใน data.jsx (11 entity) เท่านั้น งานนี้คือแปลง demo contract นั้นเป็น clean target schema ระดับ production:

  • normalize array → junctionPROJECTS.courses[]ProjectCourse · MEMBERS.courses[]Enrollment · TRAINERS.specialties[]TrainerSpecialty
  • เพิ่ม FK + audit + workflow ที่ demo ไม่มี — FK referential integrity ครบทุก relation, audit cols (CreatedAt/CreatedBy/UpdatedAt/UpdatedBy), workflow state (TrainerEditRequest, Registration approval, KnowledgeReport flag)
  • polymorphic Attachment — 1 ตารางแนบไฟล์เดียว (OwnerEntityType/OwnerEntityId) ใช้ร่วมทุก entity แทนการแยกตารางแนบไฟล์ต่อ entity
  • thin-mirror authAppUser/RoleAssignment/Role เป็นเงา (mirror) ของ SSO กลาง ไม่เก็บรหัสผ่าน

S3-specific deviation จาก design_p2 D7 — PK = int IDENTITY (ไม่ใช่ GUID)

S8/S9 ใช้ uniqueidentifier (GUID) เป็น PK เพราะต้อง carry over จาก legacy · S3 เป็น greenfield ไม่มี GUID เดิมให้รักษา จึงใช้ int IDENTITY(1,1) (running number) เป็น PK ทุกตาราง — เรียบง่ายและ index-friendly กว่า ; ตาราง log ปริมาณสูงใช้ bigint IDENTITY Audit cols CreatedBy/UpdatedBy เป็น int FK → PRC.AppUser (ต่างจาก S8/S9 ที่เก็บเป็น nvarchar)

Role Hierarchy (SRS §3.1, 6 roles) — บริหารรวมศูนย์

ADMIN · OFFICER_KSS · OFFICER_OTHER · TRAINER · VIEWER · CITIZEN

Role สิทธิ์โดยสรุป
ADMIN เห็นและจัดการทุกเมนู, อนุมัติคำขอ, จัดการ Role
OFFICER_KSS บันทึก-แก้ไขหลักสูตร/โครงการ/งบประมาณ/ครุภัณฑ์, พิจารณาคำขอลงทะเบียน
OFFICER_OTHER บันทึกรายงานเผยแพร่ฯ ของตนเอง, ร่างประวัติการสอนวิทยากร (รออนุมัติ)
TRAINER ดูตารางหลักสูตรของตน, แก้ไขข้อมูลส่วนตัวเมื่อ ADMIN เปิดสิทธิ์
VIEWER ผู้บริหาร — Dashboard + รายงาน (read-only)
CITIZEN Public Catalog + สมัครหลักสูตร + ตรวจสอบสถานะ + ดาวน์โหลดประกาศนียบัตร

กำหนดสิทธิ์ที่ส่วนกลาง (SSO via JWT)

การยืนยันตัวตน + การมอบสิทธิ์อยู่ที่ SSO กลาง (ThaID / Keycloak federate กับ RLPD Active Directory) S3 อ่านบทบาทจริงจาก JWT ขณะ runtime · AppUser + RoleAssignment ใน schema นี้เป็นเพียง local mirror (auto-provision เมื่อ login ครั้งแรก) — ไม่มีคอลัมน์ password/lockout ; Role เป็น catalog 6 บทบาทไว้ map เมนูในแอป ดู Backend Implementation §6

🔑 Requirement → Table Traceability (spine)

REQ TOR สาระสำคัญ ตารางที่รองรับ
REQ-PRC-001 7.13.1(1) Dashboard real-time + Thailand heatmap + KPI Province (new), Course (new), Registration (new), Certificate (new), Member (new), Enrollment (new) — aggregate queries
REQ-PRC-002 7.13.1(2) สมาชิก CRUD + ค้นหา + soft-delete Member (IsDeleted) (new), MemberType (new), Enrollment (new), Province (new), OrgUnit (new)
REQ-PRC-003 7.13.1(3) หลักสูตร/โครงการ/วิทยากร + แนบไฟล์ + edit-request Course (new), Project (new), ProjectCourse (new), Trainer (new), TrainerSpecialty (new), TrainerEditRequest (new), Attachment (new)
REQ-PRC-004 7.13.1(4) Per-Head budget + 2-step delete BudgetCalculation (new), Project (IsDeleted) (new), AuditLog (new)
REQ-PRC-005 7.13.1(5) ครุภัณฑ์ 4 สถานะ / อายุ 5 ปี / audit โอนผู้รับผิดชอบ Equipment (new), EquipmentOwnershipHistory (new)
REQ-PRC-006 7.13.1(6) รายงานเผยแพร่ความรู้ + flag กลับให้แก้ไข KnowledgeReport (new), KnowledgeType (new), OrgUnit (new), Province (new)
REQ-PRC-007 7.13.1(7) Dashboard export + drill-down รายจังหวัด (ไม่มี schema) อ่าน aggregate ของ REQ-001 ; export action → AuditLog (new)
REQ-PRC-008 7.13.2(1) ลงทะเบียน + approval queue + draft/publish + prerequisite Registration (new), Course (Status/IsDraft) (new), CoursePrerequisite (new), Enrollment (new), EmailNotification (new)
REQ-PRC-009 7.13.2(2) Public catalog 2 หมวด (โครงการ / นักบริหารฯ) Course (Category) (new), Batch (new), Trainer (new), Attachment (new)
REQ-PRC-010 7.13.2(3) E-mail แจ้งผล + retry 3× + เช็คสถานะ EmailNotification (new), EmailAttempt (new), Registration (new)
REQ-PRC-011 7.13.2(4) ค้นหา + ส่งออก Excel/CSV (เจ้าหน้าที่) (ไม่มี schema) อ่าน Registration / Member / Course / Enrollment
REQ-PRC-012 Extra-HYB Hybrid (Onsite + Online URL พร้อมกัน) Course (Mode + OnsiteVenue + OnlineUrl) (new)
REQ-PRC-013 Extra-LVL ระดับหลักสูตร + Batch + ทำเนียบรุ่น (Alumni) Course (Level) (new), Batch (new), Enrollment (new), Member (new), Certificate (new)
REQ-PRC-014 Extra-WM E-cert + ลายน้ำ "สำเนา" + audit การพิมพ์ Certificate (new), CertificatePrintLog (new), AuditLog (new)
Auth SRS §3.1 SSO via JWT + RBAC 6 บทบาท AppUser (mirror), RoleAssignment (mirror), Role (mirror)

REQ ที่ไม่มีผลต่อ schema (จัดการที่ app/infra layer)

  • REQ-PRC-007 — chart rendering + Dashboard export .pdf/.png/.jpeg (≥ 1920×1080) = frontend/report engine ; เก็บได้แค่ export action ใน AuditLog
  • REQ-PRC-011 — ส่งออก Excel / CSV สำหรับเจ้าหน้าที่ = generate ที่ app layer จาก query (ไม่มีตารางเฉพาะ)
  • SSL/auth — TLS 1.2+, การยืนยันตัวตน + lockout policy อยู่ที่ central SSO (ThaID / Keycloak realm) ; S3 อ่านจาก JWT เท่านั้น

Table Inventory (28 ตาราง, schema PRC)

กลุ่ม ตาราง
Lookup Province, MemberType, KnowledgeType, OrgUnit, Role
Identity/Auth (mirror) AppUser (SSO profile, no password), RoleAssignmentrole grants จาก SSO กลาง
Course Catalog Course, ProjectCourse, CoursePrerequisite
Project/Budget Project, BudgetCalculation
Trainer Trainer, TrainerSpecialty, TrainerEditRequest
Member/Alumni Member, Enrollment
Registration & Approval Registration
Batch Batch
Certificate Certificate, CertificatePrintLog
Equipment Equipment, EquipmentOwnershipHistory
Knowledge KnowledgeReport
Notification/Email EmailNotification, EmailAttempt
Audit AuditLog
File Attachment (single polymorphic)

Demo → Target mapping (สรุป)

demo data.jsx มี 11 entity — ตารางที่เหลือใน 28 ตารางเป็น support tables / lookups / mirror auth ที่เพิ่มเข้ามาเพื่อ normalize + workflow + integrity

Demo entity (data.jsx) Target (PRC) หมายเหตุ
COURSES Course + CourseCode UNIQUE, Category/Level/Mode/Status = CHECK, IsDraft, OnsiteVenue+OnlineUrl (Hybrid), HasCert, IsDeleted
PROJECTS Project + ProjectCourse PROJECTS.courses[] → junction ProjectCourse (N:M) ; Project.IsDeleted = 2-step delete
TRAINERS Trainer + TrainerSpecialty TRAINERS.specialties[] → junction TrainerSpecialty (1:N)
MEMBERS Member + Enrollment MEMBERS.courses[] → junction Enrollment (Member↔Course↔Batch) ; Member.IsDeleted บังคับ (REQ-002)
REGISTRATIONS Registration + RegistrationNo UNIQUE, Status/Channel = CHECK, approval queue, EmailSent denorm
CERTIFICATES Certificate + CertificateNo UNIQUE, Score CHECK 0..100, Result PASS/FAIL, IsOriginalIssued, ReprintCount
BATCHES Batch + UNIQUE(CourseId, BatchNo), YearBE (int พ.ศ. label), CompletedCount denorm
EQUIPMENT Equipment + EquipmentCode UNIQUE, Status 4 ค่า = CHECK, AcquiredAt → คำนวณอายุ 5 ปี runtime
KNOWLEDGE_REPORTS KnowledgeReport + KnowledgeTypeId FK, Status PENDING/APPROVED/NEEDS_FIX, FlagNote, SubmittedBy/FlaggedBy
EMAIL_LOG EmailNotification + Status PENDING/SENT/FAILED/BOUNCED, RetryCount CHECK 0..3, NextRetryAt (backoff)
AUDIT_LOG AuditLog append-only, denormalized ActorName/ActorRole, EntityType/EntityId = varchar

Support tables / mirror auth ที่เพิ่มใหม่ (ไม่มีใน demo):

Target (PRC) เพิ่มมาเพื่อ
BudgetCalculation สแนปช็อต Per-Head (user-confirm, ไม่ auto-save) — REQ-004
CoursePrerequisite เงื่อนไขหลักสูตรก่อนสมัคร (self-ref course→course) — REQ-008 (ยืนยันโดย กสส.)
TrainerEditRequest คำขอแก้ประวัติวิทยากร (ร่าง → ADMIN อนุมัติ) — REQ-003
CertificatePrintLog append-only บันทึกการพิมพ์ทุกครั้ง (ORIGINAL/COPY + watermark) — REQ-014
EquipmentOwnershipHistory append-only การเปลี่ยนผู้รับผิดชอบครุภัณฑ์ — REQ-005
EmailAttempt append-only per-try รองรับ retry/backoff — REQ-010
Attachment single polymorphic — แทนการแนบไฟล์แยกราย entity ใน demo (Course.attached = derived COUNT(*))
AppUser / RoleAssignment / Role thin-mirror auth — SSO via JWT (ไม่มี password)
Province / MemberType / KnowledgeType / OrgUnit lookup tables — normalize enum/free-text ของ demo

การยืนยันจาก กสส. (resolved)

ประเด็นที่เคยเปิดไว้ — ได้รับการยืนยันจาก กสส. แล้ว:

ประเด็น คำตอบที่ยืนยัน ผลต่อ schema
IdP ต่อ user class ใช้ทุกช่องทาง — AD (เจ้าหน้าที่), ThaID (CITIZEN), Keycloak realm rlpd ผ่าน S9 (เหมือน S8) ไม่เปลี่ยน — AppUser.AuthSource รองรับหลาย IdP แล้ว
Per-Head formula (REQ-004) (CourseCost + AdminCost) / HeadCount — ไม่มีก้อนค่าใช้จ่ายแยก ไม่เปลี่ยน — BudgetCalculation ครบแล้ว
Retention ของ log เก็บ 1 ปี (AuditLog / EmailNotification / EmailAttempt) ไม่เปลี่ยนโครงสร้าง — วางแผน archive/purge เมื่ออายุ > 1 ปี
OrgUnit master มี master list ของหน่วยงาน คง OrgUnit (FK) ; OrgText ไว้รองรับหน่วยงานนอก master เท่านั้น
Prerequisites (REQ-008) มี เงื่อนไขหลักสูตรก่อนสมัคร ; ไม่จำกัดจำนวน รับ 🆕 เพิ่มตาราง CoursePrerequisite ; capacity คง Course.TargetCount (soft)
Post-test / Score คะแนน กรอกมือ ไม่มีระบบสอบในตัว ไม่เปลี่ยน — Certificate.Score = ค่าที่กรอก

HR / Legacy humanright_file integration — เลื่อนเป็น next-phase

SRS (ar_and_crs/README.md → System Integration) ระบุไว้แต่เป็น "ระยะถัดไป" (push ประวัติเข้า HR) และ "ถ้านำมาใช้ / อยู่ระหว่างพิจารณา" (legacy humanright_file) → v1 ไม่กระทบ schema (ทำที่ API/ETL layer) · เมื่อ กสส. ตัดสินใจทำเมื่อใด → เพิ่ม export-log table แบบ S9 OpenApiExecuteLog