344 lines
17 KiB
Markdown
344 lines
17 KiB
Markdown
# Training System Requirements Aligned With Project Stack
|
|
|
|
## 1. เป้าหมายของระบบ
|
|
|
|
ระบบนี้เป็นเว็บแอปสำหรับจัดเก็บและติดตามประวัติการอบรมของพนักงาน รวมถึงไฟล์ใบรับรองการอบรม และการตรวจสอบความครบถ้วนตาม Training Matrix ของแต่ละหน่วยงานหรือแต่ละตำแหน่งงาน
|
|
|
|
เอกสารฉบับนี้ปรับให้สอดคล้องกับ stack และสถาปัตยกรรมของโปรเจ็กต์ปัจจุบัน โดยไม่ใช้ Google Apps Script, Google Sheets หรือ Google Drive เป็นแกนหลักของระบบ
|
|
|
|
## 2. Stack ที่ต้องใช้ตามโปรเจ็กต์นี้
|
|
|
|
- Frontend: Next.js 16 App Router + React 19 + TypeScript
|
|
- UI: Tailwind CSS v4 + shadcn/ui
|
|
- Auth: Auth.js
|
|
- Database: PostgreSQL + Drizzle ORM
|
|
- Data fetching: TanStack React Query
|
|
- URL state: nuqs
|
|
- Forms: TanStack Form + Zod ผ่าน `useAppForm`
|
|
- API boundary: Next.js Route Handlers ภายใต้ `src/app/api/**`
|
|
- Icons: ใช้ผ่าน `@/components/icons` เท่านั้น
|
|
|
|
## 3. แนวทางสถาปัตยกรรมที่ต้องยึด
|
|
|
|
- ใช้ feature-based structure ภายใต้ `src/features/<feature>/`
|
|
- ใช้ data layer pattern ของโปรเจ็กต์:
|
|
- `types.ts`
|
|
- `service.ts`
|
|
- `queries.ts`
|
|
- `mutations.ts` เมื่อมี create/update/delete
|
|
- ฝั่ง client ต้องเรียกข้อมูลผ่าน `service.ts`
|
|
- `service.ts` ต้องเรียก Route Handlers ด้วย `apiClient`
|
|
- Route Handlers ต้องเป็น boundary หลักสำหรับ auth, authorization, validation ขั้นต้น และ database access
|
|
- หน้า dashboard ต้องใช้ `PageContainer` สำหรับ page header
|
|
- table/listing ที่มี filter, search, sort, pagination ต้องใช้ React Query + nuqs ตาม pattern ของหน้า `products` และ `users`
|
|
- form ต้องใช้ `useAppForm` และ field wrappers ของโปรเจ็กต์
|
|
|
|
## 4. Domain Model ที่ต้องใช้ในระบบ
|
|
|
|
ระบบนี้ควรใช้คำศัพท์โดเมนให้ชัดและสอดคล้องกับโครงสร้าง auth ปัจจุบัน
|
|
|
|
- `user`: ผู้ใช้งานที่ล็อกอินเข้าระบบ
|
|
- `organization`: หน่วยงานเจ้าของข้อมูล หรือ tenant ของระบบ
|
|
- `membership`: ความสัมพันธ์ระหว่าง user กับ organization พร้อม role
|
|
- `employee`: ข้อมูลพนักงานที่ถูกติดตามประวัติการอบรม
|
|
- `course`: หลักสูตรอบรมกลาง
|
|
- `training_record`: รายการประวัติการอบรมของพนักงานแต่ละครั้ง
|
|
- `certificate`: ข้อมูลไฟล์ใบรับรองที่ผูกกับ training record
|
|
- `training_matrix`: ข้อกำหนดว่าตำแหน่งหรือแผนกใดต้องผ่านหลักสูตรอะไร
|
|
- `department`: หน่วยงานภายในองค์กร
|
|
- `position`: ตำแหน่งงาน
|
|
|
|
หมายเหตุ:
|
|
- ถ้าผู้ใช้ระบบกับพนักงานเป็นคนละแนวคิด ต้องแยก `user` ออกจาก `employee`
|
|
- ข้อมูลทั้งหมดควรถูกผูกกับ `organizationId` เพื่อรองรับ multi-tenant
|
|
|
|
## 5. ขอบเขตข้อมูลหลักใน PostgreSQL
|
|
|
|
ตารางหลักที่ควรมีในระบบนี้:
|
|
|
|
- `users`
|
|
- ข้อมูลบัญชีผู้ใช้งานสำหรับ Auth.js
|
|
- `organizations`
|
|
- ข้อมูลองค์กรหรือ workspace
|
|
- `memberships`
|
|
- บทบาทของผู้ใช้งานในแต่ละ organization
|
|
- `employees`
|
|
- รหัสพนักงาน, ชื่อ, แผนก, ตำแหน่ง, บริษัท, สถานะ
|
|
- `departments`
|
|
- หน่วยงานภายใน organization
|
|
- `positions`
|
|
- ตำแหน่งงานภายใน organization
|
|
- `courses`
|
|
- ชื่อหลักสูตร, หมวดหมู่, ผู้จัดอบรม, จำนวนชั่วโมง, อายุใบรับรอง, บังคับหรือไม่
|
|
- `training_records`
|
|
- employee, course, วันที่อบรม, รูปแบบการอบรม, ชั่วโมง, หมายเหตุ, สถานะอนุมัติ
|
|
- `certificates`
|
|
- ชื่อไฟล์, path หรือ storage key, mime type, uploadedAt
|
|
- `training_matrices`
|
|
- mapping ระหว่าง department หรือ position กับ course ที่จำเป็น
|
|
|
|
แนวทางสำคัญ:
|
|
|
|
- ทุกตารางเชิงธุรกิจควรมี `organizationId`
|
|
- ใช้ foreign keys ชัดเจนระหว่าง employee, course, training_record, certificate
|
|
- เก็บ file metadata ใน database และเก็บไฟล์จริงใน app-owned storage
|
|
|
|
## 6. แนวทางจัดเก็บไฟล์ใบรับรอง
|
|
|
|
ไม่ใช้ Google Drive เป็น storage หลักของระบบนี้
|
|
|
|
รอบแรกของระบบควรใช้แนวทางใดแนวทางหนึ่ง:
|
|
|
|
- ทางเลือกแนะนำสำหรับโปรเจ็กต์นี้:
|
|
- เก็บ metadata ใน PostgreSQL
|
|
- เก็บไฟล์จริงผ่าน local uploads หรือ object storage ที่ต่อเพิ่มภายหลัง
|
|
|
|
ข้อกำหนดเชิงระบบ:
|
|
|
|
- certificate ต้องผูกกับ `training_record`
|
|
- ต้องสามารถเปิดดูไฟล์ย้อนหลังได้
|
|
- ต้องรองรับไฟล์อย่างน้อย `pdf`, `jpg`, `jpeg`, `png`
|
|
- ต้องมี field สำหรับ `fileName`, `fileType`, `fileSize`, `storageKey`, `uploadedAt`
|
|
|
|
## 7. บทบาทผู้ใช้งาน
|
|
|
|
ระบบต้องรองรับ role อย่างน้อย:
|
|
|
|
- `member`
|
|
- ดู dashboard ของตัวเอง
|
|
- เพิ่มและแก้ไขประวัติการอบรมของตัวเอง
|
|
- อัปโหลดใบรับรองของตัวเอง
|
|
- ดูสถานะการอนุมัติ
|
|
- `admin`
|
|
- จัดการ employee
|
|
- จัดการ course
|
|
- ตรวจสอบและอนุมัติ training record
|
|
- จัดการ training matrix
|
|
- ดูรายงานภาพรวมของ organization
|
|
- `owner`
|
|
- สิทธิ์ระดับสูงสุดใน organization
|
|
- จัดการสมาชิกและค่ากำหนดหลักของ organization
|
|
|
|
Authorization ต้องตรวจที่ server-side ผ่าน session + membership ไม่ใช่ตรวจเฉพาะ client
|
|
|
|
## 8. ฟีเจอร์หลักสำหรับผู้ใช้งานทั่วไป
|
|
|
|
### 8.1 User Dashboard
|
|
|
|
ผู้ใช้งานต้องเห็น dashboard ส่วนตัวที่ประกอบด้วย:
|
|
|
|
- จำนวนหลักสูตรที่เคยอบรมทั้งหมด
|
|
- จำนวนชั่วโมงอบรมสะสม
|
|
- จำนวนใบรับรองที่บันทึกแล้ว
|
|
- จำนวนหลักสูตรที่ยังขาดตาม training matrix
|
|
- กราฟสรุปการอบรมรายเดือนหรือรายปี
|
|
|
|
แนวทาง implementation:
|
|
|
|
- ใช้ Recharts สำหรับกราฟ
|
|
- ใช้ server prefetch + `HydrationBoundary` + `useSuspenseQuery`
|
|
|
|
### 8.2 บันทึกการอบรม
|
|
|
|
ผู้ใช้งานต้องสามารถเพิ่มรายการอบรมได้ โดยข้อมูลหลักประกอบด้วย:
|
|
|
|
- employee หรือข้อมูลผู้เข้าอบรม
|
|
- course
|
|
- training date
|
|
- training type: `online | onsite | internal | external`
|
|
- training hours
|
|
- organizer
|
|
- note
|
|
- certificate file
|
|
- approval status
|
|
|
|
แนวทาง implementation:
|
|
|
|
- ใช้ TanStack Form + Zod
|
|
- submit ผ่าน mutation ไปยัง Route Handler
|
|
- หลังบันทึกต้อง invalidate query ที่เกี่ยวข้อง
|
|
|
|
### 8.3 รายการอบรมของฉัน
|
|
|
|
ผู้ใช้งานต้องสามารถ:
|
|
|
|
- ค้นหาตามชื่อหลักสูตร
|
|
- กรองตามปี
|
|
- กรองตามหมวดหมู่
|
|
- กรองตามสถานะ
|
|
- เปิดดูรายละเอียด
|
|
- เปิดดูไฟล์ใบรับรอง
|
|
- แก้ไขรายการของตัวเอง
|
|
- ลบรายการที่ยังไม่ถูกอนุมัติ หรือเป็นไปตาม policy ที่กำหนด
|
|
|
|
แนวทาง implementation:
|
|
|
|
- ใช้ Data Table pattern เดียวกับ `products` หรือ `users`
|
|
- ใช้ React Query + nuqs
|
|
|
|
## 9. ฟีเจอร์หลักสำหรับ Admin
|
|
|
|
### 9.1 Admin Dashboard
|
|
|
|
Admin ต้องเห็น dashboard ภาพรวมของ organization:
|
|
|
|
- จำนวนพนักงาน
|
|
- จำนวนชั่วโมงอบรมรวม
|
|
- เปอร์เซ็นต์ความครบถ้วนตาม training matrix
|
|
- จำนวนรายการที่รออนุมัติ
|
|
- สถิติแยกตามแผนก หมวดหมู่ และช่วงเวลา
|
|
|
|
### 9.2 จัดการ Employee
|
|
|
|
Admin ต้องสามารถ:
|
|
|
|
- เพิ่ม employee
|
|
- แก้ไข employee
|
|
- ปิดการใช้งาน employee
|
|
- กำหนดแผนก
|
|
- กำหนดตำแหน่ง
|
|
|
|
### 9.3 จัดการ Course
|
|
|
|
Admin ต้องสามารถ:
|
|
|
|
- เพิ่ม course
|
|
- แก้ไข course
|
|
- ลบ course
|
|
- กำหนด category
|
|
- กำหนด standard training hours
|
|
- กำหนด certificate validity
|
|
- ระบุว่าเป็น required course หรือไม่
|
|
|
|
### 9.4 ตรวจสอบและอนุมัติ Training Record
|
|
|
|
Admin ต้องสามารถ:
|
|
|
|
- เปิดดูไฟล์ใบรับรอง
|
|
- ตรวจสอบรายละเอียดการอบรม
|
|
- approve
|
|
- reject
|
|
- request changes
|
|
- ใส่หมายเหตุประกอบการตรวจสอบ
|
|
|
|
สถานะที่ควรใช้:
|
|
|
|
- `pending`
|
|
- `approved`
|
|
- `rejected`
|
|
- `needs_revision`
|
|
|
|
### 9.5 จัดการ Training Matrix
|
|
|
|
Admin ต้องสามารถ:
|
|
|
|
- กำหนดหลักสูตรบังคับตาม department
|
|
- กำหนดหลักสูตรบังคับตาม position
|
|
- กำหนดหลักสูตรเฉพาะรายบุคคลในอนาคตได้
|
|
- กำหนด minimum required hours เมื่อจำเป็น
|
|
- ดูสถานะครบหรือไม่ครบของแต่ละ employee
|
|
|
|
## 10. รายงานที่ระบบควรมี
|
|
|
|
อย่างน้อยควรมีรายงานต่อไปนี้:
|
|
|
|
- ประวัติการอบรมรายบุคคล
|
|
- การอบรมแยกตามแผนก
|
|
- ชั่วโมงอบรมสะสม
|
|
- หลักสูตรที่ยังขาดตาม matrix
|
|
- ใบรับรองใกล้หมดอายุ
|
|
- สรุป training matrix ของ organization
|
|
|
|
รูปแบบการแสดงผล:
|
|
|
|
- แสดงบนหน้า dashboard/table
|
|
- รองรับ export ใน phase ถัดไป
|
|
|
|
## 11. แนวทาง UI/UX ที่ต้องสอดคล้องกับโปรเจ็กต์
|
|
|
|
- ใช้ shadcn/ui และ component patterns ที่มีอยู่แล้ว
|
|
- ใช้ `PageContainer` สำหรับ page title, description, action
|
|
- ใช้ `@/components/icons` แทนการ import icon ตรงจาก package ภายนอก
|
|
- ใช้ Card, Table, Dialog, Sheet, Tabs ตามแนวทางเดิมของโปรเจ็กต์
|
|
- รองรับ desktop และ mobile
|
|
- ไม่ใช้ SweetAlert2 หรือระบบ popup ภายนอกเป็นค่าเริ่มต้น
|
|
- ใช้ toast/alert/dialog ที่มีในโปรเจ็กต์แทน
|
|
|
|
## 12. Visual Direction
|
|
|
|
โทนสีจาก requirement เดิมสามารถตีความเป็น theme ของระบบได้ แต่ต้อง implement ผ่าน theme/token ของโปรเจ็กต์นี้ ไม่ใช่เขียนเป็นระบบ CSS แยกใหม่
|
|
|
|
สีที่ต้องการ:
|
|
|
|
- เขียวเข้ม: `#336b4a`
|
|
- เทา: `#808285`
|
|
- ส้ม: `#e26631`
|
|
- ม่วงเข้ม: `#413b60`
|
|
|
|
แนวทางใช้งาน:
|
|
|
|
- primary actions: เขียวเข้ม
|
|
- warning/highlight states: ส้ม
|
|
- supporting accents/charts: ม่วงเข้ม
|
|
- muted text/borders: เทา
|
|
|
|
ถ้าต้องทำ theme จริง ให้เพิ่มผ่านระบบ theme ของโปรเจ็กต์ ไม่ทำแยกนอก `src/styles/themes` และ `theme.config.ts`
|
|
|
|
## 13. แนวทางแบ่ง feature ในรีโปนี้
|
|
|
|
ฟีเจอร์ที่ควรสร้างใน `src/features/`:
|
|
|
|
- `employees`
|
|
- `courses`
|
|
- `training-records`
|
|
- `certificates`
|
|
- `training-matrix`
|
|
- `reports`
|
|
|
|
แต่ละ feature ควรมี:
|
|
|
|
- `api/types.ts`
|
|
- `api/service.ts`
|
|
- `api/queries.ts`
|
|
- `api/mutations.ts` เมื่อมี mutation
|
|
- `components/`
|
|
- `schemas/`
|
|
- `constants/` เมื่อจำเป็น
|
|
|
|
และมี route ใต้ `src/app/dashboard/<feature>/page.tsx`
|
|
|
|
## 14. ลำดับการพัฒนาที่แนะนำ
|
|
|
|
เพื่อให้เข้ากับโครงสร้างของโปรเจ็กต์ ควรพัฒนาเป็นลำดับดังนี้:
|
|
|
|
1. Auth + organization + membership foundation
|
|
2. Employee management
|
|
3. Course management
|
|
4. Training record CRUD + certificate upload metadata
|
|
5. Training matrix
|
|
6. Dashboard summaries and reports
|
|
|
|
## 15. สิ่งที่ไม่ควรใช้ใน requirement ฉบับนี้
|
|
|
|
เพื่อให้ตรงกับโปรเจ็กต์นี้ ไม่ควรออกแบบระบบโดยอิงสิ่งต่อไปนี้เป็นแกนหลัก:
|
|
|
|
- Google Apps Script
|
|
- Google Sheets เป็น database หลัก
|
|
- Google Drive เป็น storage หลัก
|
|
- HTML/CSS/JavaScript แบบแยก standalone app
|
|
- SweetAlert2 เป็น UI feedback หลัก
|
|
- FontAwesome เป็น icon source หลัก
|
|
|
|
## 16. สรุป
|
|
|
|
ระบบ Training System ฉบับนี้ต้องถูกออกแบบให้เป็น multi-tenant web application บน stack ของโปรเจ็กต์ปัจจุบัน โดยใช้:
|
|
|
|
- Next.js App Router
|
|
- Auth.js
|
|
- PostgreSQL + Drizzle
|
|
- React Query + nuqs
|
|
- TanStack Form + Zod
|
|
- shadcn/ui + Tailwind CSS
|
|
|
|
และต้องจัดวางฟีเจอร์ตาม feature architecture ของรีโป เพื่อให้สามารถพัฒนาต่อจากฐานโค้ดนี้ได้จริง
|