Skip to content

1.7 · สวัสดิการรักษาพยาบาล (WDHospital)

บทนี้อธิบาย flow การเบิกค่ารักษาพยาบาล — เป็น state machine 13 states ที่ซับซ้อนที่สุดในระบบ

ความแตกต่างจากการลา — WDHospital เก็บใน VTRC เอง (ไม่ได้ไปฝาก HRMI เป็น source of truth) และ approver เก็บในตาราง MasterApprovers ของ VTRC ด้วย


ความสัมพันธ์ที่เบิกได้

พนักงานเบิกให้ตัวเองหรือคนในความดูแลได้ — vtrc-api/api/src/config.js:392-429 (relationHrmi)

Codeความสัมพันธ์หมายเหตุ
00ตัวเองself-claim
10บิดา
20มารดา
70คู่สมรส
81บุตรคนที่ 1
82บุตรคนที่ 2
83บุตรคนที่ 3
84บุตรคนที่ 4
85บุตรคนที่ 5

policy "เบิกให้บุตรได้สูงสุด 5 คน" เป็น policy ที่ hardcode ใน code ผ่าน list นี้ — ถ้า HR อยากขยายเป็น 6 คน ต้องแก้ code ไม่ใช่แก้ MasterData


13-state machine

models/core/withdraw/hospital.js:94-97 — status enum ทั้งหมด

Statusหมายถึงเปลี่ยนจากไหน / โดยใคร
DRAFTแบบร่างตอน create (hospital.js:1396)
PENDINGรอตรวจสอบsubmit จาก DRAFT
MOREINFOขอข้อมูลเพิ่มapprover
APPROVEอนุมัติ รอโอนเงินapprover level สุดท้าย (hospital.js:1508)
REJECTไม่อนุมัติapprover
PAIDเงินเข้า (bank) — mark ด้วยมือHR/admin ตั้ง status PAID (ไม่ใช่ผลจาก KBANK import)
PAIDCASHเงินเข้า (เงินสด)HR mark จ่ายสด
CASHรอจ่ายเงินสดเลือก channel
FAILEDKBANK ล้มเหลวKBANK import — code 6, 7, 8, 10
SUCCESSKBANK โอนสำเร็จKBANK import — code 9statusKcash.status = SUCCESS (label PAID / โอนสำเร็จ)
CANCELยกเลิกหลายทาง
CANCELDOCยกเลิกเอกสารHR
EDITadmin แก้หลังสร้างadmin

หมายเหตุ — code K-Cash 9 มี label PAID / โอนสำเร็จ แต่ค่าที่เขียนลง WDHospital.status คือ SUCCESS (config.js:508-511) — ไม่ใช่ status document PAID จาก import และ PAID ≠ alias ของ SUCCESS

PAIDCASH และ CASH ก็เช่นกัน — เป็น channel คู่ขนานกับ bank


State Diagram

            ┌─────────┐
            │  DRAFT  │ ← create (status เริ่มต้น)
            └────┬────┘
                 │ submit

            ┌─────────┐
   ┌───────►│ PENDING │◄─────────────┐
   │        └────┬────┘              │
   │             │                   │
   │             ├──► MOREINFO ──────┤ resubmit (พนักงานแก้)
   │             │                   │
   │             ├──► REJECT         │
   │             │                   │
   │             ├──► EDIT (admin) ──┤
   │             │                   │
   │             ▼                   │
   │        ┌─────────┐              │
   │        │ APPROVE │              │
   │        └────┬────┘              │
   │             │                   │
   │             ├──► CASH ──► PAIDCASH
   │             │                   │
   │             ├──► export KBANK   │
   │             │     │             │
   │             │     ▼             │
   │             │  WDExport batch   │
   │             │     │             │
   │             │     ▼             │
   │             │  KBANK process    │
   │             │     │             │
   │             │     ├──► SUCCESS (code 9)
   │             │     └──► FAILED ─┘
   │             │                   │
   │             └──► CANCEL ────────┤
   │                                 │
   └─────────────────────────────────┘
                (retry path)

Approval Chain — MasterApprovers

ผู้อนุมัติ WDHospital เก็บใน VTRC ไม่ใช่ HRMI

models/core/masterData/masterApprovers.js:1-56

Fieldหน้าที่
approverId (UUID)PK
empCodeรหัสพนักงานของผู้อนุมัติ
userIdFK → User
orgCodeหน่วยงานที่ดูแล
orgNameชื่อหน่วยงาน
isActive0/1
typeenum "MEDICAL" (ตอนนี้มีแค่ type นี้)
createdBy / updatedByaudit

HR จัดการผ่านเมนู MasterApprovers — เพิ่ม/แก้/ปิด active ตาม orgCode


