pms-api Deep Dive
pms-api (branch: uat — default branch master เป็น branch เปล่า, package name rest-structure เหมือน benefit-api/recruitment-api, pms-api/package.json (branch: uat):2) เป็น NestJS 9 service ที่รองรับระบบบริหารผลงาน (Performance Management System) ของสภากาชาดไทย — ตั้งตัวชี้วัด (indicator), รอบการประเมิน (period), แบบประเมิน (evaluate form), สายการอนุมัติ (approver chain), จนถึงการปรับเงินเดือนตามผลประเมิน (salary adjustment) และส่งออกไประบบ HRMI เป็น repo ที่ใหญ่ที่สุดและ active ที่สุดในสี่ repo ที่สำรวจรอบนี้ (33 module, 67 entity, service ที่ใหญ่สุดถึง 2,996 บรรทัด)
Stack
| ส่วน | ค่า | หลักฐาน |
|---|---|---|
| Framework | NestJS 9 (@nestjs/core ^9.0.0) | pms-api/package.json (branch: uat):29 |
| ORM | TypeORM ^0.3.10 | pms-api/package.json (branch: uat):64 |
| Database | MSSQL — 4 connection ประกาศ, ใช้จริง 3 (main, workforce, workforceTemp) | pms-api/package.json (branch: uat):49, pms-api/src/app.module.ts (branch: uat):59-82 |
| Rate limiting | @nestjs/throttler ^6.4.0 — repo เดียวในกลุ่มที่มี global rate limit (100 req/60s) | pms-api/package.json (branch: uat):34, pms-api/src/app.module.ts (branch: uat):51-58,116 |
| Auth | Passport JWT global guard + @Public() override (pattern เดียวกับ benefit-api/recruitment-api) | pms-api/libs/jwt/jwt-auth.guard.ts (branch: uat) |
| Cron | @nestjs/schedule ^6.0.0 (เวอร์ชันใหม่กว่า benefit-api ที่ใช้ ^2.2.0) | pms-api/package.json (branch: uat):32 |
| PDF/Excel | puppeteer ^19.7.5, exceljs ^4.4.0, xlsx ^0.18.5 (มีทั้งสอง library สำหรับ Excel) | pms-api/package.json (branch: uat):58,45,65 |
nodemailer ^7.0.5 | pms-api/package.json (branch: uat):52 | |
| Language | TypeScript ^4.7.4 | pms-api/package.json (branch: uat):92 |
| Package manager | yarn (yarn.lock, Dockerfile รัน yarn) | pms-api/Dockerfile (branch: uat):19 |
Entry point และพอร์ต
- Entry point:
pms-api/src/main.ts (branch: uat):20-75— global prefix${BASE_PATH}api/v1, static asset/uploadsที่ prefix/pms-api/ - พอร์ตจาก
.env(uat):PORT=9331(pms-api/.env (branch: uat):6) ตรงกับ DockerfileEXPOSE 9331(pms-api/Dockerfile (branch: uat):25) และ fallback ในmain.ts(config.get('port') || 9331,main.ts:27) console.logถูก no-op ทิ้งทั้งหมดถ้าNODE_ENV === 'prod'(main.ts:16-18) — เป็น repo เดียวในกลุ่มที่แก้ปัญหา console.log ปนใน production log ด้วยวิธีนี้ (แม้จะเป็นวิธีที่หยาบ — ปิดทั้งฟังก์ชันระดับ global แทนแก้ที่ต้นเหตุ)- CORS ปรับปรุงกว่า repo อื่นในกลุ่ม — เขียนเป็น callback function ที่ block origin ที่มีคำว่า
localhostเมื่อNODE_ENV === 'prod'เท่านั้น ไม่ใช่origin: '*'เปิดกว้างแบบbenefit-api/recruitment-api(main.ts:45-66)
Deploy artifact
Dockerfile (branch: uat) — node:20-alpine + chromium/nmap/harfbuzz/freetype/nss (ชุดเดียวกับ benefit-api) — ต่างจาก benefit-api/recruitment-api ที่ใช้ yarn install --frozen-lockfile, pms-api ใช้ yarn install ไม่มี --frozen-lockfile (pms-api/Dockerfile (branch: uat):19 เทียบกับ benefit-api/Dockerfile (branch: prod):19) — เสี่ยงที่ build แต่ละครั้งได้ dependency version ต่างกันถ้า yarn.lock ไม่ sync กับ package.json
Database topology
pms-api ประกาศ TypeORM connection ไว้ 4 ชุด และใช้งานจริง 3 ชุด (ต่างจาก recruitment-api ที่ใช้จริงแค่ครึ่งเดียว):
| Connection name | env prefix | database | สถานะการใช้งาน |
|---|---|---|---|
main | DB_* | pms | ใช้งานจริงหนักสุด — entity ของ pms ทั้งหมด |
workforce | WORKFORCE_DB_* | dbWorkforce | ใช้งานจริงอย่างหนัก — อ่านข้อมูลองค์กร/พนักงานตรงจาก database ผ่าน TypeORM query builder ในโมดูล usagePermission, salaryPercentage, report, image, evaluations, evaluateUserAmount, employeeWorkforce, dropdown, budget, approver (10 โมดูล) |
workforceTemp | WORKFORCE_TEMP_DB_* | dbWorkforce_temp | ใช้จริงในโมดูล rcc เท่านั้น |
vtrc | VTRC_DB_* | vtrc | ประกาศไว้แต่ ไม่พบการ inject ใช้งานที่ใดในโค้ด (เหมือน pattern ที่พบใน recruitment-api) |
หลักฐาน — pms-api/src/app.module.ts (branch: uat):59-82, ยืนยันด้วยการ grep @InjectEntityManager() ทั่ว repo
ข้อสังเกตสำคัญที่สุดของ repo นี้ — pms-api เป็น domain microservice ที่มีการอ่านข้อมูลจาก database dbWorkforce ตรงโดย TypeORM query builder มากที่สุดในสี่ repo ที่สำรวจ ต่างจาก recruitment-api/benefit-api ที่เชื่อม legacy core ผ่าน HTTP เป็นหลัก — pms-api เลือกอ่านข้อมูลองค์กร/พนักงานตรงจาก database แทนเรียก workforce-api HTTP (แม้จะประกาศ workforceServer env ไว้ด้วยก็ตาม — ดู 04 Auth + integrations)
สิ่งที่ควรรู้ก่อนอ่านบทถัดไป
- ไฟล์
.envที่ commit อยู่ใน repo เป็น ค่า UAT (NODE_ENV=uat) ไม่ใช่ prod เหมือนอีกสาม repo — แต่ยังมี credential ที่ใช้งานได้จริงกับ database UAT และ JWT secret ที่เหมือนกันทุกตัวอักษรกับbenefit-api/recruitment-api/ai-recruitment-api(ยืนยันครั้งที่ 4 ว่าแพลตฟอร์มใช้ shared JWT secret ข้ามอย่างน้อย 4 microservice) - มีไฟล์
vtrc-gcp-sa-key.jsoncommit อยู่ที่ root เช่นเดียวกับrecruitment-api - พบ endpoint
GET /budget/getEmployeeSalaryเป็น@Public()— คืนข้อมูลเงินเดือนพนักงานตามหน่วยงานโดยไม่ต้อง login (ดู 06 ScorecardSEC-PMS-01) - มี cron job ที่รันทุก 1 นาที (
usagePermissionsync จาก workforce) — ดู 05 Cron jobs
สารบัญ
| บท | หัวข้อ |
|---|---|
| 01 | Repository map |
| 02 | Core pipeline — ตั้งตัวชี้วัด → ประเมินผล → อนุมัติ → ปรับเงินเดือน → export HRMI |
| 03 | Persistence — entities, ตาราง, ความสัมพันธ์ |
| 04 | Auth model + external integrations |
| 05 | Cron jobs |
| 06 | Scorecard + debt register |