Skip to main content

Forms (Form Builder)

Overview

This domain has 4 tables: form_builder stores form definitions (questions, theme, thank-you page) as JSONB, form_submission stores the answers users submit, linked to the form through form_hash, form_builder_rule stores rules applied to form fields, and otp_config stores per-LINE-OA OTP verification settings (SMS via ThaiBulkSMS, and email)

Table form_builder

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
titleTEXTNO-Form title
descriptionTEXTYES-Form description
questionsJSONBNO-Full question definition of the form (array of fields)
themeJSONBYES-Theme / appearance settings for the form
thank_youJSONBYES-Thank-you page settings shown after submission
statusFormBuilderStatus (ENUM)NOdraftForm status: active, inactive, draft, delete
start_dateTIMESTAMPTZ(3)YES-When the form starts accepting answers
end_dateTIMESTAMPTZ(3)YES-When the form stops accepting answers
responses_countINTEGERNO0Number of responses received (counter)
form_hashVARCHAR(50)NO-Public form reference code (unique), used in the form URL
line_oa_idINTEGERYES-LINE OA the form belongs to (FK to line_oa.id)
convert_to_memberBOOLEANYES-Whether to convert the respondent to a member after submission
require_line_loginBOOLEANNOtrueWhether LINE login is required before filling in the form
one_time_submissionBOOLEANYES-Whether a user may submit only once
field_attribute_mappingsJSONBYES'[]'Mapping from form fields to user attributes
created_byINTEGERYES-Creator (user id)
created_atTIMESTAMPTZ(3)NOnow()Creation timestamp
updated_byINTEGERYES-Last updater (user id)
updated_atTIMESTAMPTZ(3)NOnow()Last update timestamp

Table form_submission

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
form_hashVARCHAR(50)NO-Form the answers were submitted to (FK to form_builder.form_hash)
submitted_dateTIMESTAMPTZ(3)YES-When the form was submitted
line_user_idTEXTYES-LINE user id of the respondent (when logged in via LINE)
ip_addressTEXTYES-Respondent IP address
user_agentTEXTYES-Respondent browser user agent
answerJSONBNO-All answers for the form
metadataJSONBYES-Additional submission metadata
is_submittedBOOLEANNOfalseWhether the submission is complete (separates drafts from real answers)

Table form_builder_rule

ColumnTypeNullableDefaultDescription
idSERIALNOnextval(...)Primary key
typeVARCHAR(50)NO-Rule type
nameVARCHAR(100)NO-Rule name
propertiesJSONBNO'{}'Rule parameters
statusCommonStatus (ENUM)NOactiveRule status
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
updated_dateTIMESTAMPTZ(3)YES-Last update timestamp

Table otp_config

ColumnTypeNullableDefaultDescription
idUUIDNOgen_random_uuid()Primary key
line_oa_idBIGINTNO-LINE OA using this configuration (unique — one config per OA)
organization_idBIGINTNO-Organization that owns the configuration
thaibulksms_keyTEXTYES-ThaiBulkSMS API key for sending OTP over SMS
thaibulksms_secret_encTEXTYES-ThaiBulkSMS API secret (stored encrypted)
sms_enabledBOOLEANNOfalseWhether OTP delivery over SMS is enabled
email_enabledBOOLEANNOfalseWhether OTP delivery over email is enabled
email_subjectTEXTYES-OTP email subject line
email_bodyTEXTYES-OTP email body (template)
statusTEXTNO'active'Configuration status
created_dateTIMESTAMPTZ(3)NOnow()Creation timestamp
updated_dateTIMESTAMPTZ(3)YES-Last update timestamp

Notes

  • form_submission.form_hash is a FK to form_builder.form_hash (not to id) with ON DELETE CASCADE — deleting a form deletes all of its submissions
  • form_builder.form_hash has a unique constraint plus a separate index, because it is the key used when opening a form from its public link
  • form_builder.line_oa_id is a FK to line_oa.id and is nullable (forms not yet bound to an OA)
  • Updating form_submission.is_submitted from false to true fires the notify_form_submitted() function, which emits pg_notify on channel form_submitted and inserts into event_outbox (see pg_notify and Event Outbox)
  • otp_config.line_oa_id has a unique constraint — a LINE OA can have only one OTP configuration
  • form_builder_rule has no direct FK to form_builder — rules are referenced from inside the JSONB of form_builder.questions