จัดการแคมเปญส่งข้อความ (Campaign)
ภาพรวม
Campaign คือการส่งข้อความ (rich message) ออกไปหาเพื่อน LINE ตามกลุ่มเป้าหมายที่กำหนด และตั้งเวลาส่งล่วงหน้าได้ โมดูลนี้ดูแลตั้งแต่การสร้างแคมเปญ การเลือกผู้รับ ไม่ว่าจะเป็นทั้ง OA หรือเฉพาะ audience ไปจนถึงการดูรายงานติดตามผลว่าใครเปิดหรือกดลิงก์ใดบ้าง
การส่งจริงไม่ได้เกิดขึ้นใน API นี้ โดย API ทำหน้าที่เพียงบันทึกข้อมูลและ publish งานลง RabbitMQ ให้ worker เป็นผู้ส่ง ทำให้ request ตอบกลับได้เร็วและรองรับการส่งจำนวนมาก
Business Flow
การสร้างและส่ง
-
GET /api/campaign/recipients-dropdownให้ cms-web แสดงตัวเลือกผู้รับ เช่น audience ที่มีอยู่ -
POST /api/campaignรับเป็น multipart/form-data เพื่อบันทึกแคมเปญ ประกอบด้วยชื่อแคมเปญ rich message ที่จะส่ง ประเภทผู้รับ (broadcast ทั้ง OA หรือ multicast ตาม audience) และเวลาส่ง -
service ตรวจว่าข้อความมี merge tag เช่น
{{name}}หรือไม่ ด้วยฟังก์ชันhasMergeTagsเนื่องจากข้อความที่มี merge tag ต้องส่งแบบ personalize ทีละคน -
ระบบ publish งานลง RabbitMQ ตามเงื่อนไข
- ไม่ระบุ audience จะลงคิว
line_broadcast_rich_message - ระบุ audience จะลงคิว
line_multicast_rich_message - งานที่ตั้งเวลาหรือประมวลผลรวมจะลงคิว
process_campaign
payload ถูกสร้างให้ byte-identical กับระบบ TypeScript เดิม โดยคงลำดับ key ไว้เหมือนเดิม เพราะ worker ตัวเดิมยังเป็นผู้อ่านอยู่
- ไม่ระบุ audience จะลงคิว
-
worker ดึงงานไปยิง LINE Messaging API
การติดตามผล
GET /api/campaign/campaign-tracking/:idสรุปยอดการส่ง เปิด และคลิก โดยคำนวณด้วย raw SQL aggregationGET /api/campaign/campaign-tracking/:id/usersเจาะดูรายชื่อผู้ที่ทำ action นั้น รองรับ queryactionType,originalUrl,richMessageIndex,pageและlimit- ลิงก์ในแคมเปญถูกแปลงเป็น URL ติดตามผ่าน RedirectService ฝั่ง worker ซึ่งต่างจาก rich menu ที่ใช้กลไก token-based
การจัดการทั่วไป
GET /api/campaignแสดงรายการแบบแบ่งหน้า โดย repository จะ spread ค่าtargetของ audience เข้าไปในผลลัพธ์GET /api/campaign/:idและPUT /api/campaign/:idใช้ดูและแก้ไข ส่วนDELETE /api/campaign/:idเป็น soft deleteDELETE /api/campaign/:id/hard?confirm=trueลบข้อมูลจริง เฉพาะ super admin เท่านั้น
ไฟล์และฟังก์ชันหลัก
โค้ดอยู่ที่ internal/modules/campaign/ ประกอบด้วย controller.go, service.go,
tracking.go และ dto.go
| Method | Route | Handler | Policy (metadata) |
|---|---|---|---|
| GET | /api/campaign | ct.findAll | readAll campaign |
| GET | /api/campaign/recipients-dropdown | ct.recipientsDropdown | readAll campaign |
| GET | /api/campaign/:id | ct.findByID | read campaign |
| GET | /api/campaign/campaign-tracking/:id | ct.trackingByID | read campaign |
| GET | /api/campaign/campaign-tracking/:id/users | ct.trackingUsersByID | read campaign |
| POST | /api/campaign | ct.create | create campaign |
| PUT | /api/campaign/:id | ct.update | update campaign |
| DELETE | /api/campaign/:id | ct.delete | delete campaign |
| DELETE | /api/campaign/:id/hard | ct.hardDelete | auth.SuperAdmin() |
ทุก route ครอบด้วย modulegate.ModuleGate(d, "campaign")
ฟังก์ชันที่ควรทราบคือ hasMergeTags ซึ่งใช้ regex /\{\{[^}]+\}\}/ แบบเดียวกับ JavaScript
กล่าวคือต้องมีวงเล็บปีกกาปิดสองตัวติดกันจริงจึงจะ match
จุดเชื่อมต่อกับ Service อื่น
- Permission —
ModuleGate("campaign")เป็นตัวบังคับจริง ส่วนPolicyModuleCampaignเป็นเพียง metadata และ hard delete ต้องผ่านauth.SuperAdmin() - ตารางที่เกี่ยวข้อง —
campaign,rich_message,audience,line_user,tracking_line_users,line_oa - RabbitMQ — คิว
process_campaign,line_broadcast_rich_message,line_multicast_rich_messageและcampaign_click_trigger - Redis — cache ทั้งรายการและรายละเอียด
- Cross-module —
linemessageapiสำหรับ validate และ format ข้อความ รวมถึงrichmessageและaudience - โมดูลที่เกี่ยวข้อง — ข้อความริช, การจัดการ audience และ trigger rule ซึ่งใช้การคลิกในแคมเปญเป็น trigger source