BOOK 20/25รายงานและการตรวจสอบ
ประวัติการใช้งาน
ดูว่าใครทำอะไรในระบบ เมื่อไหร่ จากเครื่องไหน — บันทึกการเปลี่ยนแปลงสำคัญทุกจุด (บิล/เมนู/พนักงาน/ตั้งค่า/สต็อก) แบบเรียงเวลาใหม่ล่าสุดก่อน กรองตามช่วงเวลา การกระทำ เครื่อง หรือค้นหาด้วยคำก็ได้ เห็นได้เฉพาะเจ้าของร้านหรือผู้ที่ได้รับสิทธิ์ระบุเจาะจงเท่านั้น
ภาพรวมหน้าบันทึกการใช้งาน
เข้าถึงหน้านี้ได้ยังไง
เปิดจากการ์ด “บันทึกการใช้งาน (Audit)” 📜 ในหน้าแรกของเมนู “จัดการ” (/admin) หรือพิมพ์ URL /audit-log ตรงก็ได้ — ทั้งสองทางต้องผ่านสิทธิ์เดียวกัน พิมพ์ URL ตรงไม่ได้ช่วยข้ามสิทธิ์
ต้องมีสิทธิ์ “ดูประวัติกิจกรรม/Audit Log” (audit.view) — ถ้าไม่มีระบบจะลองสิทธิ์ “ตั้งค่าระบบ” (settings.manage) แทนให้อัตโนมัติ ถ้าไม่มีทั้งสองอย่างจะเห็นข้อความ “ไม่มีสิทธิ์ (permission: audit.view)” แทนเนื้อหาทั้งหมด ไม่มีการรั่วข้อมูลออกมาแม้แต่บรรทัดเดียวก่อนเช็คสิทธิ์ผ่าน
สิทธิ์นี้ไม่ได้ติดมากับ role ไหนโดยอัตโนมัติเลยนอกจากเจ้าของร้าน (เจ้าของเห็นเสมอผ่านสิทธิ์ “*”) — ผู้จัดการ/ผู้ช่วยผู้จัดการ/แคชเชียร์/พนักงานเสิร์ฟ ค่าเริ่มต้นจากโรงงานไม่มีใครเห็นหน้านี้ ต้องให้เจ้าของร้านไปเปิดให้ทีละ role จากหน้า “จัดการพนักงาน → แท็บสิทธิ์” เอง

เปิดภาพเต็ม สรุปยอดด้านบน
การ์ดสรุปบนสุดแสดง 3 ตัวเลข: รายการทั้งหมด, จำนวนพนักงานที่ปรากฏ, จำนวนเครื่อง/สถานีที่ปรากฏ — ตัวเลขทั้งหมดนี้คำนวณจาก “ชุดข้อมูลหลังกรองแล้ว” ไม่ใช่ยอดรวมทั้งประวัติ ตั้งตัวกรองไว้แล้วตัวเลขสรุปจะเปลี่ยนตามทันที
หน้านี้รีเฟรชข้อมูลอัตโนมัติทุก 20 วินาที (ไม่ต้องกด F5) — ครั้งแรกที่เปิดหน้าข้อมูลมาจาก server โดยตรงไม่มีอาการหน้าขาวก่อนโหลดเสร็จ รอบรีเฟรชอัตโนมัติรอบแรกจะเริ่มที่วินาทีที่ 20 หลังเปิดหน้า

เปิดภาพเต็ม
กรองและค้นหา
ช่วงเวลา + ตัวกรองการกระทำ/เครื่อง
ปุ่มช่วงเวลามี 3 ตัวเลือก: “วันนี้”, “7 วัน”, “ทั้งหมด” — นับขอบเขตวันตามเวลาไทย (Asia/Bangkok) ไม่ใช่เวลา UTC ดิบ ๆ
ดรอปดาวน์ “การกระทำ” กับ “เครื่อง/สถานี” สร้างจากค่าที่ปรากฏจริงในประวัติที่โหลดมาเท่านั้น (ไม่ใช่รายการตายตัว) — ถ้ายังไม่เคยมีการกระทำแบบนั้นเกิดขึ้นเลย ตัวเลือกนั้นจะไม่โผล่ในดรอปดาวน์
ตั้งตัวกรองไว้ข้อใดข้อหนึ่งจะมีปุ่ม “ล้างตัวกรอง” โผล่มาให้กดล้างทุกตัวกรอง (ค้นหา/การกระทำ/เครื่อง/ช่วงเวลา) กลับเป็น “ทั้งหมด” ในคลิกเดียว