เมื่อ create WDHospital — อะไรเกิดขึ้นบ้าง

lib/controllers/withdraw/hospital.js:1357-1465

  1. บังคับ status DRAFT (hospital.js:1396) — ไม่ใช่ PENDING ทันที
  2. orderNo = 1
  3. Generate withdrawNo ผ่าน getWithdrawNo() (running number)
  4. ถ้า orgCode == "88"empType = "บำนาญ" (hospital.js:1388) อัตโนมัติ ไม่งั้น empType = "เจ้าหน้าที่"
  5. Query MasterApprovers ด้วย { orgCode, isActive: 1, type: 'MEDICAL' }
  6. ส่ง WELFARE notification ให้ผู้อนุมัติทุกคน title "รออนุมัติ" + redirect_path: /hospital/Confirm/{id}

ข้อสังเกต — notification redirect ไป /hospital/Confirm/ (role approver) ไม่ใช่ /hospital/ (role พนักงาน) ตาม redirectWDHospitalPath (wdHospital.js:170-173)


Field สำคัญใน WDHospital

models/core/withdraw/hospital.js:1-236

Fieldหน้าที่
wdHospitalId (UUID)PK
withdrawNoเลขที่เอกสาร (running)
withdrawOrderลำดับ
documentNoเลขเอกสารอ้างอิง
relationcode ความสัมพันธ์ (00, 10, 20, 70, 81-85)
totalWithdrawยอดขอเบิก
totalCurrentWithdrawยอดที่อนุมัติจริง
previousCurrentWithdrawยอดเบิกครั้งก่อน
coaCodeNameเลขงบ (chart-of-accounts)
hospitalNameชื่อโรงพยาบาล
hospitalBankAccountIdบัญชีธนาคารของโรงพยาบาล
hospitalTypeประเภทโรงพยาบาล
sicknessName / sicknessIdโรค
patientTypeประเภทคนไข้
privateCaseกรณีผู้ป่วยส่วนตัว
treatmentStartDate / EndDateวันที่รักษา
refDocumentเอกสารอ้างอิง
noteApproveหมายเหตุผู้อนุมัติ
bankKBANK หรือ OTHER
cashFlgflag จ่ายเงินสด
payCashBy / payCashDate / effectivePayDateเมื่อจ่ายสด
importStatus / importLabelผล KBANK
exportRefCode / wdExportIdbatch export
isJuristicนิติบุคคล
statusenum 13 states
isHistory0 = current, 1 = snapshot ประวัติ

Pre-check ก่อนจ่ายเงิน

checkPersonnelResignation(wdHospitalIds) (wdHospital.js:168)

ก่อน export หรือจ่าย — HR ตรวจว่าพนักงานที่จะจ่ายให้ "ลาออกแล้วหรือยัง"

ผลลัพธ์

graphql
type ResignationPersonnel {
  status: String
  empCode: [String]
  withdrawNo: [String]
}

HR เห็นในหน้าจอ → ตัดสินใจด้วยตัวเองว่าจะจ่ายหรือไม่ ระบบไม่ block อัตโนมัติ


Export ไป KBANK

flow การส่งออก batch จ่ายผ่านธนาคารกสิกรไทย (KBANK K-Cash)

  1. HR เลือก WDHospital ที่ status APPROVE หลายรายการ
  2. เรียก createExportWDHospital(wdHospitalIds, years, payDate, totalExport, wdHospitalDatas)
  3. ระบบสร้าง row ใน WDExport (table tracking batch)
  4. stamp wdExportId + exportRefCode ในแต่ละ WDHospital
  5. HR download zip ผ่าน fetchUrlExportWdHospital

zip ประกอบด้วย 3 ไฟล์ (routes.js:776-811)

FileEncodingหน้าที่
${exportCode}_KBank_welfare.txtTIS-620K-Cash payroll input
${exportCode}_Smartcredit_welfare.txt(default)SmartCredit input
${exportCode}_FMIS.xlsxbinaryFMIS accounting Excel

เงื่อนไข — KBANK text ถูกสร้างเฉพาะเมื่อ length > 179 (routes.js:803)


การ import ผล KBANK

KBANK process ไฟล์เสร็จ → ส่งไฟล์ผลกลับมา → HR upload ผ่าน importUpdateStatus(file)

lib/controllers/withdraw/hospital.js:2160-2316

algorithm

  1. Parse ไฟล์ — row header (header == 'h') ระบุ exportCode, row อื่นเป็น detail
  2. แต่ละ row — map element.status (K-Cash code) ผ่าน statusKcash (config.js:488-519)
