Internal Portal · Digital OS · 8 Modules

Portal Realfact
Digital OS สำหรับกลุ่มบริษัท

Internal Portal ที่รวม 8 แผนกของ Real Factory ไว้ในระบบเดียว — จากเอกสารกระจายใน Excel/LINE/Email สู่ Source of Truth เดียว

Internal Portal 8 Modules RBAC 18 Roles Vue 3 + TypeScript Design System Multi-Tenant i18n TH/EN

ปัญหาที่เจอ

ทำไมกลุ่มบริษัทถึงต้องมี Digital OS ของตัวเอง?

8 แผนกใช้ระบบคนละชุด — ขอซื้อใน Excel, เบิกเงินใน LINE, จองที่พักใน Google Form, ตั๋วเครื่องบินใน Email Approval cycle 3-5 วันต่อ 1 เอกสาร และไม่มีใครเห็นภาพรวม ผู้บริหารไม่รู้ด้วยซ้ำว่างานค้างอยู่ที่ใคร

— Insight จาก stakeholder interview ก่อนเริ่มโปรเจกต์
🧩

8 แผนกใช้ระบบแยก ไม่มีใครเห็นภาพรวม

ขอซื้อใน Excel, เบิกเงินใน LINE, จองที่พักใน Google Form, ตั๋วเครื่องบินใน Email — ไม่มี Source of Truth เดียว ตามไม่ได้ว่าเอกสารอยู่ที่ขั้นไหน

Approval Cycle 3-5 วันต่อเอกสาร

เอกสารต้อง print → เซ็น → สแกน → ส่งต่อ ผู้บริหารไม่รู้ว่างานค้างที่ใคร เกินวันยังไม่ได้แก้ — กระทบแผนงานทั้งบริษัท

🕵️

ไม่มี Audit Trail — ตามย้อนไม่ได้

ใคร approve ใคร reject เพราะอะไร ใช้งบเกินวงเงินหรือไม่ — ไม่มีบันทึก พอ Auditor มาตรวจหาเอกสารกันยกใหญ่

📄

ทำเอกสาร PDF ด้วยมือทุกครั้ง

เปิด Word เติมตัวเลข → export PDF → print → เซ็นปากกา → สแกนกลับ — เปลืองเวลา ผิดพลาดเยอะ ไม่มี standard layout

🔐

15+ User Roles สิทธิ์ต่างกัน

Hardcode role check ทั่ว codebase — แค่เพิ่ม role ใหม่ก็ต้องไล่แก้ทุกหน้า maintain ไม่ไหวเมื่อบริษัทขยาย


วิธีแก้ปัญหา

1 Portal เดียว — Digital OS pattern ที่รองรับทุกแผนกพร้อมกัน

🎯

1 Portal เดียวรวมทุก Request Type

PR/PO, Expense, Booking, HR Request — เข้าใน Portal เดียว 1 source of truth ผู้ใช้ login ครั้งเดียว เห็นทุก task ของตัวเอง

⚙️

Approval Engine แบบ Configurable

State machine กลาง 1 ตัว รองรับ chain แบบ M3→E1→E2→E3→CEO ตามวงเงิน — แต่ละ doc type / department config เองได้ ไม่ต้องเขียน code ใหม่

Real-time Status ผ่าน Socket.io

ผู้ขอเห็นทันทีว่างานค้างที่ใคร ผู้บริหารเห็น dashboard "เกินวันค้าง" แบบ real-time — ลด follow-up ใน LINE ไปได้กว่า 80%

📑

Document PDF Component ที่ Reuse ได้

Voucher + Signature Block + Attachment Index = component กลาง ใช้ได้ทุก doc type ไม่ต้อง duplicate layout

🛡️

RBAC 18 Roles แยก Approval Level

M3/E1/E2/E3, Finance Lv1/Head, Acc Lv1/Head, Procurement Manager + Reviewer ฯลฯ — ตรงกับ org chart จริง config ผ่าน Permissions Matrix

🌏

i18n Bilingual TH/EN ตั้งแต่วันแรก

ทุก string ผ่าน useLocale composable + type-safe LocaleKey รองรับขยายตลาดต่างประเทศโดยไม่ต้อง refactor


Architecture Overview

Vue 3 + Express + Prisma — Modern stack, shared types, single source of truth

