Skip to content

0.2 · ภาพรวมระบบใน 1 หน้า

บทนี้วาดภาพใหญ่ของระบบทั้งหมดในหน้าเดียว ถ้าจำได้แค่หน้านี้ ก็พอที่จะ debug ได้ว่าปัญหาอยู่ตรงไหน

กฎเหล็กของระบบนี้ (จำให้ได้)

frontend ทั้งสองตัวคุยกับ API ตัวเดียวเท่านั้น คือ vtrc-api — ไม่มีทางเรียก centralize-api หรือ cu-central-api โดยตรง

ถ้าเจอปัญหาใน flow ข้อมูลของ frontend ให้ debug ที่ vtrc-api ก่อนเสมอ ไม่ใช่เริ่มที่ frontend


5 Repos ทำหน้าที่อะไรบ้าง

vtrc/
├── vtrc-web/              frontend ฝั่งพนักงาน (React 16 + AntD v3)
├── vtrc-rc-backoffice/    frontend ฝั่ง HR (React 16 + AntD v4 + MUI v5)
├── vtrc-api/              API แกนกลาง — ทุก request ผ่านที่นี่
├── centralize-api/        NestJS modernization template (REST/MSSQL) — ไม่ใช่ live hop ของ frontend
└── cu-central-api/        live identity + HR GraphQL ที่ vtrc-api เรียกจริง (Node 12 + LDAP)
RepoStackPortบทบาทสั้น
vtrc-apiNode 12 + Apollo 2 + Sequelize + MariaDB + Redis8081แกนกลาง ทั้ง frontend เรียกที่นี่
vtrc-webReact 16 + Webpack 4 + Apollo v2 + AntD v33000หน้าพนักงาน
vtrc-rc-backofficeReact 16 + CRA + Apollo v2 + AntD v4 + MUI v5 + Recoil3000หน้า HR
centralize-apiNestJS 9 + TypeScript + TypeORM + MSSQL + Swagger3000 (/api, /docs)modernization template — caller จาก vtrc-api ไม่ยืนยันใน workspace
cu-central-apiNode 12 + Apollo 2 + Sequelize + LDAP + Redis + MSSQLAPP_PORT default 8080 (ดูหมายเหตุพอร์ตด้านล่าง)live identity + HR data ที่ END_POINT_CENTRALIZE ชี้ไป

หมายเหตุพอร์ต cu-central-api — ในโค้ด cu-central-api/main-api/src/config.js ค่า default คือ APP_PORT = 8080 ส่วน vtrc-api/api/.env.example ตั้ง END_POINT_CENTRALIZE เป็น localhost:8082 (CLIENT_TARGET / mapping ของ env ตัวอย่าง) Dockerfile มี EXPOSE 9000 ซึ่งเป็น metadata ของ image ไม่ใช่ listen port จริง และ docker-compose.yml ของ cu-central มัก map พอร์ต 8000 — อย่าสรุปว่าแอปฟังที่ 9000


แต่ละ repo ทำอะไร แบบเจาะ

vtrc-api — ทุกอย่างผ่านที่นี่

เป็น API ที่ frontend ทั้งคู่เรียก ทำหลายอย่างมาก

  • authentication และ RBAC (@auth directive)
  • payslip, tax, salary certificate
  • leave (12 ประเภท) + multi-level approval
  • welfare withdrawal (WDHospital — 13-state machine)
  • provident fund
  • time attendance (read-only — ดึงจาก HRMI ผ่าน cu-central)
  • notification, news, document, policy
  • PDF generation (slip + tax + cert + ใบเสร็จ) ผ่าน routes.js
  • bridge ไป cu-central-api ผ่านโฟลเดอร์ centralize/ + END_POINT_CENTRALIZE (GraphQL) / END_POINT_CENTRALIZE_AUTH (REST auth)
  • cron jobs ใน crons.js (in-process, ไม่มี HA)

โครงภายในเป็น 3 layer: typeDefs (43 ไฟล์) → resolvers (41 ไฟล์) → lib/{controllers, repositories} (31+31 โฟลเดอร์) — รายละเอียดใน Volume 3

vtrc-web — หน้าพนักงาน

