Form Builder
Overview
Form Builder creates forms for LINE users to fill in — registration forms, surveys, or
prize-draw entries. Each form carries a form hash as its public identifier, and every answer
is stored in the form_submission table.
The module's standout capability is profile mapping, which binds individual answers to fields in the Customer Database or to a LINE user's custom attributes, so submitted data flows straight back into the profile.
It also provides a rule system, stored in form_builder_rule, for conditional logic within
a form — for example, skipping to a different question based on an answer — along with a set of
common rules shared across forms.
Form responses are an important data source for Audience Filter and act as a trigger source for Trigger Rule.
Business Flow
Authoring a form
GET /api/form-builder/common-rulesloads the standard rule set for the form editor to use.POST /api/form-builder(multipart/form-data) creates a form, specifying questions, answer types, rules, and profile mapping. The system generates the form hash automatically.GET /api/form-builderlists all forms with pagination;GET /api/form-builder/:idreturns a single form.PUT /api/form-builder/:id(form-data) updates a form andDELETE /api/form-builder/:idremoves it.
Collecting and reading responses
- LINE users open the form through client-web or LIFF and submit their answers. Submission itself is handled by client-api, not by this module, and if OTP is enabled on the form the respondent must verify their phone number first.
GET /api/form-builder/:id/responsesreads submissions with pagination and filtering perFormSubmissionDto.GET /api/form-builder/:id/statssummarises statistics per question for the form's dashboard.GET /api/form-builder/:id/exportexports all responses as a CSV file.- Answers covered by profile mapping are written back into the Customer Database or the LINE user's custom attributes.
- Each new submission publishes an event to the
form_submitted_triggerqueue so Trigger Rule can act on it.
Key Files & Functions
Core code lives in internal/modules/formbuilder/, comprising controller.go, service.go,
and dto.go. The service consolidates the logic of three TypeScript repositories
(form-builder.repository.ts, form-builder-rule.repository.ts, and
form-submission.repository.ts) into a single file.
| Method | Route | Handler | Policy (metadata) |
|---|---|---|---|
| GET | /api/form-builder | ct.getAllForms | — |
| GET | /api/form-builder/common-rules | ct.getCommonRule | — |
| GET | /api/form-builder/:id | ct.getFormById | — |
| GET | /api/form-builder/:id/responses | ct.getFormResponses | — |
| GET | /api/form-builder/:id/stats | ct.getFormResponseStats | — |
| GET | /api/form-builder/:id/export | ct.exportResponses | — |
| POST | /api/form-builder | ct.createForm | create form-builder |
| PUT | /api/form-builder/:id | ct.updateForm | update form-builder |
| DELETE | /api/form-builder/:id | ct.deleteForm | — |
Every route is wrapped by modulegate.ModuleGate(d, "form-builder"). The function other modules
call is GetFormById(ctx, id), which Audience Filter invokes through an interface.
Connections to Other Services
- Access control —
ModuleGate("form-builder")is actively enforced here.PolicyModuleFormBuilderappears as metadata only on the create and update handlers. - Tables —
form_builder,form_builder_rule,form_submission,customer_database,customer_database_row,line_user,otp_config - RabbitMQ — publishes to the
form_submitted_triggerqueue. - Storage Service — holds form attachments and exported CSV files.
- Cross-module — consumed by Audience Filter, and linked to Customer Database through the
databaseIdkey insideprofile_mapping. - Related modules — OTP Config, Trigger Rule, Audience Filter, and Customer Database.