ริชเมนู (Rich Menu)
ภาพรวม
Rich Menu คือเมนูรูปภาพที่แสดงอยู่ด้านล่างหน้าแชท LINE โมดูลนี้เป็นหนึ่งในโมดูลที่ซับซ้อนที่สุด ในระบบ เพราะต้องรับผิดชอบหลายเรื่องพร้อมกัน ได้แก่ การจัดการรูปและพื้นที่กด (layout), การผูกและเลิกผูกเมนูกับผู้ใช้บน LINE, การตั้งเมนู default, การจัดการ alias สำหรับเมนูหลายชั้น หรือแบบแท็บ, การเก็บ archive ของเวอร์ชันเก่า, การสร้างลิงก์ติดตาม (tracking token) รายปุ่ม และการคำนวณสถิติการกด
การผูกเมนูกับ audience ต้องอ่านไฟล์ CSV รายชื่อ LINE user จาก object storage ผ่าน CSV engine
Business Flow
การสร้างและ publish
POST /api/rich-menuรับ multipart/form-data สำหรับอัปโหลดรูป ระบุ layout และกำหนด action ของแต่ละพื้นที่- action ที่เป็นลิงก์จะถูกแปลงเป็น token-based tracking URL
- หากชื่อซ้ำจะตอบ error
RMN_001
- service เรียก LINE ผ่าน line message api ตามลำดับ
callCreateRichMenuOnLineOAแล้วsetRichMenuImageและหากมี alias จะสร้างหรืออัปเดต alias ต่อ - การระบุกลุ่มเป้าหมายมี 2 แบบ
- ทั้ง OA ใช้
setDefaultRichMenu - เฉพาะ audience ใช้
processRichMenuAudienceซึ่งอ่าน CSV ของ audience ผ่านDeps.CSVEngineแล้วเรียกlinkRichMenuIdToUsersเป็นชุด พร้อมบันทึกผลลงrich_menu_member
- ทั้ง OA ใช้
- เวอร์ชันเดิมจะถูกเก็บลง
rich_menu_archiveก่อนถูกแทนที่
การใช้งานประจำวัน
GET /api/rich-menuแสดงรายการแบบแบ่งหน้า และGET /api/rich-menu/find-all-objectสำหรับทำ dropdown ซึ่งไม่มี policyGET /api/rich-menu/:idดูรายละเอียดพร้อม action และสถิติPUT /api/rich-menu/:idรับ form-data สำหรับแก้ไข ใช้ flow เดียวกับการสร้าง แต่ต้องจัดการเมนูเดิมที่อยู่บน LINE ด้วยPOST /api/rich-menu/:id/recalculate-statสั่งคำนวณสถิติการกดใหม่ โดย publish ลงคิวcalculate_rich_menu_stat_itemให้ worker เป็นผู้คำนวณDELETE /api/rich-menu/:idลบแบบ soft delete พร้อมเรียกdeleteRichMenuที่ฝั่ง LINE ส่วนDELETE /api/rich-menu/:id/hard?confirm=trueลบข้อมูลจริง เฉพาะ super admin- การเปลี่ยนเมนูให้ผู้ใช้แบบ event-driven ทำผ่านคิว
line_change_richmenu
ไฟล์และฟังก์ชันหลัก
โค้ดอยู่ที่ internal/modules/richmenu/
| ไฟล์ | บทบาท |
|---|---|
controller.go | การ register route |
service.go | logic หลัก โดย fold repository ของ rich_menu, action, member และ archive เข้าด้วยกัน |
create_update.go | flow การสร้างและอัปเดต รวมถึง processRichMenuAudience |
update.go | flow การอัปเดตเมนูที่ publish ไปแล้ว |
tracking_adapter.go | แปลง action ที่เป็นลิงก์ให้เป็น tracking token URL |
util.go, js.go, dto.go | helper และ DTO |
| Method | Route | Handler | Policy (metadata) |
|---|---|---|---|
| GET | /api/rich-menu | ct.findAll | readAll rich-menu |
| GET | /api/rich-menu/find-all-object | ct.findAllObject | — |
| GET | /api/rich-menu/:id | ct.findById | read rich-menu |
| POST | /api/rich-menu | ct.create | create rich-menu |
| POST | /api/rich-menu/:id/recalculate-stat | ct.recalcStat | read rich-menu |
| PUT | /api/rich-menu/:id | ct.update | update rich-menu |
| DELETE | /api/rich-menu/:id | ct.delete | delete rich-menu |
| DELETE | /api/rich-menu/:id/hard | ct.hardDelete | auth.SuperAdmin() |
ทุก route ครอบด้วย modulegate.ModuleGate(d, "rich-menu")
จุดเชื่อมต่อกับ Service อื่น
- Permission —
ModuleGate("rich-menu")เป็นตัวบังคับจริง ส่วนPolicyModuleRichMenuเป็นเพียง metadata และ hard delete ต้องผ่านauth.SuperAdmin() - ตารางที่เกี่ยวข้อง —
rich_menu,rich_menu_action,rich_menu_member,rich_menu_archive,tracking_token,audience,line_oa - RabbitMQ — คิว
line_change_richmenuและcalculate_rich_menu_stat_item - Cross-module —
linemessageapi.Service,linemessageapi.RichMenuService,tracking.TrackingTokenServiceและDeps.CSVEngineสำหรับอ่าน CSV ของ audience - หมายเหตุ — การอ่านข้อมูล LINE OA ทำด้วย query
entities.LineOaโดยตรง ไม่ผ่านlineoa.Service.FindByIDเพราะจำเป็นต้องได้ค่าchannelAccessTokenซึ่ง service ตัวนั้นตัดออก - Error code —
RMN_001ชื่อซ้ำ