Frontend — Portal SPA
Vue 3.5 Vite 8 TypeScript PrimeVue 4 Tailwind v4 Pinia 3
@portal/shared — Zod Schemas
Validation Types Single Source of Truth
Backend API
Express 5 Prisma 6 JWT + Google OAuth Socket.io Pino Logger
Infrastructure
PostgreSQL (Supabase) Supabase Storage Docker Railway / AWS ECS GitHub Actions

สิ่งที่สร้าง — 8 Modules

Phase 1 MVP — Core Platform + 7 Functional Modules

📋

PR / Procurement

Purchase Request + PO with approval chain (M3→E1→E2→E3→CEO ตามวงเงิน) + supplier comparison

💰

Expense Suite

Petty Cash, Reimbursement, Advance + Clear, Credit Card OCR, Travel — 5 sub-flows + WHT 1/2/3/5%

🏨

Booking

ที่พัก (HR confirm จาก voucher pool ของบริษัท) + ตั๋วเครื่องบิน (HR แนบ e-ticket)

👥

HR

Employee Directory, Vehicle Registry, Course Library, Form Templates, Announcements

Think Tank

กิจกรรม engagement + leaderboard + scoring โดย C-Level พร้อมรายงานผล

📚

Legal

Knowledge Base + AI Chat (Phase 1: Legal Admin only) — รวบรวมสัญญา + ข้อกฎหมายภายใน

📊

C-Level Dashboard

Pending approvals, Budget vs Actual, Approval Bottleneck, Department Ranking, Spending Trend

⚙️

Admin

Permissions Matrix (18 roles × all routes), Workflow config, System settings — เปลี่ยนสิทธิ์โดยไม่ต้อง deploy


Hack กับปัญหา

6 challenges ที่ไม่มีอยู่ใน playbook — ต้องคิดทาง workaround เอง

🎯

RBAC 18 Roles แตกจาก 11

PRD ระบุ 15 roles แต่ codebase รวบยอดเป็น 11 → approval threshold ทำงานไม่ตรงกับ org chart จริง คนที่ควรเห็นเอกสารเห็นไม่ครบ คนที่ไม่ควรเห็นกลับเข้าได้

แก้: split manager → m3/e1/e2/e3, Finance → Lv1/Head, Acc → Lv1/Head, Procurement Manager + เพิ่ม Reviewer + tab filter per role + backward-compat normalize legacy roles ด้วย mapping function
📄

Document PDF ที่ Scale ได้ 8 Doc Types

8 doc types × signature block × attachment index × ต้องการ real PDF merge (text-selectable) — ถ้า duplicate layout ต่อ doc คือฝันร้าย maintainability

