เขตเวลาและวันธุรกิจ
วันของร้านอาหารไม่ได้จบตอนเที่ยงคืน ScanFood จึงบันทึกวันที่ไว้สองแบบบนบิลทุกใบ และการหยิบผิดตัวคือสาเหตุอันดับหนึ่งที่ข้อมูลส่งออกไม่ตรงกับรายงานของร้านเอง
เขตเวลา
หัวข้อที่มีชื่อว่า “เขตเวลา”ร้านแต่ละร้านมีเขตเวลาของตัวเอง ส่งกลับมาเป็นชื่อมาตรฐาน IANA ที่ GET /v1/shops
{ "shopId": "aK3mP9xQ2bR7cT4dV6wY", "timezone": "Asia/Bangkok" }ร้านที่ไม่เคยตั้งค่านี้จะได้ null ซึ่งเป็นเรื่องปกติของร้านเก่า ให้ถือว่า null
คือ Asia/Bangkok เพราะนั่นคือค่าที่ ScanFood ใช้จัดรูปวันที่ของร้านนั้นเอง
อย่าส่งค่าดิบเข้าตัวแปลงเขตเวลาโดยไม่มีค่าสำรองนี้ ไม่อย่างนั้นจะพังทันทีที่เจอสาขาเก่าสาขาแรก
เวลาแต่ละช่องถูกจัดรูปให้เหมาะกับคนที่ต้องใช้มัน
| ช่อง | รูปแบบ | เขตเวลา |
|---|---|---|
timestamp และ updatedAt บนบิล |
ISO-8601 พร้อมค่าชดเชย เช่น 2026-09-01T13:30:00.000+07:00 |
เขตเวลาของร้าน |
createdDate และ coupons[].expireAt บนสมาชิก |
ISO-8601 พร้อมค่าชดเชย | เขตเวลาของแบรนด์สมาชิก |
businessDate billDate lastVisit |
YYYY-MM-DD |
วันตามนาฬิกาบนผนังในเขตเวลาเดียวกันนั้น ไม่มีเวลา ไม่มีค่าชดเชย |
serverTime ในทุกคำตอบ |
ISO-8601 ลงท้ายด้วย Z |
UTC |
from และ to ในคำขอ |
YYYYMMDD ไม่มีขีด |
วันตามปฏิทินในเขตเวลาของร้าน |
updatedSince ในคำขอ |
ISO-8601 | เขตเวลาไหนก็ได้ ส่งเป็น Z แล้วจบเรื่อง |
เพราะค่าชดเชยเดินทางมากับเวลาอยู่แล้ว คุณจึงไม่จำเป็นต้องรู้เขตเวลาของร้านเพื่อเรียงหรือเทียบบิล
อ่านเป็นจุดเวลาได้เลย คุณต้องใช้เขตเวลาก็ต่อเมื่ออยากตอบว่า “บิลนี้เป็นของวันไหน”
ซึ่ง API ทำให้เรียบร้อยแล้ว ให้อ่าน billDate หรือ businessDate แทนการคำนวณวันจากเวลาเอง
วันตามปฏิทิน กับ วันธุรกิจ
หัวข้อที่มีชื่อว่า “วันตามปฏิทิน กับ วันธุรกิจ”| ช่อง | ตอบคำถามว่า |
|---|---|
billDate |
บิลนี้จ่ายในวันไหนตามปฏิทิน โดยดูนาฬิกาบนผนังของร้าน |
businessDate |
บิลนี้นับเป็นยอดของวันทำการวันไหน |
ร้านที่ปิดก่อนเที่ยงคืน สองค่านี้จะตรงกันเสมอ ส่วนบาร์ที่ขายถึงตีสาม สองค่านี้ต่างกันทุกคืน และนั่นคือเหตุผลทั้งหมดที่ต้องมีสองช่อง
เวลาปิดรอบของร้าน
หัวข้อที่มีชื่อว่า “เวลาปิดรอบของร้าน”ทุกร้านตั้งเวลาปิดรอบไว้ คือเวลาที่วันทำการหมุนไปวันใหม่ ร้านที่ตั้งเวลาปิดรอบ 06:00 น. จะถือว่าทุกบิลตั้งแต่ 06:00 น. ของวันนี้ ถึง 05:59 น. ของวันพรุ่งนี้ เป็นวันทำการเดียวกัน ซึ่งตรงกับรายงานปิดวันของร้าน ตรงกับการนับเงินในลิ้นชัก และตรงกับที่พนักงานเข้าใจ
businessDate คำนวณกติกานี้ให้คุณแล้ว คุณไม่ต้องรู้เวลาปิดรอบ ไม่ต้องไปดึงมา
และไม่ต้องเขียนสูตรซ้ำเอง
เลือกตัวกรองให้ถูก
หัวข้อที่มีชื่อว่า “เลือกตัวกรองให้ถูก”สองกติกานี้ครอบคลุมทุกกรณี
- กรองด้วย
from/toซึ่งตรงกับbillDateไม่มีวิธีกรองด้วยวันธุรกิจ พารามิเตอร์ช่วงวันดูที่วันตามปฏิทินเท่านั้น - จัดกลุ่มด้วย
businessDateทุกครั้งที่ตัวเลขต้องตรงกับของร้าน ยอดขาย VAT ยอดปิดวัน ค่าคอมมิชชัน ทั้งหมดนี้เป็นตัวเลขระดับวันทำการ
การจับคู่แบบนี้มีผลอย่างหนึ่งที่ต้องออกแบบเผื่อไว้ คือถ้าอยากมั่นใจว่าได้บิลของวันทำการหนึ่งครบ
คุณต้องดึงวันตามปฏิทินนั้น และ วันถัดไปด้วย แล้วค่อยจัดกลุ่มด้วย businessDate
เพราะบิลที่จ่ายตอนตีหนึ่งของวันที่ 2 กันยายน มี billDate เป็น "2026-09-02"
ทั้งที่เป็นของวันทำการ 1 กันยายน
รูปแบบที่ปลอดภัยสำหรับงานส่งออกรายคืน
- ดึงโดยให้
fromเป็นวันที่จะรายงาน และtoเป็นวันถัดไป - เก็บเฉพาะแถวที่
businessDateตรงกับวันที่จะรายงาน - รันวันนั้นซ้ำอีกครั้งหลังเลยเวลาปิดรอบของร้านแล้ว เพราะการยกเลิกบิลย้อนหลัง และการออกใบกำกับภาษีใหม่ ทำให้บิลเปลี่ยนหลังจากนั้นได้ ซึ่งโหมดดึงเฉพาะส่วนที่เปลี่ยนใน การแบ่งหน้าและการซิงก์ จะจับให้เองอยู่แล้ว
ตัวอย่างจริง
หัวข้อที่มีชื่อว่า “ตัวอย่างจริง”ร้านหนึ่งอยู่ในเขตเวลา Asia/Bangkok ตั้งเวลาปิดรอบไว้ 06:00 น. มีสองบิล
| จ่ายเมื่อ | timestamp |
billDate |
businessDate |
|---|---|---|---|
| 1 ก.ย. 13:30 น. | 2026-09-01T13:30:00.000+07:00 |
2026-09-01 |
2026-09-01 |
| 2 ก.ย. 01:40 น. | 2026-09-02T01:40:00.000+07:00 |
2026-09-02 |
2026-09-01 |
รายงานของร้านสำหรับวันที่ 1 กันยายน มีทั้งสองบิล ดังนั้น
- เรียก
from=20260901&to=20260901จะได้ เฉพาะบิลแรก เพราะบิลที่สองมีวันตามปฏิทิน เป็นวันที่ 2 กันยายน ยอดของคุณจะขาดไป - เรียก
from=20260901&to=20260902จะได้ทั้งสองบิล บวกกับทุกบิลที่เป็นของวันที่ 2 กันยายนจริง ๆ แล้วกรองผลลัพธ์นั้นด้วยbusinessDate === "2026-09-01"จะได้ตัวเลขตรงกับของร้านพอดี
ถ้าคุณเทียบกับรายงานปิดวันของร้านแล้วขาดไปไม่กี่บิล สาเหตุมักเป็นเรื่องนี้เกือบทุกครั้ง