S8 — Official Website — ER Diagram (Target Design)¶
TARGET DESIGN
ความสัมพันธ์ตาม schema.sql (FK ทุกเส้นถูกประกาศจริงใน DDL) · ทุกตารางเป็น NEW design (S8 redesign ทั้งชุด)
ทุกตารางมี audit columns (CreatedAt/By, UpdatedAt/By) + soft delete (IsDeleted) — ละไว้ในไดอะแกรมเพื่อความชัด
Core: Department → Template → Content → Media¶
erDiagram
Department ||--o{ DepartmentTheme : "selects"
Template ||--o{ DepartmentTheme : "used by"
ThemeColor ||--o{ DepartmentTheme : "palette"
Department ||--o{ Menu : "navbar"
Menu ||--o{ MenuTranslation : "i18n"
Menu ||--o{ Menu : "parent"
MenuType ||--o{ Menu : "type"
Department ||--o{ Category : "owns"
Category ||--o{ CategoryTranslation: "i18n"
Category ||--o{ Content : "groups"
ContentType ||--o{ Content : "type"
Content ||--o{ Content : "parent"
Content ||--o{ ContentArticle : "body i18n"
Content ||--o{ ContentRevision : "workflow versions"
Content ||--o{ ContentAttachFile : "files"
Content ||--o{ ContentImage : "images"
MediaType ||--o{ MediaAsset : "kind"
MediaAsset ||--o{ MediaVariant : "auto-resized"
MediaAsset ||--o{ ContentAttachFile : "attached"
MediaAsset ||--o{ ContentImage : "shown"
Language ||--o{ ContentArticle : "lang"
Banner & Widgets¶
erDiagram
Department ||--o{ Banner : "owns"
BannerType ||--o{ Banner : "type"
BannerLocation ||--o{ Banner : "position"
BannerGroup ||--o{ Banner : "group"
Template ||--o{ Banner : "for template"
MediaAsset ||--o{ Banner : "image"
Banner ||--o{ BannerTranslation: "i18n + alt"
Department ||--o{ BannerSetting : "slide cfg"
BannerType ||--o{ BannerSetting : "for type"
Department ||--o{ Popup : "popup"
Department ||--o{ Faq : "faq"
Faq ||--o{ FaqQuestion : "Q/A"
Faq ||--o{ Faq : "parent"
Department ||--o{ Calendar : "events"
CalendarCategory ||--o{ Calendar : "category"
Department ||--o{ Footer : "footer"
Footer ||--o{ FooterItem : "links"
RBAC, Embed, API, Logs¶
erDiagram
Department ||--o{ User : "belongs (SSO profile)"
Position ||--o{ User : "position"
AdminMenu ||--o{ RoleMenu : "controls"
AdminMenu ||--o{ AdminMenu : "parent"
%% RoleMenu.RoleCode = central role (PORTAL.ModuleRoles) — no local Role/UserRole table
%% user→role grants live in PORTAL.UserRole + Keycloak (read from JWT)
Department ||--o{ EmbedCode : "embeds"
EmbedCode ||--o{ EmbedCodeAudit : "audit trail"
ApiClient ||--o{ ApiClientScope : "scopes"
ApiClient ||--o{ ApiAccessLog : "calls"
Department ||--o{ ApiClientScope : "limited to"
User ||--o{ SearchLog : "searches"
Department ||--o{ AccessibilityIssue : "a11y issues"
Content ||--o{ PublicAccessLog: "viewed"
Category ||--o{ PublicAccessLog: "viewed"
หมายเหตุการออกแบบ¶
- MediaAsset → MediaVariant คือหัวใจของ REQ-WEB-003 (auto-resize): เก็บไฟล์ต้นฉบับ 1 แถว + renditions หลายแถว (banner-main / banner-service / article / thumb) ตามขนาด section ของ
Template - Content → ContentRevision แยก workflow/approval ออกจาก body ที่เผยแพร่ (
ContentArticle) — รองรับCONTENT_EDITORส่ง →CONTENT_APPROVERอนุมัติ - EmbedCode.RequiresSuperAdmin บังคับกติกา "Header-level เพิ่มได้เฉพาะ Super Admin" (REQ-WEB-004)
- ไม่มี FK ข้ามไป S9 ในระดับ DB — การฝังแบบประเมิน (S9 Survey) ทำผ่าน URL/Embed เท่านั้น