Skip to main content

ริชเมนู (Rich Menu)

ภาพรวม

Rich Menu คือเมนูรูปภาพที่แสดงอยู่ด้านล่างหน้าแชท LINE โมดูลนี้เป็นหนึ่งในโมดูลที่ซับซ้อนที่สุด ในระบบ เพราะต้องรับผิดชอบหลายเรื่องพร้อมกัน ได้แก่ การจัดการรูปและพื้นที่กด (layout), การผูกและเลิกผูกเมนูกับผู้ใช้บน LINE, การตั้งเมนู default, การจัดการ alias สำหรับเมนูหลายชั้น หรือแบบแท็บ, การเก็บ archive ของเวอร์ชันเก่า, การสร้างลิงก์ติดตาม (tracking token) รายปุ่ม และการคำนวณสถิติการกด

การผูกเมนูกับ audience ต้องอ่านไฟล์ CSV รายชื่อ LINE user จาก object storage ผ่าน CSV engine

Business Flow

การสร้างและ publish

  1. POST /api/rich-menu รับ multipart/form-data สำหรับอัปโหลดรูป ระบุ layout และกำหนด action ของแต่ละพื้นที่
    • action ที่เป็นลิงก์จะถูกแปลงเป็น token-based tracking URL
    • หากชื่อซ้ำจะตอบ error RMN_001
  2. service เรียก LINE ผ่าน line message api ตามลำดับ callCreateRichMenuOnLineOA แล้ว setRichMenuImage และหากมี alias จะสร้างหรืออัปเดต alias ต่อ
  3. การระบุกลุ่มเป้าหมายมี 2 แบบ
    • ทั้ง OA ใช้ setDefaultRichMenu
    • เฉพาะ audience ใช้ processRichMenuAudience ซึ่งอ่าน CSV ของ audience ผ่าน Deps.CSVEngine แล้วเรียก linkRichMenuIdToUsers เป็นชุด พร้อมบันทึกผลลง rich_menu_member
  4. เวอร์ชันเดิมจะถูกเก็บลง rich_menu_archive ก่อนถูกแทนที่

การใช้งานประจำวัน

  1. GET /api/rich-menu แสดงรายการแบบแบ่งหน้า และ GET /api/rich-menu/find-all-object สำหรับทำ dropdown ซึ่งไม่มี policy
  2. GET /api/rich-menu/:id ดูรายละเอียดพร้อม action และสถิติ
  3. PUT /api/rich-menu/:id รับ form-data สำหรับแก้ไข ใช้ flow เดียวกับการสร้าง แต่ต้องจัดการเมนูเดิมที่อยู่บน LINE ด้วย
  4. POST /api/rich-menu/:id/recalculate-stat สั่งคำนวณสถิติการกดใหม่ โดย publish ลงคิว calculate_rich_menu_stat_item ให้ worker เป็นผู้คำนวณ
  5. DELETE /api/rich-menu/:id ลบแบบ soft delete พร้อมเรียก deleteRichMenu ที่ฝั่ง LINE ส่วน DELETE /api/rich-menu/:id/hard?confirm=true ลบข้อมูลจริง เฉพาะ super admin
  6. การเปลี่ยนเมนูให้ผู้ใช้แบบ event-driven ทำผ่านคิว line_change_richmenu

ไฟล์และฟังก์ชันหลัก

โค้ดอยู่ที่ internal/modules/richmenu/

ไฟล์บทบาท
controller.goการ register route
service.gologic หลัก โดย fold repository ของ rich_menu, action, member และ archive เข้าด้วยกัน
create_update.goflow การสร้างและอัปเดต รวมถึง processRichMenuAudience
update.goflow การอัปเดตเมนูที่ publish ไปแล้ว
tracking_adapter.goแปลง action ที่เป็นลิงก์ให้เป็น tracking token URL
util.go, js.go, dto.gohelper และ DTO
MethodRouteHandlerPolicy (metadata)
GET/api/rich-menuct.findAllreadAll rich-menu
GET/api/rich-menu/find-all-objectct.findAllObject
GET/api/rich-menu/:idct.findByIdread rich-menu
POST/api/rich-menuct.createcreate rich-menu
POST/api/rich-menu/:id/recalculate-statct.recalcStatread rich-menu
PUT/api/rich-menu/:idct.updateupdate rich-menu
DELETE/api/rich-menu/:idct.deletedelete rich-menu
DELETE/api/rich-menu/:id/hardct.hardDeleteauth.SuperAdmin()

ทุก route ครอบด้วย modulegate.ModuleGate(d, "rich-menu")

จุดเชื่อมต่อกับ Service อื่น

  • PermissionModuleGate("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-modulelinemessageapi.Service, linemessageapi.RichMenuService, tracking.TrackingTokenService และ Deps.CSVEngine สำหรับอ่าน CSV ของ audience
  • หมายเหตุ — การอ่านข้อมูล LINE OA ทำด้วย query entities.LineOa โดยตรง ไม่ผ่าน lineoa.Service.FindByID เพราะจำเป็นต้องได้ค่า channelAccessToken ซึ่ง service ตัวนั้นตัดออก
  • Error codeRMN_001 ชื่อซ้ำ