Skip to main content

แคมเปญส่งข้อความ

ภาพรวม

Domain นี้มี 2 ตาราง คือ campaign ซึ่งเก็บนิยามแคมเปญส่งข้อความ (ผู้รับ เนื้อหา เวลาส่ง สถานะ และตัวเลขสรุปผล) และ campaign_delivery_batch ซึ่งเป็นตารางที่สร้างด้วย manual SQL สำหรับติดตาม การส่งแบบแบ่ง batch ของแคมเปญ multicast โดยมี 1 แถวต่อ 1 batch

ตาราง campaign

ColumnTypeNullableDefaultคำอธิบาย
idSERIAL (INTEGER)NOnextval(...)รหัสอ้างอิงหลักของแคมเปญ
nameTEXTNO-ชื่อแคมเปญ
broadcast_nowBOOLEANNO-ส่งทันทีหรือไม่ (false = ตั้งเวลาส่งตาม start_date)
start_dateTIMESTAMPTZ(3)NO-วันเวลาที่กำหนดให้เริ่มส่ง
cast_type"CastType"YESbroadcastรูปแบบการส่ง: broadcast, multicast, narrowcast
audience_idINTEGERYES-กลุ่มเป้าหมายผู้รับ (FK ไป audience.id; NULL เมื่อส่ง broadcast ทั้งหมด)
rich_message_idINTEGERNO-ข้อความที่ใช้ส่ง (FK ไป rich_message.id)
line_oa_idINTEGERNO-รหัส LINE OA ที่ส่งแคมเปญ (FK ไป line_oa.id)
organization_idINTEGERYES0รหัสองค์กรเจ้าของข้อมูล (FK ไป organization.id)
status"CampaignStatus"NO-สถานะแคมเปญ: sent, scheduled, cancel, draft, failed, sending
created_dateTIMESTAMPTZ(3)NOnow()วันเวลาที่สร้างรายการ
created_byINTEGERNO0รหัสผู้ใช้ที่สร้างรายการ
updated_dateTIMESTAMPTZ(3)YES-วันเวลาที่แก้ไขล่าสุด (อัปเดตอัตโนมัติ)
updated_byINTEGERYES0รหัสผู้ใช้ที่แก้ไขล่าสุด
deleted_dateTIMESTAMPTZ(3)YES-วันเวลาที่ลบแบบ soft delete
reasonTEXTYES''เหตุผลประกอบสถานะ เช่น สาเหตุที่ยกเลิกหรือส่งไม่สำเร็จ
rich_message_contentJSONBYES-สำเนาเนื้อหาข้อความ ณ เวลาที่ส่ง (snapshot กันเนื้อหาต้นทางถูกแก้ภายหลัง)
line_message_objectJSONBYES-payload ที่ส่งเข้า LINE Messaging API จริง
template_trackingJSONBYES-ข้อมูล mapping สำหรับติดตามการคลิกในแต่ละส่วนของข้อความ
end_tracking_dateTIMESTAMPTZ(3)YES-วันเวลาสิ้นสุดการเก็บสถิติการคลิกของแคมเปญ
has_merge_tagsBOOLEANNOfalseข้อความมีการใช้ merge tag (ตัวแปรส่วนบุคคล) หรือไม่
skip_merge_tag_missingBOOLEANNOfalseข้ามผู้รับที่ไม่มีค่าของ merge tag แทนที่จะส่งด้วยค่าว่าง
total_activityINTEGERNO0จำนวน activity ที่เกิดจากแคมเปญนี้ทั้งหมด
total_recipientINTEGERNO0จำนวนผู้รับที่ตั้งเป้าจะส่ง
total_reachINTEGERNO0จำนวนผู้รับที่ส่งถึงจริง
total_unique_clickINTEGERNO0จำนวนผู้คลิกแบบไม่นับซ้ำ
total_first_clickINTEGERNO0จำนวนการคลิกครั้งแรกของผู้รับแต่ละคน
claimed_atTIMESTAMPTZYES-เวลาที่ worker จับจอง (claim) แคมเปญไปส่ง ใช้เป็นตัวจับ lease ของสถานะ sending

ตาราง campaign_delivery_batch

ตารางนี้ไม่ได้อยู่ใน Prisma schema — สร้างด้วย manual-sql/8.campaign_delivery_batch.sql เก็บ 1 แถวต่อ 1 batch การส่งของแคมเปญแบบ multicast โดย planner ของ worker เป็นผู้ insert, worker ฝั่งส่งเป็นผู้ claim และอัปเดต และ batch สุดท้ายที่เสร็จจะเป็นตัวปิดงานแคมเปญ

ColumnTypeNullableDefaultคำอธิบาย
idBIGSERIAL (BIGINT)NOnextval(...)รหัสอ้างอิงหลักของ batch
campaign_idINTEGERNO-รหัสแคมเปญที่ batch นี้สังกัด
batch_noINTEGERNO-ลำดับที่ของ batch ภายในแคมเปญ
user_countINTEGERNO-จำนวนผู้รับใน batch นี้
statusVARCHARNO'pending'สถานะของ batch: pending, sending, done, failed
sent_countINTEGERNO0จำนวนที่ส่งสำเร็จใน batch นี้
error_countINTEGERNO0จำนวนที่ส่งไม่สำเร็จ
skipped_countINTEGERNO0จำนวนที่ถูกข้าม (เช่น merge tag ไม่ครบ)
created_dateTIMESTAMPTZNOnow()วันเวลาที่สร้าง batch
updated_dateTIMESTAMPTZNOnow()วันเวลาที่อัปเดต batch ล่าสุด

หมายเหตุ

  • FK ของ campaign: audience_id ไป audience.id, rich_message_id ไป rich_message.id, line_oa_id ไป line_oa.id, organization_id ไป organization.id และถูกอ้างอิงกลับโดย tracking_log.campaign_id
  • Index ของ campaign: line_oa_id, deleted_date
  • คอลัมน์ claimed_at เพิ่มภายหลังผ่าน manual-sql/8.campaign_claim.sql พร้อมกับการเพิ่มค่า sending เข้าไปใน enum CampaignStatus — สถานะ sending หมายถึงถูก worker จับจองแล้ว และ claimed_at เป็นตัวให้ reaper ตรวจว่าแถวไหนค้างเกิน lease แล้วดึงกลับไปเป็น scheduled
  • campaign_delivery_batch มี unique constraint campaign_delivery_batch_campaign_batch_uq บน (campaign_id, batch_no) — ใช้กันการ claim ซ้ำและทำให้ redelivery ส่งซ้ำได้ไม่เกิน 1 batch
  • campaign_delivery_batch มี index campaign_delivery_batch_campaign_status_idx บน (campaign_id, status) สำหรับตรวจว่าแคมเปญยังมี batch ค้างอยู่หรือไม่
  • campaign_delivery_batch.campaign_id ไม่ได้ประกาศเป็น FK constraint ในสคริปต์ (อ้างถึง campaign.id เชิงตรรกะ)