เปิดภาพเต็ม ค้นหาด้วยคำ
ช่องค้นหาจับคู่แบบ “มีคำนี้อยู่ในข้อความ” (ไม่สนตัวพิมพ์เล็ก/ใหญ่) กับ 3 ฟิลด์รวมกัน: ชื่อการกระทำ, รายละเอียด, ชื่อพนักงาน — พิมพ์ชื่อพนักงาน คำในรายละเอียด (เช่น ชื่อโต๊ะ ชื่อเมนู) หรือส่วนหนึ่งของโค้ดการกระทำก็เจอได้
ค้นหา/กรองทั้งหมดทำงานฝั่งเบราว์เซอร์กับข้อมูลที่โหลดมาแล้ว ไม่ได้ยิง query ใหม่ขึ้น server ทุกครั้งที่พิมพ์ — จึงตอบสนองทันทีไม่มีดีเลย์เครือข่าย

เปิดภาพเต็ม
อ่านตารางและแบ่งหน้า
คอลัมน์ในตาราง
5 คอลัมน์: เวลา (นาฬิกาเครื่อง server เสมอ ไม่ใช่นาฬิกาเครื่องลูกค้า — กันคนตั้งเวลาเครื่องเองแล้วปลอมเวลาบันทึก), พนักงาน, การกระทำ (โค้ดภายในระบบ เช่น bill:refund, staff:setRole, menu:removeItem — ไม่ใช่ประโยคภาษาคน), รายละเอียด (ข้อความสั้นอธิบายเพิ่ม เช่น ชื่อโต๊ะ/ชื่อเมนู/จำนวนเงิน), เครื่อง/สถานี
คอลัมน์ “พนักงาน” แสดง “—” ได้ในบางแถว — ไม่ใช่ข้อมูลหาย แต่หมายถึงการกระทำนั้นไม่มีพนักงานคนใดเป็นผู้สั่งโดยตรง เช่น ระบบจับคู่แจ้งเตือนเงินโอนเข้าอัตโนมัติจากธนาคาร (ไม่มีใครกดปุ่มเอง) แถวแบบนี้เกิดขึ้นได้ปกติ

เปิดภาพเต็ม แบ่งหน้าแสดงผล
เลือกจำนวนแถวต่อหน้าได้ 50/100/300 — การแบ่งหน้านี้ตัดเฉพาะ “ตารางที่แสดงผล” เท่านั้น สรุปยอดด้านบนและดรอปดาวน์ตัวกรองยังคำนวณจากชุดข้อมูลเต็มหลังกรองเสมอ ไม่ถูกตัดตามหน้าที่เลือก
เปลี่ยนตัวกรองหรือขนาดหน้าเมื่อไหร่ ระบบจะดีดกลับไปหน้า 1 ให้อัตโนมัติ กันปัญหาอยู่หน้า 3 แล้วผลกรองใหม่เหลือแค่ 1 หน้าแต่จอว่างเปล่า