React SPA ที่พนักงานเปิดใน browser เน้นฟีเจอร์ดูข้อมูล (สลิป, เวลาทำงาน, ข่าว) และยื่นคำขอ (ลา, เบิกสวัสดิการ)

มีไฟล์ GraphQL operations อันเดียวที่ยาว 4,493 บรรทัด (src/graphql/queries.js) — เป็นไฟล์ที่ทุก query ของทุกหน้าอยู่รวมกัน

vtrc-rc-backoffice — หน้า HR

React SPA ที่ HR ใช้ เน้นฟีเจอร์อนุมัติและจัดการ

ไฟล์ operations ยาว 4,108 บรรทัด (queries.js) และ mutations ยาว 2,208 บรรทัด

มี axios instances 15 ตัว ใน src/config/ (axios*.js — เช่น axios-pms.js, axios-recruitment.js, axios-workforce.js, ...) — แต่ละตัวต่อ subsystem ของระบบย่อย บ่งชี้ว่า backoffice เป็น federated portal ของหลายระบบที่ glue รวมกันใน bundle เดียว

centralize-api — modernization template (แยกจาก live path)

NestJS + TypeScript + TypeORM + MSSQL + Swagger

เป็น repo เดียวที่ใช้ stack สมัยใหม่และมี pattern ที่ถูกต้อง (DTO validation, JWT guard, global exception filter, Swagger) — ทีมใช้เป็น template สำหรับ modernization ในอนาคต

อ่าน HR data จาก MSSQL (dbHRMI_Center + dbHRMI_Center_NBC) ผ่าน REST เช่น GET /api/employee, POST /api/hrPaySlip, POST /api/hrTimeTemp/import, ฯลฯ

ไม่ใช่ hop ที่ vtrc-api เรียกใน live payslip / time-attendance / auth flow ของ workspace นี้ — อย่าสับสนกับโฟลเดอร์ vtrc-api/api/src/centralize/

cu-central-api — live identity + HR data

Node 12 + Apollo 2 + LDAP + MSSQL + Redis

เป็นปลายทางจริงของ END_POINT_CENTRALIZE / END_POINT_CENTRALIZE_AUTH ดูแล

  • identity verification ผ่าน LDAP/AD ของจุฬา (พนักงานที่สังกัด CU) — REST /signin ฯลฯ ภายใต้ END_POINT_CENTRALIZE_AUTH
  • อ่าน/จัดการ HR raw data (MSSQL) ผ่าน Sequelize ของตัวเอง (db, dbHr, … ใน cu-central-api/main-api/src/connector.js)
  • OTP/SMS + SFTP file transfer
  • two-way sync กับ HRMI

4 Logical Databases

จุดที่ทำให้ระบบซับซ้อนที่สุด คือมี database แยกกัน 4 อัน บน engine 2 ตัว

MariaDB (engine เดียวกัน, host เดียวกัน)
├── schema: vtrc              ← เขียนโดย vtrc-api (db connection)
│   users, sessions, leave, withdraw, fund, ...
└── schema: vtrc-centralize   ← เขียนโดย vtrc-api (db2 connection)
    cross-schema join tables

MSSQL (HRMI — ระบบ HR ภายนอก)
├── dbHRMI_Center       ← อ่านโดย cu-central-api (live) + NestJS centralize-api (template)
└── dbHRMI_Center_NBC   ← อ่านโดย NestJS centralize-api (conn "nbc") — ชื่อเต็มในโค้ด/SQL
#DatabaseEngineOwnerทำอะไร
1vtrcMariaDBvtrc-api (db conn)application state — users, sessions, leave, withdraw, fund, ...
2vtrc-centralizeMariaDBvtrc-api (db2 conn)cross-schema join tables
3dbHRMI_CenterMSSQLcu-central-api (live) + centralize-api (template)HR Master Data (Employee, PaySlip VIEWs, ...)
4dbHRMI_Center_NBCMSSQLcentralize-api (และ SQL ที่อ้างชื่อนี้ใน NestJS)NBC variant (กลุ่มพนักงานแยก)

กฎสำคัญvtrc-api เป็น read-mostly consumer ของ HRMI ผ่าน GraphQL ของ cu-central-api และ ไม่ มี Sequelize MSSQL (dbHr) ใน vtrc-api/api/src/connector.js (export แค่ db กับ db2)

