ฟอร์ม (Form Builder)
ภาพรวม
Domain นี้มี 4 ตาราง: form_builder เก็บนิยามฟอร์ม (คำถาม/ธีม/หน้าขอบคุณ) แบบ JSONB,
form_submission เก็บคำตอบที่ผู้ใช้ส่งเข้ามาโดยอ้างอิงฟอร์มผ่าน form_hash,
form_builder_rule เก็บ rule ที่นำไปใช้กับ field ในฟอร์ม และ otp_config
เก็บการตั้งค่าช่องทางยืนยัน OTP (SMS ผ่าน ThaiBulkSMS และอีเมล) แยกตาม LINE OA
ตาราง form_builder
| Column | Type | Nullable | Default | คำอธิบาย |
|---|---|---|---|---|
id | SERIAL | NO | nextval(...) | Primary key |
title | TEXT | NO | - | ชื่อฟอร์ม |
description | TEXT | YES | - | คำอธิบายฟอร์ม |
questions | JSONB | NO | - | นิยามคำถามทั้งหมดของฟอร์ม (array ของ field) |
theme | JSONB | YES | - | การตั้งค่าธีม/หน้าตาของฟอร์ม |
thank_you | JSONB | YES | - | การตั้งค่าหน้าขอบคุณหลังส่งฟอร์ม |
status | FormBuilderStatus (ENUM) | NO | draft | สถานะฟอร์ม: active, inactive, draft, delete |
start_date | TIMESTAMPTZ(3) | YES | - | วันเวลาที่เริ่มเปิดรับคำตอบ |
end_date | TIMESTAMPTZ(3) | YES | - | วันเวลาที่ปิดรับคำตอบ |
responses_count | INTEGER | NO | 0 | จำนวนคำตอบที่ได้รับ (counter) |
form_hash | VARCHAR(50) | NO | - | รหัสอ้างอิงฟอร์มแบบสาธารณะ (unique) ใช้ในลิงก์ฟอร์ม |
line_oa_id | INTEGER | YES | - | LINE OA ที่ฟอร์มนี้สังกัด (FK ไป line_oa.id) |
convert_to_member | BOOLEAN | YES | - | ให้เปลี่ยนสถานะผู้ตอบเป็น member หลังส่งฟอร์มหรือไม่ |
require_line_login | BOOLEAN | NO | true | บังคับให้ล็อกอิน LINE ก่อนกรอกฟอร์มหรือไม่ |
one_time_submission | BOOLEAN | YES | - | จำกัดให้ผู้ใช้หนึ่งคนส่งได้ครั้งเดียวหรือไม่ |
field_attribute_mappings | JSONB | YES | '[]' | การ map field ในฟอร์มไปยัง attribute ของผู้ใช้ |
created_by | INTEGER | YES | - | ผู้สร้าง (user id) |
created_at | TIMESTAMPTZ(3) | NO | now() | วันเวลาที่สร้าง |
updated_by | INTEGER | YES | - | ผู้แก้ไขล่าสุด (user id) |
updated_at | TIMESTAMPTZ(3) | NO | now() | วันเวลาที่แก้ไขล่าสุด |
ตาราง form_submission
| Column | Type | Nullable | Default | คำอธิบาย |
|---|---|---|---|---|
id | SERIAL | NO | nextval(...) | Primary key |
form_hash | VARCHAR(50) | NO | - | รหัสฟอร์มที่ส่งคำตอบเข้ามา (FK ไป form_builder.form_hash) |
submitted_date | TIMESTAMPTZ(3) | YES | - | วันเวลาที่กดส่งฟอร์ม |
line_user_id | TEXT | YES | - | LINE user id ของผู้ตอบ (ถ้าล็อกอิน LINE) |
ip_address | TEXT | YES | - | IP address ของผู้ตอบ |
user_agent | TEXT | YES | - | User agent ของเบราว์เซอร์ผู้ตอบ |
answer | JSONB | NO | - | คำตอบทั้งหมดของแบบฟอร์ม |
metadata | JSONB | YES | - | ข้อมูลเพิ่มเติมของการส่งฟอร์ม |
is_submitted | BOOLEAN | NO | false | ส่งฟอร์มสมบูรณ์แล้วหรือยัง (ใช้แยก draft ออกจากคำตอบจริง) |
ตาราง form_builder_rule
| Column | Type | Nullable | Default | คำอธิบาย |
|---|---|---|---|---|
id | SERIAL | NO | nextval(...) | Primary key |
type | VARCHAR(50) | NO | - | ประเภทของ rule |
name | VARCHAR(100) | NO | - | ชื่อ rule |
properties | JSONB | NO | '{}' | พารามิเตอร์ของ rule |
status | CommonStatus (ENUM) | NO | active | สถานะของ rule |
created_date | TIMESTAMPTZ(3) | NO | now() | วันเวลาที่สร้าง |
updated_date | TIMESTAMPTZ(3) | YES | - | วันเวลาที่แก้ไขล่าสุด |
ตาราง otp_config
| Column | Type | Nullable | Default | คำอธิบาย |
|---|---|---|---|---|
id | UUID | NO | gen_random_uuid() | Primary key |
line_oa_id | BIGINT | NO | - | LINE OA ที่ใช้การตั้งค่านี้ (unique — หนึ่ง OA ต่อหนึ่ง config) |
organization_id | BIGINT | NO | - | องค์กรเจ้าของการตั้งค่า |
thaibulksms_key | TEXT | YES | - | API key ของ ThaiBulkSMS สำหรับส่ง OTP ทาง SMS |
thaibulksms_secret_enc | TEXT | YES | - | API secret ของ ThaiBulkSMS (เก็บแบบเข้ารหัส) |
sms_enabled | BOOLEAN | NO | false | เปิดใช้งานการส่ง OTP ทาง SMS หรือไม่ |
email_enabled | BOOLEAN | NO | false | เปิดใช้งานการส่ง OTP ทางอีเมลหรือไม่ |
email_subject | TEXT | YES | - | หัวเรื่องอีเมล OTP |
email_body | TEXT | YES | - | เนื้อหาอีเมล OTP (template) |
status | TEXT | NO | 'active' | สถานะของการตั้งค่า |
created_date | TIMESTAMPTZ(3) | NO | now() | วันเวลาที่สร้าง |
updated_date | TIMESTAMPTZ(3) | YES | - | วันเวลาที่แก้ไขล่าสุด |
หมายเหตุ
form_submission.form_hashเป็น FK ไปยังform_builder.form_hash(ไม่ใช่id) พร้อมON DELETE CASCADE— ลบฟอร์มแล้วคำตอบทั้งหมดจะถูกลบตามform_builder.form_hashมี unique constraint และมี index แยกอีกหนึ่งตัว เพราะถูกใช้เป็น key ในการเปิดฟอร์มจากลิงก์สาธารณะform_builder.line_oa_idเป็น FK ไปline_oa.idและเป็น nullable (ฟอร์มที่ยังไม่ผูก OA)- การอัปเดต
form_submission.is_submittedจากfalseเป็นtrueจะ trigger ฟังก์ชันnotify_form_submitted()ซึ่งยิงpg_notifychannelform_submittedและ insert ลงevent_outbox(ดู pg_notify และ Event Outbox) otp_config.line_oa_idมี unique constraint — หนึ่ง LINE OA มีการตั้งค่า OTP ได้ชุดเดียวform_builder_ruleไม่มี FK ตรงไปยังform_builder— rule ถูกอ้างอิงจากภายใน JSONB ของform_builder.questions