K-Cash codeVTRC statuslabel / คำอธิบาย
9SUCCESSlabel PAID / โอนสำเร็จ — ไม่เขียน status PAID
6FAILEDduplicate + stoppay
7FAILEDcancelled
8FAILEDstoppay
10FAILEDunsuccessful credit
  1. Validate ยอด — totalCurrentWithdraw ในไฟล์ต้องตรงกับ DB (hospital.js:~2230)
  2. Update WDHospital
js
WDHospital.update({
  importStatus: element.status,
  status: statusByKcash.status,        // SUCCESS หรือ FAILED
  importLabel: statusByKcash.labelTH,
  effectivePayDate: element.effectivePayDate
})
  1. เขียน WDHistory row + snapshot WDHospital (isHistory=1)
  2. เมื่อ wdExportData.totalExport == totalImportWDExport.isImport = 1 (batch ปิด)

Channel เงินสด (Cash)

ถ้า HR เลือกจ่ายเงินสดแทนผ่านธนาคาร — cashFlg = 1 และ status เป็น CASH หรือ PAIDCASH

Fieldใช้ตอนไหน
bank = 'OTHER'ไม่ใช่ KBANK
cashFlg = 1จ่ายสด
payCashBy (UUID)ใครจ่าย
payCashDateวันที่จ่าย
effectivePayDateวันมีผล

flow นี้ไม่ผ่าน KBANK — HR mark จ่ายด้วยมือในหน้า backoffice


Cancel export

cancelExportWDHospital (wdHospital.js:398)

HR สามารถ cancel batch export ทั้ง batch ได้ ถ้ายังไม่ import ผล

  • WDHospital ทุกตัวใน batch reset status กลับเป็น APPROVE (hospital.js:2393)
  • WDExport.isCancel = 1 (export.js:26-30)

ประเภทค้นหาใน backoffice

BackOfficeSeachType enum (wdHospital.js:611-618)

Codeview
ALLWDLISTทั้งหมด
PAYWDLISTรอโอน/จ่าย
FAILEDWDLISTล้มเหลว

SearchDetailType enum (wdHospital.js:602-609)

Coderole
DETAILพนักงานดูของตัวเอง
CONFIRMapprover ดูที่ต้องอนุมัติ
BACKOFFICEHR

Associations — relation กับตารางอื่น

models/core/withdraw/hospital.js:247-259

WDHospital
├── hasMany WDSlip            (ใบเสร็จหลายใบ)
├── hasMany WDHospitalDocument (เอกสารอื่น)
├── hasMany Approver
├── hasMany MasterApprover    (by orgCode)
├── belongsTo WDHistory
├── belongsTo WDExport
├── belongsTo Sickness        (2 alias)
├── belongsTo Hospital        (2 alias)
└── belongsTo HospitalBankAccount

WDSlip สำคัญ — แต่ละ WDHospital มีได้หลายใบเสร็จ และยอดเบิก = ผลรวมของ slip ทั้งหมด


รายงาน — PDF + Excel

lib/controllers/withdraw/hospital.template.js (imported at routes.js:26) — template ทั้งหมด

QueryTemplate
fetchUrlFailPaymentPDFfailPaymentReportTemplate
fetchUrlAllWithdrawPDFReportsumOverveiwReportTemplate + variants
fetchUrlWDHospitalApproverPDFReportsumCoAReportTemplate ฯลฯ
fetchUrlWDHospitalPaidPDFReportsumWDHospitalPaidTemplate

template แบ่งตามมุมมอง

  • by chart-of-accounts (sumCoAReportAllOrgTemplate, sumCoAReportTemplate)
  • by division (sumDivisionReportTemplate)
  • by organization (sumOrganizeReportTemplate)
  • by person (sumPersonalReportTemplate)
  • overview (sumOverveiwReportTemplate)
  • paying prepare (sumPayingPrepareTemplate)

รายละเอียดเพิ่มเติมใน บท 1.14


Checklist ตอน debug

อาการสาเหตุ
"อนุมัติแล้วไม่เห็นเงิน"ยังไม่ export KBANK หรือ KBANK ยังไม่ import
"KBANK ตีก"K-Cash code 6, 7, 8, 10 — ดู importLabel ใน WDHospital
"ยอดในไฟล์ไม่ตรง DB"import ปฏิเสธ (hospital.js:~2230)
"หา approver ไม่ได้"MasterApprovers.isActive = 0 หรือไม่มี row สำหรับ orgCode นี้
"สถานะ APPROVE แต่ export ไม่ได้"wdExportId ติด batch ที่ isCancel = 0 อยู่
"พนักงานลาออก แต่ยังโอนได้"checkPersonnelResignation แค่ flag ไม่ block

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

ไป บท 1.8 สวัสดิการอื่นๆ →