รายงานวิเคราะห์ระบบจัดคนงานก่อสร้างสำหรับโฟร์แมนไทย
เอกสารนี้สรุปโครงสร้างระบบและข้อกำหนดเชิงปฏิบัติสำหรับเดโม: ใช้ง่ายกลางแจ้ง ตัวอักษรใหญ่ ลดภาระการคิด รองรับเน็ตช้า และเก็บหลักฐานตรวจสอบย้อนหลังได้
หลักคิดของระบบ
ระบบต้องช่วยโฟร์แมนตัดสินใจเร็ว ไม่บังคับกรอกข้อมูลยาว และต้องไม่พังเมื่อสัญญาณอินเทอร์เน็ตไม่เสถียร
Domain Model
โมเดลโดเมนควรแยก “คน”, “ไซต์”, “การมอบหมาย”, “รอบเวลา”, และ “หลักฐาน” ออกจากกัน เพื่อให้ตรวจสอบและแก้ไขภายหลังได้ง่าย
| Entity | หน้าที่ | ฟิลด์สำคัญ | หมายเหตุเดโม |
|---|---|---|---|
| Worker | ข้อมูลคนงานที่ถูกจัดลงไซต์ | workerIdชื่อเล่นทักษะเบอร์โทรสถานะพร้อมงาน | ใช้ชื่อเล่นหรือรูปแทนการอ่านข้อความยาว ลดความผิดพลาดในไซต์ |
| Foreman | ผู้สั่งงานและรับผิดชอบรอบไซต์ | foremanIdrolesiteScopepinVerifiedAt | ใช้สิทธิ์ตามไซต์ ห้ามเห็นข้อมูลไซต์ที่ไม่ได้รับมอบหมาย |
| Site | พื้นที่ก่อสร้างหรือโซนงาน | siteIdชื่อไซต์โซนพิกัดกฎเข้างาน | เดโมควรมีไซต์ 2-3 แห่งเพื่อโชว์การกรองทีม |
| Assignment | คำสั่งมอบหมายคนงานไปไซต์/โซน/งาน | assignmentIdworkerIdsiteIdtaskCodeshiftDatestate | เป็นแกนหลักของหน้าจอ “วันนี้ต้องมีใครอยู่ที่ไหน” |
| AttendanceSession | หลักฐานเข้า-ออกไซต์จริง | sessionIdsiteInAtsiteOutAtmethodlocation | รองรับ QR, ปุ่มยืนยันโดยโฟร์แมน, หรือ offline stamp |
| AuditEvent | บันทึกเหตุการณ์แบบ append-only | eventIdtypeactorbeforeafterdeviceTime | ไม่ลบ event เก่า ใช้ event ใหม่เพื่อแก้ไขหรือยกเลิก |
| SyncBatch | ชุดข้อมูลที่รอส่งเมื่อ offline | batchIddeviceIdevents[]retryCountstatus | ช่วยอธิบายในเดโมว่าข้อมูลไม่หายแม้เน็ตหลุด |
State Machine
สถานะต้องสั้น ชัด และแสดงเป็นสีหรือไอคอน ไม่ให้โฟร์แมนต้องตีความเยอะ
Data Contract
สำหรับเดโมให้ใช้ contract ที่อ่านง่ายก่อน แล้วค่อยขยายเป็น production schema ภายหลัง
API หลักที่ควรมี
GET /api/sites/today ดึงไซต์และรอบงานวันนี้
GET /api/assignments?siteId=&date= ดึงบอร์ดคนงานตามไซต์
POST /api/assignments มอบหมายหรือย้ายคนงาน
POST /api/attendance/site-in ยืนยันเข้าไซต์
POST /api/attendance/site-out ยืนยันออกไซต์
POST /api/sync/events ส่ง event ที่ค้างจาก offline queue
กติกาการตอบกลับ
ทุก response ต้องมี requestId, serverTime, ok และเมื่อผิดพลาดต้องมี error.code ที่ UI แปลงเป็นภาษาไทยง่าย ๆ ได้
ห้ามให้ frontend เดาความหมายจากข้อความ error ยาว ๆ เพราะโฟร์แมนต้องเห็นคำแนะนำที่ทำต่อได้ทันที
{
"assignmentId": "asg_20260602_001",
"worker": {
"workerId": "w_1207",
"displayName": "ลุงสมชาย",
"skillTags": ["ช่างปูน", "ยกของ"],
"photoUrl": "/demo/workers/w_1207.jpg"
},
"site": {
"siteId": "site_a",
"name": "ไซต์พระราม 9",
"zone": "ชั้น 3 - โซน B"
},
"task": {
"taskCode": "MASONRY",
"taskName": "ก่อผนัง",
"priority": "normal"
},
"state": "ASSIGNED",
"shiftDate": "2026-06-02",
"version": 4,
"lastEventId": "evt_9fh2"
}
Action Flow สำหรับโฟร์แมน
- เลือกไซต์วันนี้
ระบบแสดงไซต์ที่โฟร์แมนมีสิทธิ์เท่านั้น พร้อมจำนวนคน “ต้องมี / มาแล้ว / ยังไม่มา / มีปัญหา” - ดูรายชื่อคนงานเป็นการ์ดใหญ่
แสดงรูป ชื่อเล่น ทักษะหลัก และสถานะสีเดียวต่อคน ลดการอ่านหลายบรรทัด - มอบหมายงานด้วยปุ่มเดียว
เลือกคน เลือกโซน/งาน กดยืนยัน ระบบบันทึก event และอัปเดตบอร์ดทันทีแบบ optimistic - ยืนยันเข้าไซต์
ใช้ QR หรือปุ่ม “เข้าไซต์แล้ว” โดยต้องแนบเวลา อุปกรณ์ และผู้ยืนยันเสมอ - จัดการปัญหาหน้างาน
ถ้าคนไม่มา ให้กด “ขาด/ยังไม่ถึง” ถ้าส่งผิดไซต์ ให้กด “ย้ายไซต์” โดยระบบขอเหตุผลสั้น ๆ - ยืนยันออกไซต์และปิดรอบ
ระบบสรุปคนออกครบหรือยัง ถ้ายังมีคนค้างต้องโชว์แถบเตือนใหญ่ก่อนปิดรอบ
Offline / Slow Network Handling
แนวทางระบบ
ใช้ offline-first สำหรับคำสั่งหน้างานที่สำคัญ เช่น site-in, site-out, เปลี่ยนสถานะ และย้ายงาน โดยบันทึกลง local queue ก่อน แล้ว sync เมื่อมีสัญญาณ
UI ต้องแยกชัดระหว่าง “บันทึกในเครื่องแล้ว” กับ “ส่งขึ้นระบบกลางแล้ว” เพื่อไม่ให้เข้าใจผิด
ข้อความที่ควรแสดง
สีเขียว: ส่งสำเร็จแล้ว
สีเหลือง: บันทึกในเครื่องแล้ว รอส่ง
สีแดง: ส่งไม่สำเร็จ ต้องแก้หรือกดส่งใหม่
สีเทา: กำลังโหลดข้อมูลเดิมจาก cache
Audit / Event Model
ระบบต้องตอบคำถามย้อนหลังได้ว่า “ใครสั่งอะไร เวลาไหน จากเครื่องไหน ก่อนและหลังเป็นอย่างไร”
{
"eventId": "evt_20260602_000045",
"eventType": "WORKER_SITE_IN_CONFIRMED",
"entityType": "Assignment",
"entityId": "asg_20260602_001",
"actor": {
"actorId": "fm_88",
"role": "FOREMAN",
"displayName": "ช่างนพ"
},
"before": { "state": "ASSIGNED" },
"after": { "state": "SITE_IN", "siteInAt": "2026-06-02T08:12:31+07:00" },
"source": {
"deviceId": "tablet_site_a_02",
"network": "offline-queued",
"clientEventId": "local_7ad92"
},
"reason": null,
"createdAt": "2026-06-02T08:12:35+07:00"
}
| Event Type | ใช้เมื่อ | ต้องมีเหตุผลไหม |
|---|---|---|
| ASSIGNMENT_CREATED | จัดคนเข้ารอบงาน | ไม่ต้องมี |
| ASSIGNMENT_MOVED | ย้ายไซต์/โซน/งาน | ต้องมี หากย้ายหลังเข้าไซต์แล้ว |
| WORKER_SITE_IN_CONFIRMED | ยืนยันเข้าไซต์ | ไม่ต้องมี |
| WORKER_SITE_OUT_CONFIRMED | ยืนยันออกไซต์ | ไม่ต้องมี |
| ATTENDANCE_CORRECTED | แก้เวลาเข้า-ออกย้อนหลัง | ต้องมีเสมอ |
| SYNC_CONFLICT_RESOLVED | แก้ข้อมูลชนกันจาก offline | ต้องมีเสมอ |
Error Recovery และ Security
Error Recovery
ข้อมูลซ้ำ: ใช้ clientEventId และ idempotency key เพื่อไม่สร้าง event ซ้ำเมื่อกดส่งใหม่
ข้อมูลชนกัน: เทียบ version ของ assignment และให้หัวหน้าเลือก “ยึดข้อมูลล่าสุด / ยืนยันของฉัน / ส่งให้แอดมิน”
เช็คอินผิดคน: ไม่ลบ event เดิม แต่สร้าง correction event พร้อมเหตุผล
เครื่องดับ: local queue ต้องค้างอยู่ใน IndexedDB หรือ storage ที่ไม่หายเมื่อ reload
Security / Permissions
Role: Foreman เห็นเฉพาะไซต์ตัวเอง, Admin เห็นทุกไซต์, Auditor อ่าน audit ได้แต่แก้ไม่ได้
Action permission: site-in/out ต้องเป็น foreman ของไซต์นั้น หรือผู้ได้รับมอบหมายแทน
PII: แสดงข้อมูลเท่าที่จำเป็น เช่น ชื่อเล่น รูป ทักษะ หลีกเลี่ยงเลขบัตรหรือข้อมูลเงินในหน้าหน้างาน
Device trust: ผูก deviceId และ session timeout สั้นเมื่อใช้ tablet กลางไซต์
Integration Boundaries
| ขอบเขต | ระบบนี้รับผิดชอบ | ระบบภายนอกรับผิดชอบ | ข้อควรระวัง |
|---|---|---|---|
| HR / Master Worker | อ่านรายชื่อ ทักษะ สถานะพร้อมงาน | สร้าง/ปิดประวัติคนงาน ข้อมูลสัญญาจ้าง | ต้อง sync เฉพาะข้อมูลที่จำเป็นต่อไซต์ |
| Payroll | ส่งสรุปเวลาเข้า-ออกและ correction events | คำนวณค่าแรง ภาษี หักเงิน | อย่าให้เดโมผูก payroll ลึกเกินไป ให้โชว์ export/snapshot ก่อน |
| Access Control / Gate | รับสัญญาณ QR หรือ gate pass | สแกนบัตรหรือควบคุมประตูจริง | ถ้า gate ล่ม ต้องยังมี manual confirm พร้อม audit |
| Notification | สร้างเหตุการณ์ที่ควรแจ้ง เช่น คนยังไม่เข้าไซต์ | ส่ง LINE/SMS/Push | ต้องไม่พึ่ง notification เป็นหลัก เพราะไซต์อาจเสียงดังหรือไม่มีเน็ต |
Route / Component Implications
การออกแบบ route และ component ควรสะท้อน workflow จริง ไม่ใช่แค่หน้า dashboard กว้าง ๆ หน้าเดียว
Routes ที่แนะนำสำหรับเดโม
/foreman เลือกไซต์และสรุปสถานะวันนี้
/foreman/sites/[siteId] บอร์ดคนงานของไซต์
/foreman/assignments/new มอบหมายคนเข้าไซต์/โซน
/foreman/attendance เช็คอิน/เช็คเอาต์แบบเร็ว
/foreman/audit ดูประวัติ event และ correction
Components ที่ควรแยก
SiteStatusHeader ตัวเลขใหญ่: ต้องมา / มาแล้ว / ยังไม่มา / มีปัญหา
WorkerCard รูป ชื่อเล่น ทักษะ สถานะ และปุ่ม action หลัก
AssignmentDrawer เลือกโซน งาน และเหตุผลเมื่อย้าย
OfflineQueueBanner บอกจำนวน event ที่รอ sync
AuditTimeline แสดง event แบบอ่านง่ายพร้อม filter
requestId, clientEventId, actorId, deviceId, และ assignmentVersion เพื่อรองรับ retry และ audit
Implementation Checkpoints
ขอบเขตเดโมที่ควรทำก่อน
เพื่อให้เดโมชัดและไม่บานปลาย ควรทำให้ครบเส้นทางหลักก่อน แล้วค่อยเพิ่ม integration จริง
| Must Have | Should Have | Defer |
|---|---|---|
| บอร์ดคนงานรายไซต์, assign, site-in/out, audit event, offline queue จำลอง | QR demo, conflict resolution, export audit, notification mock | Payroll จริง, gate hardware จริง, HR sync สองทาง, biometric |