แก้: สร้าง component กลาง components/document/* (SignatureBlock, AttachmentIndex, AttachmentPage) + ใช้ pdf-lib merge real PDF bytes ติดท้าย + html2canvas สำหรับ image-only attachments — 1 abstraction รองรับทุก doc
🌐

i18n Project-wide ใน 1 Sprint

~50 views, 1000+ strings, ต้องบังคับ TH/EN parity แบบ strict (ขาด key ฝั่งใดฝั่งหนึ่ง = build แตก) — ทำมือคนเดียวไม่ทันแน่

แก้: handwritten composable useLocale (zero-dep, type-safe via LocaleKey union) + delegate batch ไป subagents 10 ตัว + auto type-check ทุก batch ก่อน commit → TH/EN parity บังคับด้วย TypeScript ไม่ใช่ discipline
🌙

Login Dark Mode ที่ขัดกับ App

App รองรับ dark mode ทั้งระบบ แต่หน้า Login เป็น brand experience ที่ต้องคงสีขาว + brand panel สีเข้มตลอด — token cascade เผลอ flip สีตอนเปิด dark mode

แก้: pattern .login-light-scope lock token values ใน CSS scope; brand panel hardcoded #231F20 + !important rule กัน cascade override; SplashScreen ใช้ pattern เดียวกัน reuse ได้
🔍

Approval Bottleneck Real-time

C-Level อยากเห็นว่างานค้างอยู่ที่ใคร, chain ขั้นไหน, ค้างมานานเท่าไหร่ — แต่ refresh เอามันก็ไม่ทันใจ

แก้: Socket.io broadcast ทุก approve/reject event ไป channel ของ company; Dashboard chart "ค้าง >24 ชม." เรียงตามเวลา + drill-down เห็นชื่อผู้อนุมัติ + click ส่ง LINE notify ตรงได้
📐

Design Tokens 100% — กัน Drift ก่อนเกิด

Tailwind v4 + PrimeVue Aura theme + custom tokens — 3 layers ที่ override กันได้ ถ้าไม่มีระเบียบ hex hardcode จะแอบหลุดเข้ามาเรื่อยๆ

แก้: audit hex hardcodes → swap เป็น CSS variables; token definitions ใน design-tokens.css เป็น single source of truth; dark mode flip ผ่าน :root.dark-mode overrides — ไม่ต้องเขียน Tailwind dark: variant

Stakeholders & Build Period

Internal product — co-designed กับทีมจริงทุก department

Portal Realfact ไม่ใช่ product ที่ออกแบบจาก ivory tower — ทุก flow ผ่าน workshop กับ HR, Finance, Accounting, Procurement, Legal, C-Level จริง ทุก approval threshold มาจาก policy ของ Real Factory จริง

🏢
Real Factory Group

ลูกค้า + Production team — 8 departments stakeholder

⏱️
Build Period

6 weeks — Phase 1 MVP (Core + 7 modules)

👥
Team Composition

TechLead, PM×2, BA, UX/UI — cross-functional small team

🤖
AI-Augmented Workflow

BMAD framework + Claude subagents ช่วยทำ i18n + create-story

ทำไม co-design ถึงสำคัญกับ Internal Tools?

Internal user คือ user ที่หนีไม่ได้ — บังคับใช้ก็ต้องใช้ แต่ถ้าออกแบบไม่ตรง pain point จริง พวกเขาจะหา workaround กลับไป Excel เหมือนเดิม co-design ทำให้ทุก approval rule, ทุก field, ทุก label มาจาก domain expert จริง ไม่ใช่ assumption


Key Takeaways

4 บทเรียน Design Thinking จาก Portal Realfact

Empathy First — แยกบทบาท 18 roles ทำให้ approval flow ใกล้เคียง real org chart:

ตอนแรกใช้ 11 roles ตามที่ codebase มีอยู่ พอ test กับ Finance Head จริง เขาบอก "ผมไม่ใช่ Lv1 ผมเป็น Head ทำไมต้องเห็นเอกสารเดียวกับ Lv1?" — ถึงรู้ว่า role ต้องสะท้อน hierarchy จริง ไม่ใช่ลดเพื่อความง่ายของ dev สุดท้าย split เป็น 18 roles แล้ว approval ตรงกับ policy ของบริษัทเป๊ะ

Single Source of Truth — design tokens + Zod schemas + DEPARTMENT_LABELS:

ถ้ามี constant 1 ตัวอยู่ 3 ที่ มันจะ drift แน่นอน — ไม่ใช่ "ถ้า" แต่เป็น "เมื่อไหร่" Portal Realfact บังคับให้ทุก type, ทุก validation, ทุก label ดึงมาจากแหล่งเดียว → frontend กับ backend mismatch กันไม่ได้ tokens กับ component ขัดกันไม่ได้

Scale by Composition — 4 component กลางรองรับ 8 doc types:

SignatureBlock + AttachmentIndex + AttachmentPage + DocumentLayout — แค่ 4 components รับ prop interface เดียว generate ได้ 8 doc types (PR, PO, Petty Cash, Reimbursement, Advance, Clear, Travel, Booking) ถ้า duplicate ต่อ doc คือ 8× maintenance burden — Composition ชนะ duplication เสมอ

Subagent Workflow — งาน i18n 1000+ strings เสร็จในวันเดียว:

Translate ทีละไฟล์ทีละ string คือฝันร้าย — ใช้ Claude subagents 10 ตัว parallel แต่ละตัวรับ batch ของ views + auto type-check guard ก่อน commit ถ้า key ขาด TS แตกทันที — ไม่ต้องพึ่ง human discipline สิ่งสำคัญคือออกแบบ guard ที่ machine ตรวจได้ ไม่ใช่ checklist ใน Notion

8
Modules
18
User Roles (RBAC)
2
Languages (TH/EN)
6w
Phase 1 MVP
Aw mascot

Portal Realfact

Digital OS รวม 8 แผนกในระบบเดียว — ออกแบบให้ scale ทั้ง user count, role hierarchy และตลาดต่างประเทศ ด้วย Design System + RBAC + i18n bilingual ตั้งแต่วันแรก

Vue 3 TypeScript PrimeVue Tailwind v4 Express 5 Prisma PostgreSQL Socket.io Design System
Projects