แอปจองคิว/นัดหมาย
ภาพรวม
แอป appointment ให้ลูกค้าเปิดระบบจองคิวผ่าน LINE โครงสร้างข้อมูลแบ่งเป็นห้าส่วน
| ส่วน | ความหมาย |
|---|---|
| Location | สาขาหรือสถานที่ให้บริการ |
| Service | บริการที่จองได้ ผูกกับสาขา |
| Staff | พนักงานที่ให้บริการ ผูกกับสาขา |
| Journey | เส้นทางหรือขั้นตอนการจองที่ผู้ใช้เห็น |
| Booking | รายการจองที่เกิดขึ้นจริง |
ฝั่ง cms-api รับผิดชอบการตั้งค่าและการจัดการรายการจอง ส่วนการจองจริงของผู้ใช้ปลายทางทำผ่าน client-web และ client-api
ข้อสังเกตเรื่องความไม่สม่ำเสมอของ guard ซึ่งยกมาจากระบบ TypeScript เดิมโดยตรง คือ endpoint กลุ่ม booking อยู่บน group authed คู่กับ AppEnabledGuard, กลุ่ม journey, service และ staff อยู่บน group public คู่กับ JwtLoginAuth ส่วนกลุ่ม location บาง route อยู่บน group authed เฉย ๆ โดยไม่มี policy
Business Flow
ตั้งค่าครั้งแรก
- สร้างสาขาด้วย
POST /api/apps/appointment/locations - เพิ่มบริการในสาขาด้วย
POST /api/apps/appointment/locations/:id/services - เพิ่มพนักงานในสาขาด้วย
POST /api/apps/appointment/locations/:id/staff - ออกแบบขั้นตอนการจองด้วย
POST /api/apps/appointment/journeys
ผู้ใช้ทำการจอง
- ผู้ใช้เปิด LIFF จาก LINE แล้วเลือกสาขา บริการ พนักงาน และเวลา ก่อนยืนยัน ขั้นตอนนี้ทำผ่าน client-api ไม่ใช่ endpoint ในเอกสารนี้
- ระบบสร้างแถวใหม่ในตาราง
booking
ผู้ดูแลจัดการรายการจอง
GET /api/apps/appointment/bookingsพร้อมFilterBookingDtoเพื่อดูรายการจองGET /api/apps/appointment/bookings/:idดูรายละเอียดการจองPUT /api/apps/appointment/bookings/:id/statusเปลี่ยนสถานะ เช่น ยืนยัน ยกเลิก หรือเสร็จสิ้น- การเปลี่ยนสถานะจะ publish ข้อความลง RabbitMQ คิว
booking_event_triggerโดย payload มี byte-shape ตรงกับของเดิมทุกประการ รวมถึงลำดับ key - ทำให้ กฎทริกเกอร์อัตโนมัติ สั่งส่งข้อความแจ้งผู้จองต่อได้
- การเปลี่ยนสถานะจะ publish ข้อความลง RabbitMQ คิว
รูปแบบ CRUD ที่ใช้ร่วมกัน
โครงสร้าง CRUD ของทุกเอนทิตีย่อยใน service_appointment.go เป็นรูปแบบเดียวกัน
_getCls()ดึงlineOaId,organizationId,selfIdและlangออกจาก CLSfindAllและfindAllByLocationประกอบ where และ order พร้อมกรองแถวที่ถูกลบออก แล้วคืน array ตรง ๆ โดยไม่ห่อ envelopefindByIdค้นด้วยเงื่อนไข id ร่วมกับlineOaIdหากไม่พบจะโยน NotFoundExceptioncreate,updateและremoveโดย remove เป็น soft delete- เอนทิตีกลุ่มนี้มี
gorm.DeletedAtทำให้ GORM เติมเงื่อนไขdeleted_date IS NULLและแปลง Delete เป็น soft delete ให้อัตโนมัติ
ไฟล์และฟังก์ชันหลัก
โค้ดอยู่ที่ internal/modules/apps/ ประกอบด้วย controller.go, service.go, service_appointment.go และ guard.go
Bookings (group authed + AppEnabledGuard)
| Method | Route | Handler | Policy |
|---|---|---|---|
| GET | /api/apps/appointment/bookings | ct.bookingFindAll | readAll line-oa |
| GET | /api/apps/appointment/bookings/:id | ct.bookingFindById | read line-oa |
| PUT | /api/apps/appointment/bookings/:id/status | ct.bookingUpdateStatus | update line-oa |
Journeys (group public + JwtLoginAuth)
| Method | Route | Handler |
|---|---|---|
| GET | /api/apps/appointment/journeys | ct.journeyFindAll |
| GET | /api/apps/appointment/journeys/:id | ct.journeyFindById |
| POST | /api/apps/appointment/journeys | ct.journeyCreate |
| PUT | /api/apps/appointment/journeys/:id | ct.journeyUpdate |
| DELETE | /api/apps/appointment/journeys/:id | ct.journeyRemove |
Locations
| Method | Route | Handler | Group |
|---|---|---|---|
| GET | /api/apps/appointment/locations | ct.locationFindAll | authed (ไม่มี policy) |
| POST | /api/apps/appointment/locations | ct.locationCreate | authed |
| GET | /api/apps/appointment/locations/:id | ct.locationFindById | authed |
| PUT | /api/apps/appointment/locations/:id | ct.locationUpdate | authed |
| DELETE | /api/apps/appointment/locations/:id | ct.locationRemove | authed |
Services และ Staff (group public + JwtLoginAuth)
| Method | Route | Handler |
|---|---|---|
| GET | /api/apps/appointment/locations/:id/services | ct.serviceFindAllByLocation |
| POST | /api/apps/appointment/locations/:id/services | ct.serviceCreate |
| GET | /api/apps/appointment/services/:id | ct.serviceFindById |
| PUT | /api/apps/appointment/services/:id | ct.serviceUpdate |
| DELETE | /api/apps/appointment/services/:id | ct.serviceRemove |
| GET | /api/apps/appointment/locations/:id/staff | ct.staffFindAllByLocation |
| POST | /api/apps/appointment/locations/:id/staff | ct.staffCreate |
| GET | /api/apps/appointment/staff/:id | ct.staffFindById |
| PUT | /api/apps/appointment/staff/:id | ct.staffUpdate |
| DELETE | /api/apps/appointment/staff/:id | ct.staffRemove |
หมายเหตุเรื่อง routing: route ที่ใช้ชื่อ param เป็น :id แทน :locationId เป็นเพราะ gin บังคับให้ชื่อ param ใน subtree เดียวกันต้องตรงกัน ขณะที่ระบบ TypeScript เดิมใช้ :locationId
จุดเชื่อมต่อกับ Service อื่น
- สิทธิ์การเข้าถึง — แอปต้องถูกเปิดให้องค์กรก่อนจึงจะเรียกได้ ตรวจโดย
AppEnabledGuard(ดู ระบบ Apps เสริม) ส่วน policy metadata ใช้PolicyModuleLineOa - ตารางที่เกี่ยวข้อง —
booking,location,service,staff,journey,line_oa_appและline_oa - RabbitMQ — คิว
booking_event_triggerเมื่อมีการเปลี่ยนสถานะการจอง - โมดูลที่เกี่ยวข้อง — ระบบ Apps เสริม, กฎทริกเกอร์อัตโนมัติ, แอปสะสมแต้ม และ แอปกระดานประกาศ