ฝั่ง cu-central-api มี two-way sync กับ HRMI — ดังนั้นกฎ "ไม่เคยเขียน MSSQL" ใช้กับ vtrc-api เป็นหลัก ไม่ใช่กับ cu-central ทั้งก้อน

ถ้าเจอโค้ดที่พยายาม UPDATE หรือ INSERT ลง MSSQL จาก path ของ vtrc-api โดยตรง ให้ระวัง — อาจเป็น bug หรือเป็น feature ที่ไม่ได้ activate


ข้อมูลวิ่งอย่างไรในการดูสลิปเงินเดือน (ตัวอย่าง)

ตัวอย่าง flow ที่ใช้กันบ่อยที่สุด — พนักงานกดดูสลิป

1. browser (vtrc-web)
   POST https://vtrcapi.redcross.or.th/api/graphql
   Headers: apiKey + Authorization: Bearer <jwt>
   Body: query fetchSlip(month, year)

2. vtrc-api
   - context(): เช็ค apiKey ว่าตรง API_DEVICE_KEY ไหม
   - ถ้าผ่าน, verify JWT (TTL 15 นาที) → ดึง sessionId
   - @auth(accessRole: ["USER"]) directive เช็ค session + role
   - เรียก lib/repositories/slip → centralize/controllers/slip.js

3. centralize/controllers/slip.js (ใน vtrc-api)
   - GraphqlCDWithToken → END_POINT_CENTRALIZE (GraphQL ของ cu-central-api)
   - header: API_CENTRALIZE_KEY

4. cu-central-api
   - GraphQL resolver คิวรี่ MSSQL VIEW (PaySlip)
   - ส่ง JSON กลับ

5. vtrc-api
   - ส่ง response กลับ frontend
   - (ไม่มี Redis key payslip:{emp}:{date} บน path นี้ — ไม่เขียน cache สลิป)

6. browser (vtrc-web)
   - render สลิปในหน้าจอ

ถ้าพนักงานกดดาวน์โหลด PDF จะเป็น flow อื่นที่ใช้ REST endpoint (ไม่ใช่ GraphQL) — ดูรายละเอียดใน Volume 11 · API Reference และคำเตือนเรื่อง security ใน บท 0.1


URL ที่ผู้ใช้รู้จัก

frontend เลือก GraphQL endpoint ที่จะยิงแบบ runtime โดยดูจาก window.location.href — แต่ละ frontend มี checkLinkURL() ของตัวเอง อย่ารวมตารางเป็นไฟล์เดียว

vtrc-webvtrc-web/src/config/apollo.js

Origin ที่ user เปิดGraphQL endpoint ที่ใช้
https://vtrc.redcross.or.th/https://vtrcapi.redcross.or.th/api/graphql
https://uat-vtrc.redcross.or.th/https://uat-vtrcapi.redcross.or.th/api-uat/graphql
http://localhost:3000/ (หรือ 192.168.0.105:3000)ชี้ไป UAT โดย default

vtrc-rc-backofficevtrc-rc-backoffice/src/config/apollo.js

Origin ที่ user เปิดGraphQL endpoint ที่ใช้
https://vtrcbackoffice.redcross.or.th/ หรือ https://rc-vtrcbackoffice.redcross.or.th/https://vtrcapi.redcross.or.th/api/graphql
https://uat-vtrcbackoffice.redcross.or.th/https://uat-vtrcapi.redcross.or.th/api-uat/graphql
https://uat-rc-vtrcbackoffice.redcross.or.th/https://uat-vtrcapi.redcross.or.th/api-uat/graphql
http://localhost:3000/ หรือ http://localhost:3001/ชี้ไป UAT โดย default
https://backoffice-vtrc.web.apphttps://api.vtrcapp.com/api-dev/graphql

สังเกตว่า prod ใช้ path /api/graphql แต่ UAT ใช้ /api-uat/graphql — เป็น pattern เดียวกันทั้ง frontend ทั้งคู่

ถ้าแก้ config ฝั่ง frontend อย่าทำผ่าน .env — ให้แก้ใน checkLinkURL() ของ frontend นั้น ตาม pattern เดิม ตามกฎใน .cursor/rules/workspace-structure.mdc


ขั้นตอนถัดไป

ไป บท 0.3 วันหนึ่งของพนักงาน →