1.3 · วงจรชีวิตพนักงาน
บทนี้เล่าว่าพนักงานคนหนึ่ง "เข้ามาอยู่ในระบบ VTRC" และ "ออกจากระบบ" อย่างไร — ตั้งแต่วันแรกที่ HRMI สร้าง record จนถึงวันลาออก
เนื้อหาส่วนใหญ่เป็น integration point ระหว่าง HRMI และ VTRC ไม่ใช่ implementation detail ของฝั่งเดียว
แผนภาพวงจรรวม
HRMI สร้าง employee record
│
│ (EmpCode ถูกกำหนดใน HRMI)
▼
พนักงานยังไม่มี account ใน VTRC
ต้อง "register" ผ่าน verifyEmpCodeLogin
│
▼
Step 1: verifyEmpCodeLogin
- ป้อน EmpCode + captcha
- ระบบสร้าง LoginSession (TTL 15 นาที)
- ส่ง password default ไป
│
▼
Step 2: login(lsid, password)
- ถ้าผ่าน → สร้าง User + Session
- ครั้งแรก: บังคับเปลี่ยน password
│
▼
ใช้ระบบปกติ (ตลอดการจ้าง)
│
▼
HRMI mark "resignationDate"
VTRC ยังเห็น record แต่ deny action
│
▼
Session หมดอายุ + ไม่ login ได้อีก
(VTRC ไม่ลบ User row — ปล่อยทิ้งไว้)Step 1 — ยืนยันตัวตนครั้งแรก
เมื่อพนักงานใหม่เข้ามาใช้ระบบครั้งแรก เขายังไม่มี account ใน VTRC
ต้องผ่าน verifyEmpCodeLogin — vtrc-api/api/src/typeDefs/authentication.js:10-17
Input:
empCode รหัสพนักงาน
captchaText ตัวอักษรจากภาพ
captchaUid ID ของ captcha session
organization เลือก context (RC หรือ CU)
csId device identifier
workflow SIGNIN | RESET_PASSWORD
Output:
LoginSession {
lsid login session id
exp expire time (15 นาที)
stat status flag
form ข้อมูลฟอร์มขั้นถัดไป
}ขั้นตอนภายใน — VTRC forward EmpCode ไป HRMI เพื่อ verify ว่ามีคนนี้จริง ถ้าผ่านจะสร้าง LoginSession row ใน MariaDB (loginSession.js:43) ที่มี TTL 15 นาที และจำกัด 3 attempts
ถ้าพนักงานกรอกผิดเกิน 3 ครั้ง — LoginSession ถูก lock ต้องรอหมดอายุแล้วเริ่มใหม่
Step 2 — Login ครั้งแรก
หลัง verify ผ่าน พนักงานใส่ password เพื่อเรียก login — authentication.js:26-32
Input:
lsid login session id (จาก step 1)
password password
clientInfo browser/device info
apiKey device key
organization context
Output:
Auth {
accessToken JWT 15 นาที
refreshToken token ยาวสำหรับ refresh
}ครั้งแรกที่ login สำเร็จ — ระบบ
- สร้าง
Userrow ใน MariaDB (ถ้ายังไม่มี) —param = empCode(typeDefs/user.js:57-61) - ผูก
role = USERโดย default - สร้าง
Sessionrow TTL 1 วัน - Return JWT
พนักงานสามารถเลือก profile ได้ถ้ามีหลาย profile (changeCurrentProfile) — เช่นกรณีเป็นทั้งพนักงานกาชาดและ affiliated จุฬา
Step 3 — ใช้ระบบตลอดการจ้าง
ในสถานะปกติ ทุก request แนบ Authorization: Bearer <jwt> + apiKey header
JWT TTL 15 นาที — เมื่อใกล้หมดอายุ frontend ใช้ refreshToken ขอใหม่ (authentication.js:54-61)
ถ้า JWT หมดอายุก่อน refresh — user ต้อง login ใหม่
Profile typeDef expose flag ที่ gate ฟีเจอร์ (profile.js:43-87)
| Flag | หมายถึง |
|---|---|
isHr | มีบทบาท HR |
isKCMH | พนักงานโรงพยาบาลจุฬาฯ (King Chulalongkorn Memorial Hospital) |
isPlasma | อยู่ในกลุ่ม plasma (ธนาคารเลือด) |
isEmployeeManagement | มีสิทธิ์จัดการพนักงาน |
isEmployeeApprover / isEmployeeApproverLeave | มีสิทธิ์อนุมัติ (ทั่วไป / การลา) |
isCanLeave | สามารถยื่นคำขอลา |
isBC | (TBC — ถาม HR) |
ระหว่างทาง — เปลี่ยนข้อมูลส่วนตัว
พนักงานสามารถเปลี่ยนข้อมูลได้บางส่วนผ่าน VTRC บางส่วนต้องทำที่ HRMI
| ข้อมูล | เปลี่ยนที่ไหน |
|---|---|
| Password | VTRC (forgetPassword flow + SMS OTP) |
| ชื่อ-สกุล | HRMI เท่านั้น |
| ที่อยู่ | VTRC (updateAddress) |
| เบอร์โทร | HRMI (เพราะใช้ส่ง SMS OTP) |
| บัญชีธนาคาร | HRMI |
| Profile beneficiary (กองทุนสงเคราะห์) | VTRC (createFundBenefitPerson) |
| Tax allowance | VTRC (createTaxDraft — บันทึก draft, sync ไป HRMI) |
รายละเอียดฝั่ง tax — ดู บท 1.5
Step 4 — ลาออก / เกษียณ
เมื่อพนักงานลาออก HRMI mark resignationDate ใน record — VTRC ไม่ได้เป็นคนตั้งค่านี้
ผลกระทบใน VTRC
fetchEmployeeDetail(user.js:43-48, 184-198) คืนworkingStatusและresignationDate— ใช้ตรวจก่อนยื่นคำขอลาหรือเบิกสวัสดิการ- การเบิก WDHospital มี precheck
checkPersonnelResignation(wdHospitalIds)(wdHospital.js:168) ที่ flag พนักงานที่ลาออกแล้ว ให้ HR ตัดสินใจก่อนจ่าย - Session ที่ active ยังใช้ได้จนหมดอายุ — แต่ action ใหม่ถูกปฏิเสธ
- ในทางปฏิบัติ user จะโดน "fetch employee detail ไม่ได้" → login ใหม่ไม่ผ่าน
พนักงานกลุ่ม orgCode == "88" (ผู้รับบำนาญ) เป็นกรณีพิเศษ — ยังใช้ระบบได้ แต่ flow การเบิกสวัสดิการต่างจากพนักงานปกติ (withdraw/hospital.js:1388)
กรณีพิเศษ — ผู้รับบำนาญ
orgCode == "88" → ระบบ tag empType = "บำนาญ" อัตโนมัติ (withdraw/hospital.js:1388)
กลุ่มนี้
- ยังเบิกสวัสดิการรักษาพยาบาลได้
- สลิปเงินเดือนกลายเป็น "เงินบำนาญ" — label เปลี่ยนตาม (
slip.js:255-294) - ไม่สามารถยื่นคำขอลาใหม่ได้ (เป็นเรื่องเชิง business — HRMI กำหนด)
การ reset password — flow SMS OTP
ถ้าลืม password — forgetPassword flow ใน typeDefs/user.js:16-33, 99-107
1. forgetPassword(empCode) → ส่ง SMS OTP ไปเบอร์ที่ลงทะเบียน (จาก HRMI)
2. checkSMSforgetPassword(empCode, verificationCode) → ถ้าผ่าน ได้ lsid
3. resetPassword(lsid, identityCard, verificationCode, birthDate,
organization, password, confirmPassword)
- ตรวจ identityCard + birthDate เพิ่ม (defense in depth)
- ถ้าผ่าน → override password ใน HRMIOTP TTL 15 นาที — เท่ากับ LoginSession
ถ้าเบอร์โทรใน HRMI ไม่ตรง — OTP ไม่ถึง และ VTRC ไม่สามารถแก้เบอร์ให้เองได้ พนักงานต้องติดต่อ HR ให้แก้ใน HRMI
การจัดการผู้ใช้ฝั่ง HR
HR ใช้เมนู ManageUser (menu key manageUser) จัดการบัญชีผู้ใช้
| Mutation | หน้าที่ | สิทธิ์ |
|---|---|---|
searchUser | ค้นหาพนักงานด้วย EmpCode/ชื่อ/identityCard | ADMIN+ |
changeRole | เปลี่ยน role ของ user (เช่น STAFF → ADMIN) | SUPER_ADMIN |
createUserRole | เพิ่ม role ให้ user | SUPER_ADMIN |
revokeRole | ลบ role ออกจาก user | SUPER_ADMIN |
fetchEmployeeDetail | ดูรายละเอียดการจ้าง | ADMIN+ |
Source — typeDefs/user.js:81-97, 35-48
ข้อควรระวัง
- VTRC ไม่เคย "ลบ" User row แม้พนักงานลาออก — เพราะต้องเก็บประวัติเพื่อ audit และออกเอกสาร
- พนักงานที่สังกัด CU (profile
dbHRMI_CU_*) ใช้tokenCDที่แตกต่างจาก RC — บางครั้ง flow ทำงานต่างกัน loginBypass(asid, ...)ใช้สำหรับ subsystemTWOWAYเท่านั้น — ห้ามเรียกจาก WEB/MOBILE เพราะข้าม authentication