Skip to main content

ฟอร์ม (Form Builder)

ภาพรวม​

Form builder ให้แอดมินสร้างฟอร์มเก็บข้อมูลลูกค้า เช่น งาน lead generation หรือการลงทะเบียน สมาชิก แล้วเปิดให้กรอกผ่าน LIFF หรือลิงก์สาธารณะ คำตอบที่ได้สามารถ เขียนกลับเป็น attribute ของเพื่อน LINE และเปลี่ยนสถานะผู้ใช้จาก guest เป็น member ได้

จุดที่ควรทราบเกี่ยวกับการออกแบบคือ โครงสร้างคำถามทั้งฟอร์มถูกเก็บเป็น JSONB ก้อนเดียว ไม่มีตารางคำถามหรือตัวเลือกแยกออกมา โดยมี form_builder_rule ทำหน้าที่เป็น master ของกติกา validate สำหรับฟิลด์แต่ละชนิด

โครงสร้างข้อมูลหลัก​

form_builder (model FormBuilder)​

  • title, description, questions JSONB, theme JSONB
  • thank_you JSONB (nullable) — ค่า NULL มีความหมายเทียบเท่า {"mode":"default"} คือใช้หน้าขอบคุณมาตรฐานภาษาไทย
  • form_hash VARCHAR(50) unique — คีย์สาธารณะที่ใช้ในลิงก์ และเป็นเป้าหมายของ FK จากฝั่ง submission
  • status (enum FormBuilderStatus) — active / inactive / draft / delete
  • ช่วงเวลาเปิดรับ start_date / end_date และตัวนับ responses_count
  • พฤติกรรมของฟอร์ม require_line_login (default true), one_time_submission และ convert_to_member
  • field_attribute_mappings JSONB — map คำถามไปยัง attribute ของ line_user
  • profile_mapping JSONB (เพิ่มด้วย manual SQL) — เติมข้อมูลอัตโนมัติจากฐานลูกค้า และเก็บคีย์ย่อย otp ว่าฟิลด์ใดต้องยืนยันตัวตน
  • line_oa_id FK (nullable)

form_submission (model FormSubmission)​

  • form_hash FK → form_builder.form_hash (ON DELETE CASCADE) — สังเกตว่าอ้างด้วย hash ไม่ใช่ id
  • answer JSONB และ metadata JSONB
  • line_user_id, ip_address, user_agent, submitted_date
  • is_submitted — แถวถูกสร้างตั้งแต่ผู้ใช้เริ่มกรอก แล้วจึงตั้งเป็น true เมื่อกดส่งจริง

form_builder_rule (model FormBuilderRule)​

ตาราง master ของกติกา validate แยกตามชนิดฟิลด์

  • type เช่น short_text, paragraph, email, phone, number, file_upload, date, date_of_birth
  • name และ properties JSONB ซึ่งเก็บ regex, ค่า min/max และข้อความ error ทั้งภาษาไทยและอังกฤษ

otp_config (model OtpConfig, PK UUID)​

หนึ่งแถวต่อหนึ่ง OA (line_oa_id unique)

  • thaibulksms_key และ thaibulksms_secret_enc ซึ่งเข้ารหัสด้วย AES โดยใช้ APP_ENCRYPT_SECRET ไม่มีการเก็บค่า plaintext
  • sms_enabled, email_enabled, email_subject, email_body

Trigger​

form_submission_notify (AFTER INSERT OR UPDATE) เรียก notify_form_submitted() เพื่อยิง pg_notify('form_submitted', ...) เมื่อ is_submitted เปลี่ยนเป็น true ตัวฟังก์ชันจะ join form_builder ไปยัง line_oa เพื่อประกอบ lineOaId และ organizationId ลงใน payload

ไฟล์ที่เกี่ยวข้อง​

  • prisma/schema.prisma:916 — model FormBuilder
  • prisma/schema.prisma:948 — model FormSubmission
  • prisma/schema.prisma:904 — model FormBuilderRule
  • prisma/schema.prisma:802 — model OtpConfig
  • prisma/migrations/20260725090000_add_form_builder_thank_you/migration.sql
  • prisma/migrations/20260726100000_add_otp_config/migration.sql
  • manual-sql/6.customer_database.sql — เพิ่มคอลัมน์ form_builder.profile_mapping
  • manual-sql/2.notify_attribute_change.sql และ manual-sql/5.sql — trigger form_submitted
  • seed-data/16.form_builder_rule.sql — seed กติกา validate ครบทุกชนิดฟิลด์
  • schema-dumps/2026-07-24/schema.sql:1749, :1832, :1797

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

  • client-api-go — โหลดฟอร์มจาก form_hash validate ด้วย form_builder_rule ส่ง OTP บันทึก submission และเปลี่ยน rich menu หลังส่งสำเร็จ
  • cms-api-go — สร้างและแก้ไขฟอร์ม ดูคำตอบ ตั้งค่า OTP และ profile mapping
  • worker-go — listen ช่อง form_submitted เพื่อเขียน attribute จัดเข้ากลุ่ม audience และจุด workflow

โดเมนที่เกี่ยวข้อง: เพื่อน LINE, Attribute Master, ฐานข้อมูลลูกค้า, Rich Menu