Skip to content

1.9 · กองทุนสงเคราะห์ (Provident Fund)

บทนี้อธิบาย flow กองทุนสงเคราะห์ — เปลี่ยนอัตราสมทบ, เพิ่ม/แก้ผู้รับผลประโยชน์, และ cron job ที่ flush การเปลี่ยนแปลงอัตโนมัติ

VTRC เป็น "front desk" สำหรับพนักงาน — ข้อมูลจริงเก็บใน HRMI เพราะต้องคำนวณอัตราหักในสลิป


ภาพรวม feature

vtrc-api/api/src/typeDefs/providentFund.js:1-304

Queryหน้าที่
fetchAllProvidentFundDetailข้อมูลกองทุนครบ — policy, rate, history, beneficiary
fetchConfigChangeProvPercentageช่วงเวลาที่อนุญาตให้เปลี่ยน contribution rate
fetchListChangeProvPercentageประวัติการเปลี่ยน rate
fetchListFundApplicationใบสมัครเข้ากองทุน
fetchListFundBenefitPersonผู้รับผลประโยชน์
fetchFundChangeHistoryaudit trail
dropdownRelationShipLabeldropdown ความสัมพันธ์ (สำหรับ beneficiary)

PDF/Excel reports

  • fetchUrlFundApplicationExcel
  • fetchUrlFundRateChangeExcel
  • fetchUrlFundRateChangeSummaryReport
  • fetchUrlFundBenefitPersonSummaryReport

Member Status — 3 สถานะ

providentFund.js:287-294EmpFundStatusType enum

Statusหมายถึง
ISMEMBERสมาชิกปัจจุบัน
CANCELMEMBERเคยเป็นสมาชิก ตอนนี้ยกเลิกแล้ว
NOTMEMBERไม่เคยเป็นสมาชิก

หมายเหตุ — docstring มี typo "เป็ฯสมาชิก" (providentFund.js:288)


Request Status — 5 สถานะ

providentFund.js:296-302RequestFundStatus enum

Statusเปลี่ยนจากไหน
DRAFTตอน create
PENDINGsubmit จาก draft
SUCCESScron flush วันที่มีผล
CANCELผู้ใช้ยกเลิก
REJECTHR ปฏิเสธ

เปลี่ยน contribution rate — flow

พนักงานขอเปลี่ยนอัตราสมทบได้ "ในช่วงเวลาที่กำหนด" ต่อปี

1. fetchConfigChangeProvPercentage → ดูช่วงเวลาที่เปิดให้เปลี่ยน
   (providentFundEffectiveDate, provChangeDateFrom, provChangeDateTo)

2. ถ้าอยู่ในช่วง → พนักงาน createFundRateChange(newRate)
   status = PENDING

3. cron updateSuccessFundChangeRateByJob รันทุกนาที
   - ถ้าวันนี้ตรงกับ ProvidentFundEffectiveDate → flip ทุก PENDING เป็น SUCCESS
   - sync ไป HRMI
   - HRMI หักจากสลิปเดือนถัดไป

4. ถ้าไม่อยู่ในช่วง → fetchConfigChangeProvPercentage คืน isCanEdit = false
   พนักงานยื่นไม่ได้

Source — vtrc-api/api/src/crons.js:14-18 + lib/controllers/fund/fund.js:400-434

ช่วงเวลาเปลี่ยน rate — กำหนดโดยใคร

config อยู่ในตาราง MasterConfig ที่ HR แก้ได้

Fieldหน้าที่
configGroup = 'ProvidentFund'group
configType = 'ProvidentFundEffectiveDate'type
configValue1วันที่มีผล

HR ตั้งค่านี้ปีละครั้ง ก่อนปีภาษีใหม่


Field ของ ProvidentFundDetail

providentFund.js:157-169

graphql
type ProvidentFundDetail {
  employeeFundPolicy: EmployeeFundPolicy  # อัตราปัจจุบัน
  providentFundRateHistory: [...]          # ประวัติเปลี่ยน rate
  providentFundBenefitsPerson: [...]       # ผู้รับผลประโยชน์
  fundPolicy: [...]                        # policy ที่ใช้
  empFundStatusType: EmpFundStatusType     # ISMEMBER / CANCELMEMBER / NOTMEMBER
  applicationProvidentFund: ...            # ใบสมัคร
}

EmployeeFundPolicy

graphql
type EmployeeFundPolicy {
  provEmployerDeduct: Float       # อัตราหักฝั่งนายจ้าง (%)
  provEmployeeDeduct: Float       # อัตราหักฝั่งพนักงาน (%)
  fundPolicyName: String          # ชื่อนโยบาย
  policyFixedRate: Float          # อัตราคงที่
  policyMixRate: Float            # อัตราผสม
  policyEquityRate: Float         # อัตราตามอายุการงาน
  memberStatus: String
  provBeginAmount: Float          # ยอดคงเหลือตอนเริ่ม
  provEndAmount: Float            # ยอดคงเหลือตอนจบ
}

