commit
This commit is contained in:
343
plans/req.md
Normal file
343
plans/req.md
Normal file
@@ -0,0 +1,343 @@
|
||||
# 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 ของรีโป เพื่อให้สามารถพัฒนาต่อจากฐานโค้ดนี้ได้จริง
|
||||
Reference in New Issue
Block a user