14.3 · Scorecard — Business-logic correctness debt
รายการนี้ tag BIZ และใช้ prefix CORR- เป็นหลัก (correctness/data-integrity) — เป็น debt ที่เกิดจาก flow ข้าม repo ใน 14.2 ไม่ใช่ debt ระดับ repo เดี่ยวที่มีอยู่แล้ว (เช่น CORR-BENEFIT-01, CORR-WORKFLOW-01) — ID ใหม่ในนี้อ้างอิง (aggregate) จาก ID ระดับ repo เดิมเมื่อเกี่ยวข้อง
Severity: Critical
CORR-BIZ-01 · WdHospitals มีข้อมูลอยู่ 2 schema พร้อมกัน ไม่มี source of truth เดียว
ที่ — benefit.wdHospitals (benefit-api) เทียบกับ vtrc.WDHospitals (vtrc-api cluster D, withdraw/hospital.js) — sync เกิดผ่าน raw SQL manual เฉพาะ flow cancel/update bank detail เท่านั้น (ดู 14.2.1)
ผลกระทบ — ถ้ามี flow ใหม่ในอนาคตที่เขียนฝั่งเดียวแล้วลืมอีกฝั่ง (เช่น เพิ่ม field ใหม่ที่ทีม benefit-api ไม่รู้ว่าต้อง mirror กลับ vtrc.WDHospitals) ข้อมูลจะ drift แบบเงียบ — เพราะทั้งสอง schema มี state machine คนละชุด (vtrc-api เดิมมี 13-state machine เต็ม ส่วน benefit-api มี state machine ของตัวเอง) จึงไม่มีทางบอกได้ง่ายว่า "สถานะไหนคือ authoritative" เมื่อสอง schema ขัดกัน — อ้างอิง CORR-BENEFIT-01 ระดับ repo ที่ benefit-api/06-scorecard
CORR-BIZ-02 · Export ไป HRMI อาศัยมนุษย์ทำต่อจากอีเมล — ไม่มี API sync ที่ยืนยันได้ใน 2 process
ที่ — Recruitment: recruitment-api ContractService ส่ง email แจ้ง HRMI แทน API call (recruitment-api/02-core-pipeline); Performance evaluation: pms-api SalaryAdjustToHRMIModule export เป็นไฟล์ Excel ให้ทีม HR นำเข้าด้วยมือ (pms-api/02-core-pipeline)
ผลกระทบ — ทั้งสอง flow เปลี่ยนสถานะฝั่งตัวเอง (hired, salary adjustment confirmed) ก่อน ที่ HRMI จะถูกอัปเดตจริง — ถ้าเจ้าหน้าที่ HRMI พลาดไม่ได้บันทึกตามอีเมล/ไฟล์ Excel ระบบต้นทางจะรายงานว่า flow เสร็จสมบูรณ์ทั้งที่ HRMI ยังไม่มีข้อมูลจริง ไม่มี reconciliation job ที่ตรวจสอบว่า HRMI ได้รับข้อมูลจริงหรือไม่ในทั้งสอง flow
Severity: High
CORR-BIZ-03 · Cron sync dbWorkforce → pms-api ไม่มี health-check/alert
ที่ — pms-api UsagePermissionService.handleCron (@Cron('*/1 * * * *')) — pms-api/02-core-pipeline §workforce sync
ผลกระทบ — ถ้า cron หยุดทำงานเงียบ ๆ (crash, deploy ผิด, DB connection หลุด) ข้อมูลองค์กร/ตำแหน่ง/salary range ที่ EvaluateFormModule/ConfirmEvaluationModule/SalaryAdjustment ใช้จะ drift จาก dbWorkforce โดยไม่มี alert ตรวจจับได้แค่ตอนผลประเมิน/เงินเดือนที่คำนวณผิดปกติถูกสังเกตเห็นโดยมนุษย์ — severity สูงเพราะกระทบการคำนวณเงินเดือนจริงของพนักงานทั้งองค์กร
CORR-BIZ-04 · HTTP call ข้าม repo แบบ fire-without-compensation — พบซ้ำ 4 จุด
ที่ — benefit-api→vtrc-api (cancelStudyEducation, 14.2.2), benefit-api→centralize server (14.2.1), recruitment-api→workforce-api (14.2.4), meeting-vtrc-api→vtrc-api/cu-central-api (14.2.6)
ผลกระทบ — ไม่มีจุดใดใน 4 จุดนี้ที่มี retry/timeout ที่กำหนดเอง หรือ compensating transaction ถ้า network ล้มกลางทาง — caller ไม่มีทางรู้ว่าฝั่งปลายทางประมวลผลสำเร็จหรือไม่ ต้องพึ่งการตรวจสอบด้วยมือถ้าเกิดข้อผิดพลาดกลางทาง เป็น pattern เชิงโครงสร้างที่พบซ้ำข้าม 4 คู่ repo ไม่ใช่ปัญหาเฉพาะจุดเดียว
CORR-BIZ-05 · Time attendance ไม่มี business logic ที่ยืนยันได้ในเวิร์กสเปซนี้
ที่ — vtrc-api timeAttendance/ controller มีแค่ 9 บรรทัดเป็น pass-through พร้อม dead import (vtrc-api/06-controllers §Cluster B)
ผลกระทบ — process "meeting/attendance" ที่ระบุไว้ในสโคปเอกสารนี้มีเพียงส่วน "meeting" ที่ trace ได้เต็ม ส่วน "attendance" (เช็คชื่อเข้า-ออกงาน) ไม่มีหลักฐานว่าอยู่ที่ไหน — เป็นไปได้ว่าอยู่ที่ HRMI/ระบบภายนอกที่ไม่อยู่ใน workspace นี้ ทำให้ไม่สามารถยืนยันได้ว่าข้อมูล attendance ที่ใช้ประกอบการประเมินผลงาน (pms-api) หรือคำนวณเงินเดือนมีความถูกต้องอย่างไร — ทำเครื่องหมาย UNVERIFIED ไม่ใช่ debt ที่ยืนยันขนาดแน่ชัด แต่เป็นช่องว่างความรู้ (knowledge gap) ที่ต้องปิดก่อนจะสรุป audit เรื่อง payroll ได้ครบ
Severity: Medium
QUAL-BIZ-01 · Shared database (recruitment_ai) ไม่มี API contract คุ้มกัน schema change
ที่ — recruitment-api (TypeORM, connection ai) และ ai-recruitment-api (mssql driver ตรง) ต่อ database recruitment_ai เดียวกัน (14.2.3)
ผลกระทบ — ไม่มี compile-time check ใด ๆ ข้าม repo ถ้า recruitment-api เปลี่ยน schema (rename/drop column) ทีม ai-recruitment-api จะไม่รู้จนกว่า runtime error เกิดขึ้นจริง — ต่างจาก network-based coupling ที่อย่างน้อยมี API contract (แม้ไม่ formal) ให้ตรวจสอบได้ระดับหนึ่ง
QUAL-BIZ-02 · WORKFORCE_SERVER/workforce-api mount บน domain เดียวกับ vtrc-api แต่ identity ไม่ยืนยัน
ที่ — recruitment-api เรียก ${WORKFORCE_SERVER}/workforce-api/api/restful โดย WORKFORCE_SERVER=https://vtrcapi.redcross.or.th — ไม่มี repo ชื่อ workforce-api อยู่ใน ~30 sub-repo ของ workspace (recruitment-api/02-core-pipeline §Contract)
ผลกระทบ — ไม่กระทบ business logic โดยตรง (flow ทำงานได้) แต่เป็นความไม่ชัดเจนเชิง ownership — ถ้า workforce-api เป็น route ที่ mount อยู่ใน vtrc-api เอง (ไม่ใช่ service แยก) ทีมที่ดูแล vtrc-api ต้องรู้ตัวว่า recruitment-api พึ่งพา route นี้อยู่ เพื่อไม่ให้ breaking change โดยไม่ได้ตั้งใจ
สรุป — คะแนนรวม
| Severity | จำนวน |
|---|---|
| Critical | 2 |
| High | 3 |
| Medium | 2 |
Modernization — ลำดับ ROI
- ตัดสินใจ source of truth ของ WdHospitals ระหว่าง
benefit/vtrcschema (CORR-BIZ-01) — ทำก่อนอย่างอื่นเพราะกระทบข้อมูลการเงินจริง ต้องมีทีม business ร่วมตัดสินใจ ไม่ใช่แค่ทีม dev - เพิ่ม reconciliation job สำหรับ export HRMI ทั้ง 2 flow (
CORR-BIZ-02) — เทียบจำนวน record ที่ระบบต้นทาง mark ว่า "ส่งแล้ว" กับจำนวนที่ HRMI มีจริง แจ้ง alert ถ้าไม่ตรง - เพิ่ม health-check/alert ให้ cron sync
dbWorkforce→pms-api(CORR-BIZ-03) — quick win เทียบกับความเสี่ยงที่ลดได้ (กระทบเงินเดือนพนักงานทั้งองค์กร) - เพิ่ม timeout/retry ให้ HTTP call ข้าม repo ทั้ง 4 จุด (
CORR-BIZ-04) — เริ่มจากbenefit-api→vtrc-apiเพราะกระทบเงินจริง (StudyLeave cancel) - สืบหาระบบ time attendance จริง (
CORR-BIZ-05) — ต้องสัมภาษณ์ทีม HRMI/business ก่อน ไม่สามารถปิดจาก source code ของ workspace นี้ได้ - เขียน shared type/schema-check ระหว่าง
recruitment-api/ai-recruitment-api(QUAL-BIZ-01) — เช่น เผยแพร่ TypeScript type ของjobReqPositionผ่าน npm package ภายใน - ยืนยัน ownership ของ
workforce-apiroute กับทีมvtrc-api(QUAL-BIZ-02) — งาน documentation ล้วน ไม่กระทบโค้ด