NeccessaryChangeProvData — ข้อมูลช่วงเปลี่ยน rate

providentFund.js:144-155

graphql
type NeccessaryChangeProvData {
  providentFundEffectiveDate: String   # วันที่มีผล
  provChangeDateFrom: String            # วันเปิดยื่น
  provChangeDateTo: String              # วันปิดยื่น
  salary: Float                         # เงินเดือนปัจจุบัน
  changeMin: Float                      # rate ต่ำสุดที่ตั้งได้
  changeMax: Float                      # rate สูงสุดที่ตั้งได้
  fundPolicyId: String
  provEmployeeDeduct: Float             # rate ปัจจุบัน
  isCanEdit: Boolean                    # เปิดให้แก้ไหม
}

ผู้รับผลประโยชน์ (Benefit Person)

createFundBenefitPerson / updateFundBenefitPerson / updateFundBenefitPersonArray (bulk)

แต่ละ beneficiary มี benefitsRate (เปอร์เซ็นต์) — ผลรวมต้องเท่ากับ 100%

Fieldหน้าที่
relationshipความสัมพันธ์ (ดึงจาก dropdownRelationShipLabel)
fullNameชื่อผู้รับ
idCardidCard
birthDateวันเกิด
benefitsRateเปอร์เซ็นต์ (0-100)
orderNoลำดับกรณีเสียชีวิตพร้อมกัน

updateFundBenefitPersonArray ใช้สำหรับ bulk update status (เช่น approve/reject หลายคนพร้อมกัน)

PDF — createFundBenefitPersonFormPDF สร้าง PDF ฟอร์มให้พิมพ์ลงนาม


Mutations ทั้งหมด

Mutationหน้าที่Auth
createFundRateChangeขอเปลี่ยน rateUSER
updateFundRateChangeแก้คำขอUSER
createFundApplicationยื่นใบสมัครสมาชิกUSER
forceUpdateSuccessStatus(HR) บังคับ flip เป็น SUCCESSSUPER_ADMIN
createFundBenefitPersonเพิ่มผู้รับผลประโยชน์USER
updateFundBenefitPersonแก้ผู้รับUSER
updateFundBenefitPersonArraybulk update statusADMIN+
createFundBenefitPersonFormPDFสร้าง PDFUSER

Cron — อัตโนมัติ

crons.js:14-18รันเฉพาะ instance APP_NO === 1 (single-instance guard เพราะ vtrc-api รัน 4 replicas)

ScheduleJobหน้าที่
* 1 * * * * (ทุกนาที)updateSuccessFundChangeRateByJobflip PENDING → SUCCESS ถ้าวันนี้ตรง effective date
30 3 * * * (03:30 ประจำวัน)updateDelegatesExpireexpire delegate ที่หมดอายุ

Manual override

forceUpdateSuccessStatus + updateSuccessFundChangeRateByForce (fund.js:436+) — HR บังคับ flip โดยไม่รอ cron กรณีฉุกเฉิน


Models — ตาราง MariaDB

vtrc-api/api/src/models/core/fund/

Modelหน้าที่
fundRequest.jsคำขอทั่วไป (rate change, application)
fundRequestHistory.jsaudit trail
fundRateChange.jsคำขอเปลี่ยน rate โดยเฉพาะ
fundDocument.jsเอกสารแนบ
fundBenefitPerson.jsผู้รับผลประโยชน์
fundApplication.jsใบสมัครสมาชิก

Export — Excel reports

routes.js:1219-1274

EndpointOutput
GET /fund/application/excelใบสมัคร Excel
POST /fund/ratechange/excelzip ของ rate change แยกตาม sourceDB

rate change export — วนลูป convertedData แยกตาม sourceDB แล้วสร้าง Excel แต่ละอัน ชื่อไฟล์ เปลี่ยนนโยบายกองทุน_${mapSourceDBName[key]}.xlsx ทั้งหมด zip รวมกัน


ข้อควรระวัง

  • cron รันเฉพาะ APP_NO === 1 — ถ้า docker-compose รันใหม่และ APP_NO ผิด จะไม่มี cron ทำงาน
  • ช่วงเปลี่ยน rate ปิดแล้ว — พนักงานยื่นไม่ได้ ต้องรอปีถัดไป (หรือ HR override)
  • benefitsRate ผลรวมต้อง 100% — ถ้าไม่ครบ HRMI ปฏิเสธ
  • sync ไป HRMI เป็น batch ไม่ใช่ real-time — เหมือน TaxDraft
  • การ force update ทิ้ง audit trail ไม่ครบ — ใช้ด้วยความระมัดระวัง

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

ไป บท 1.10 เวลาทำงาน (Time Attendance) →