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