เปิดภาพเต็ม
จุดที่มักสับสน
ไม่มีการลบ/แก้ไขรายการในบันทึก — มีแต่อ่านอย่างเดียว
หน้านี้และ API เบื้องหลัง (/api/audit-log) รองรับแค่การอ่านข้อมูล ไม่มีปุ่มหรือ endpoint สำหรับลบ แก้ไข หรือซ่อนรายการใดรายการหนึ่งเลย ต่อให้เป็นเจ้าของร้านก็ลบรายการทีละแถวไม่ได้ — รายการจะหายไปเองก็ต่อเมื่อถูกดันตกขอบเก็บ (ดูข้อถัดไป)
เก็บย้อนหลังไม่ได้นับเป็น “กี่วัน” — นับเป็นจำนวนรายการ (สูงสุด 10,000)
ระบบเก็บบันทึกแบบ ring buffer จำกัดที่ 10,000 รายการล่าสุด ไม่ใช่กติกาแบบ “เก็บ 30 วันแล้วลบ” — ร้านที่มีการเคลื่อนไหวเยอะ (บิล/แก้เมนู/ล็อกอินถี่ๆ) อาจเห็นประวัติย้อนหลังได้แค่ไม่กี่วัน ในขณะที่ร้านที่เงียบอาจเห็นย้อนหลังเป็นเดือน — เมื่อรายการเกิน 10,000 รายการที่เก่าที่สุดจะถูกตัดทิ้งอัตโนมัติทีละกลุ่ม
ไม่ใช่ทุก action ในระบบจะถูกบันทึก — เฉพาะจุดที่ผูกไว้เท่านั้น
การบันทึกลง audit log ต้องมีโค้ดเรียกใช้อย่างชัดเจนในแต่ละ endpoint (ไม่ได้ดักจับอัตโนมัติทั้งระบบ) — การกระทำที่แค่ “ดู” เฉยๆ เช่น เปิดดูเมนู เปิดดูรายงาน เปิดดูออเดอร์ จะไม่ปรากฏในนี้เลย จะเห็นเฉพาะการกระทำที่เปลี่ยนแปลงข้อมูลจริง (บิล/เมนู/พนักงาน/ตั้งค่า/สต็อก/พิมพ์บางประเภท ฯลฯ) และเป็นจุดที่นักพัฒนาผูกโค้ดบันทึกไว้แล้วเท่านั้น
การบันทึกเป็นแบบ best-effort — พังแล้วไม่บล็อกงานจริง
ถ้าเครื่องขัดข้องระหว่างเขียนบันทึก (เช่น พื้นที่เก็บข้อมูลมีปัญหาชั่วคราว) ระบบจะกลืนข้อผิดพลาดนั้นไปเงียบๆ แล้วปล่อยให้การกระทำจริง (เช่น ปิดบิล) สำเร็จตามปกติ — แปลว่าในสถานการณ์ที่หายากมากๆ อาจมีการกระทำจริงเกิดขึ้นแล้วแต่ไม่มีรายการในบันทึกให้ตรวจสอบย้อนหลัง
PIN login ไม่ได้ถูกละเว้นจากบันทึก — แค่บันทึกผ่านแถวเฉพาะของมันเอง
การล็อกอิน/ล็อกเอาต์ของพนักงานทุกครั้งถูกบันทึกจริง เห็นเป็นแถว staff:login (สำเร็จ) / staff:loginFail (ผิดพลาด) / staff:logout — เพียงแต่ไม่ได้ไหลผ่านแถวบันทึกทั่วไปที่ใช้กับการกระทำอื่นๆ ในหน้าจัดการพนักงาน (ซึ่งจงใจข้ามการพิมพ์ PIN สด/ล็อกเอาต์ทิ้ง เพื่อไม่ให้ได้แถวที่ข้อมูลไม่ครบ) — ถ้าค้นหาด้วยคำว่า “login” จะเจอครบทุกครั้งที่มีคนพยายามเข้าระบบ ไม่ว่าจะสำเร็จหรือไม่
มีสิทธิ์ “ตั้งค่าระบบระดับเจ้าของ” (system.admin) อย่างเดียวอาจเข้าหน้านี้ไม่ได้ทั้งที่เห็นลิงก์
ระบบมี 2 ชั้นการเช็คสิทธิ์ที่ตั้งใจให้ไม่เหมือนกัน: ชั้นนอก (ล็อกทั้งหน้า กันพิมพ์ URL ตรงเข้ามาดื้อๆ) ยอมให้ผ่านถ้ามีสิทธิ์ audit.view หรือ system.admin อย่างใดอย่างหนึ่ง แต่ตัวหน้า /audit-log เองเช็คซ้ำอีกชั้นและยอมรับเฉพาะ audit.view หรือ settings.manage เท่านั้น (ไม่รับ system.admin) — ผลคือ role ที่ถือ system.admin ล้วนๆ (ไม่มี audit.view หรือ settings.manage ควบ) จะผ่านด่านแรกได้แต่มาติดด่านสองแทน เห็นข้อความไม่มีสิทธิ์แทนเนื้อหา ถ้าเจอเคสนี้ให้ไปมอบสิทธิ์ audit.view ให้ role นั้นตรงๆ แทนการพึ่ง system.admin