FLS Platform Overview
What is FLS?
The Form Lifecycle Service (FLS) is the central form and survey collection platform inside GoodBooks GB5. Any module that needs to collect structured responses from people — post-training feedback, annual appraisals, satisfaction surveys, peer reviews, or quick ratings — uses FLS as its engine instead of building its own form system.
FLS handles the entire lifecycle of a form deployment: creating the questionnaire, assigning it to the right people, dispatching token-based access links, tracking who has responded and who hasn't, sending automated reminders, aggregating results, and publishing completion events back to the originating module.
FLS Core
Registrations, instances, groups, respondents, sessions. The form lifecycle engine that every other component builds on.
Survey Engine
Multi-section questionnaires with 6 question types — rating stars, NPS, single/multi choice, yes-no, free text.
QuickRating Widget
One-tap star or numeric rating embeddable in any screen. No survey, no session — just a single score with optional comment.
TMS Feedback Bridge
Pre-built integration between the Training Management System and FLS. Auto-dispatches feedback after batch completion; gates certificates on submission.
Why FLS Exists
Before FLS, each module (TMS, HRMS, CRM) built its own ad-hoc form collection: separate tables, separate email dispatch, no shared reminders, no consistent token-based access, no common results format. Maintaining four separate form systems created duplicated effort and inconsistent experiences.
| Capability | Before FLS (per-module) | With FLS (shared platform) |
|---|---|---|
| Token links (no-login access) | Ad-hoc or not supported | Built-in; every respondent gets a GUID token link |
| Automated reminders | Manual or hardcoded | Configurable reminder rules (Day 3, Day 6, on deadline) |
| Anonymous responses | Not available in most | IsAnonymous flag on any survey instrument |
| Multi-step forms | Not supported | StepNo sequencing (employee → manager → HR) |
| Result aggregation | Custom SP per module | Pre-built TSURVEYRESPONSESUMMARY with AvgRating, NPS, distributions |
| Certificate gating | TMS-only custom logic | FLS BlockingFlag + BlockingSp — any module can use it |
| Real-time monitoring | Not available | SignalR FlsMonitorHub with live completion % push |
| Cross-module events | Not available | Bridge config + Dapr pub/sub: FormSubmitted, InstanceCompleted, etc. |
Platform Components at a Glance
The four components are layered — FLS Core provides the foundational lifecycle, Survey Engine and QuickRating provide collection mechanisms, and the TMS Bridge is the first production integration built on top.
TMS · HRMS · CRM · PERM — any module that needs form collection
Registration · Instance · Group · Respondent · Session · Access Rules
Instrument Config · Sections · Question Bank · Answers · Summary Aggregation
Rating Config · 1-tap submit · Summary badge · Trend data
MFLSBRIDGECONFIG · MFLSEVENTSUBSCRIPTION · Dapr pub/sub or HTTP webhook · Retry logic
Email · SMS · Push · Token links dispatched via Enterprise Integration Platform
Form Lifecycle
Every FLS Instance passes through a defined lifecycle. Understanding which state an instance is in tells you exactly what respondents can do and what admin actions are available.
| Status | Triggered by | Respondents can… | Admin can… |
|---|---|---|---|
| Draft | Instance created via API or SP | Nothing — tokens not yet generated | Edit all settings, add respondents |
| Scheduled | Schedule endpoint called with OpensFrom/ClosesOn | Nothing — form not yet open | Modify schedule, add respondents |
| Open | OpenFlsInstance called (or OpensFrom time passes via Quartz job) | Access form via token link, fill and submit | Add respondents, send nudges, view live progress |
| Paused | Admin calls ControlFlsInstance(Action=Pause) | Cannot submit new responses — form link shows "Paused" | Resume (returns to Open) or Close |
| Closed | Admin closes, or ClosesOn date passes | Cannot access form — link shows "Closed" | View results, archive |
| Archived | Admin archives closed instance | No access | Read-only results only |
Roles & Permissions
Access to FLS data is governed by MFLSACCESSRULE. Each rule grants a Principal (User or Role) an AccessType for a specific Registration, with an optional Scope (all orgs, one org unit, one department).
| Role | Create Registration | Create Instance | View Summary Results | View Individual Responses | Manage Respondents |
|---|---|---|---|---|---|
| System Admin | ✓ | ✓ | ✓ | ✓ | ✓ |
| HR Admin (AccessType=Manage) | ✓ | ✓ | ✓ | ✓ | ✓ |
| Incharge (AccessType=ViewSummary) | ✗ | ✓ (own instances) | ✓ | ✗ | ✓ (nudge only) |
| Incharge (AccessType=ViewResponses) | ✗ | ✓ (own instances) | ✓ | ✓ | ✓ |
| Respondent | ✗ | ✗ | ✗ | ✗ | ✗ |
Incharges can be scoped to a specific Org Unit (Scope=OrgUnit, ScopeObjectId=WorkOUId) or Department. This means a department head can view FLS results for their department only — they cannot see other departments' responses even within the same instance.
Token-based Access
One of FLS's most important features is that respondents do not need a GoodBooks login. Every respondent gets a unique GUID access token embedded in their link. This makes FLS ideal for external feedback, customer surveys, or any scenario where logging in creates friction.
Here is the full token-based access flow:
Admin opens instance → POST /fls/instances/42/open is called. FLS transitions status to Open.
Tokens generated → FLS creates one AccessToken (GUID) per respondent in MFLSRESPONDENT. TokenExpiry set to now + TokenExpiryHours (e.g., 72 hours).
EIP dispatches email → FLS publishes to LFLSDISPATCHLOG. EIP picks up the dispatch job and sends a personalised email with the token link: https://app/survey?token=9f4e8c12-…
Respondent clicks link → No login required. The Angular app calls POST /fls/sessions/open with the token.
FLS validates token → Checks MFLSRESPONDENT: token exists, not expired, status ≤ InProgress. Returns FlsSessionContextDto with the survey instrument and session ID.
Respondent fills form → Draft auto-saved via POST /fls/sessions/{id}/draft. RespondentSts updated to InProgress.
Respondent submits → POST /fls/sessions/{id}/submit. RespondentSts set to Submitted. TFLSRESPONSESESSION row created. FormSubmitted event published.
If a respondent clicks the link after the token has expired, they see an "Expired" page. The admin can nudge (re-dispatch) the respondent to generate a fresh token, or manually mark them as submitted if they completed it through another channel.
Multi-step Forms
FLS supports sequential multi-step workflows where different people fill different forms in order. The classic example is an annual appraisal: the employee fills Step 1 (self-assessment), then the manager reviews in Step 2, and HR finalises in Step 3. Each step can use a different survey instrument.
| StepNo | Who fills it | Unlocked when | Example form |
|---|---|---|---|
| 1 | Employee (self) | Instance opens | Self-assessment questionnaire |
| 2 | Manager | All Step 1 respondents in group submitted (or GroupBlockingSp returns OK) | Manager review and rating |
| 3 | HR Admin | All Step 2 respondents submitted | HR sign-off and final grade |
BlockingFlag=1 on MFLSINSTANCEGROUP means Step 2 respondents cannot access their form until Step 1 is complete. BlockingSp is an optional stored procedure that validates the blocking condition — allowing complex rules like "at least 80% of Step 1 must submit before Step 2 opens".
FLS Core
FLS Core is the lifecycle engine. It does not care what type of form is being filled — that's the Survey Engine's job. FLS Core manages who fills what, when, and tracks whether they did.
Key Database Tables
| Table | Purpose | Key Fields |
|---|---|---|
| MFLSREGISTRATION | Master config template for a type of form (e.g., "TMS Training Feedback") | FlsRegistrationId, RegistrationCode, FormTemplateId, CompletionMethod, AllowDraftResponse, TokenExpiryHours |
| MFLSINSTANCE | A specific deployment of a registration (e.g., Q2-2026 batch feedback) | FlsInstanceId, FlsRegistrationId, InstanceStatus (0–5), EntityObjectId, OpensFrom, ClosesOn |
| MFLSINSTANCEGROUP | Target audience groups within an instance | GroupId, FlsInstanceId, GroupName, RespondentCount, SubmittedCount, StepCount, BlockingFlag |
| MFLSRESPONDENT | One row per person assigned to fill a form | FlsRespondentId, AccessToken (GUID), TokenExpiry, RespondentSts (0–5), FirstOpenedAt, SubmittedAt |
| TFLSRESPONSESESSION | Session tracking per attempt | FlsSessionId, FlsRespondentId, SessionStatus, StartedAt, SubmittedAt, TimeTakenSeconds |
| MFLSREMINDERRULE | Automated reminder/escalation rules per registration | DayOffset, StatusFilter, ReminderAction (Notify / Escalate / AutoClose), EipTemplCode |
| MFLSACCESSRULE | Who can view/manage a registration | PrincipalType, PrincipalId, AccessType (0=Manage, 1=ViewSummary, 2=ViewResponses), Scope |
Respondent Status Codes
| Code | Status | What it means |
|---|---|---|
| 0 | Not Started | Token dispatched but respondent has not clicked the link yet |
| 1 | Opened | Respondent clicked the link; session started |
| 2 | In Progress | At least one draft answer saved |
| 3 | Submitted | Form fully submitted — no further changes allowed |
| 4 | Expired | Token expiry date passed before submission |
| 5 | Opted Out | Respondent explicitly opted out via the form link |
Survey Engine
The Survey Engine manages questionnaire design and collects structured answers. It sits on top of FLS Core — a survey instrument is linked to a FLS Registration, and answers are stored per FLS Session.
Instrument Hierarchy
Survey Instrument Config (MSURVEYINSTRUMENTCONFIG) — The top-level questionnaire. Settings: title, language, anonymous flag, NPS enabled, version. Linked to one FLS Registration.
Sections (MSURVEYINSTRUMENTSECTION) — Groups of related questions shown on one page. Example: "General Feedback" + "Trainer Evaluation".
Question Bank (MSURVEYQUESTIONBANK) — Reusable questions with question code, text, type. Can be shared across multiple instruments.
Instance Questions (MSURVEYINSTQUESTION) — Links a bank question to a specific instrument section, with override settings (required, weight, scale, branch rules).
6 Question Types
QuickRating Widget
QuickRating is a lightweight one-tap rating component. Unlike a full survey, it requires no FLS instance, no session, no sections — just a configured scale and an entity to rate. It's designed to be embedded inline in any screen (TMS batch card, product page, service ticket).
| Feature | Detail |
|---|---|
| Scale types | Stars 1–5, Stars 1–10, Numeric 0–10, Numeric 1–100 |
| Entity scoping | ObjectTypeId (what kind of thing) + ObjectId (which specific one). E.g., ObjectTypeId=3=Trainer, ObjectId=301=Arun Krishnamurthy |
| Business context | BizTransactionTypeId distinguishes rating contexts for the same entity — e.g., rate trainer per session vs. overall |
| Optional comment | AllowComment: 0=None, 1=Optional, 2=Required. CommentMaxLength configurable. |
| Multi-rating | AllowMultiRating=1: user can rate again (IsLatest flag tracks most recent). AllowMultiRating=0: one rating per user per entity. |
| Anonymous | IdentityMode=0: ratings stored without linking to user identity. IdentityMode=1: user is recorded. |
| Summary badge | Live aggregated AvgRating, count, NPS Score, RatingDistJson shown to other users viewing the entity. |
TMS Feedback Bridge
The TMS module integrates with FLS through a dedicated bridge. When a training batch is completed, TMS auto-dispatches a feedback survey to all learners using a single stored procedure call. The trainer's rating is aggregated from dimension questions in the survey.
Training Manager marks batch as completed (or sets auto-dispatch in settings).
TmsFeedbackBLL calls SP_TMS_DISPATCHFEEDBACK with BatchId, InstrumentConfigId, BlockCertificate flag, and list of EnrollmentIds.
The SP creates the MFLSINSTANCE, MFLSINSTANCEGROUP, and one MFLSRESPONDENT row per learner. It returns (FlsInstanceId, RespondentCount).
TmsFeedbackBLL calls OpenFlsInstance → tokens generated → EIP sends learners their feedback link.
As learners submit, the FormSubmitted event fires → TMS handler aggregates trainer ratings (AvgKnowledge, AvgClarity, AvgEngagement) from the survey answers.
If BlockCertificate=true, the certificate issuance SP checks RespondentSts=3 (Submitted) before issuing. Learners who haven't submitted are blocked.
Where FLS Fits in GB5
FLS is a horizontal platform service — it lives below individual business modules and provides shared capabilities they all consume. Think of it the way EIP (Enterprise Integration Platform) provides notifications: FLS provides form collection.
| GB5 Module | Uses FLS for | Form type | Key feature used |
|---|---|---|---|
| TMS (Training) | Post-training feedback | Survey (6 questions) | Certificate gating, trainer rating aggregation |
| HRMS | Annual appraisals | Survey (multi-step) | 3-step sequential: employee → manager → HR |
| PERM (Performance) | 360° review & OKR feedback | Survey (anonymous) | Anonymous IsAnonymous=1, multiple rater types |
| CRM / Sales | Customer satisfaction | Survey (short poll) | External token access, no GB5 login needed |
| Any module | Quick star rating on any entity | QuickRating widget | Inline embed, 1-tap, summary badge |
Module Integration Map
Each module that integrates with FLS registers a Bridge Config (MFLSBRIDGECONFIG) row. This row tells FLS where to send events when things happen — either via Dapr pub/sub or via HTTP webhook.
| Column | Value example | Purpose |
|---|---|---|
| ModuleId | 301 (TMS), 501 (HRMS) | Identifies the owning module |
| IsDapr | 1 = Dapr, 0 = HTTP | Event delivery mechanism |
| DaprPubSubTopic | tms-fls-events | Dapr topic to publish to (if IsDapr=1) |
| EventHandlerUrl | /tms/webhooks/fls | HTTP endpoint for events (if IsDapr=0) |
| SummarySpName | SP_TMS_FLS_UPDATESUMMARY | SP to call after InstanceCompleted to aggregate results |
| ResponseVisibility | 0=All, 1=Incharge, 2=HROnly | Who can see individual respondent answers |
| AllowRespondentAdd | 1 = yes | Can respondents be added after instance opens? |
Event & Bridge System
When significant things happen inside FLS, it publishes events to LFLSEVENTLOG. A background job picks these up and dispatches them to each registered module via Dapr or HTTP. If delivery fails, FLS retries with exponential backoff.
| EventType | Code | When fired | Typical handler action |
|---|---|---|---|
| FormSubmitted | 0 | Individual respondent submits their form | TMS: update learner status, aggregate trainer rating |
| StepCompleted | 1 | All respondents in a step group submitted | HRMS: unlock next appraisal step for managers |
| InstanceCompleted | 2 | All steps across all groups submitted | Call SummarySpName to aggregate final results |
| InstanceExpired | 3 | ClosesOn date passes with incomplete responses | Mark pending respondents as Expired |
| RespondentOverdue | 4 | Individual deadline passes | Flag certificate block, notify manager |
| InstanceStatusChanged | 5 | Instance paused, resumed, or closed | Update module UI, notify stakeholders |
| RespondentOpened | 6 | Respondent clicks link and opens form | Analytics: track open rate |
LFLSEVENTLOG.EVENTSTATUS tracks delivery: 0=Pending, 1=Success, 2=Failed, 3=Retry. On failure, FLS waits NextRetryOn (exponential backoff) before retrying up to MaxRetries times (configured per event subscription). After exhausting retries, the row stays at EventStatus=2 — a failed event alert should be monitored.
SignalR Real-Time Monitoring
For form incharges who want to watch submissions happen live (e.g., during a training day when 70 learners are filling feedback simultaneously), FLS provides a SignalR hub that pushes completion updates without any page refresh.
| Aspect | Detail |
|---|---|
| Hub class | FlsMonitorHub (FLSSL/Hubs/FlsMonitorHub.cs) |
| Group pattern | fls:instance:{flsInstanceId} — scoped to one instance |
| Client method | ReceiveSummaryUpdate(FlsInstanceSummaryDto) — pushed to all watching incharges |
| When pushed | After every FormSubmitted event — completion %, submitted count, in-progress count updated in real time |
| Join/Leave | Incharge calls JoinInstanceMonitor(flsInstanceId) on connect; LeaveInstanceMonitor on navigate away |
Scenario 1 · TMS Post-Training Feedback
Scenario 1 — TMS Post-Training Feedback with Certificate Gate
Setup (one-time): HR Admin creates FLS Registration "TMS Training Feedback" (FlsRegistrationId=7) with CompletionMethod=Survey, TokenExpiryHours=72, reminder rules: Day 3 nudge, Day 6 escalation. Survey Instrument Config #18 is designed with 6 questions (Rating, NPS, Knowledge, Clarity, Engagement, Comments).
Batch completes: Training Manager marks Batch #TRG-2026-047 "Advanced Excel for Finance" as completed in TMS. Auto-dispatch is enabled.
SP_TMS_DISPATCHFEEDBACK executes: Creates MFLSINSTANCE (FlsInstanceId=42, "TMS Batch Feedback Q2-2026"), MFLSINSTANCEGROUP (70 learners, BlockingFlag=1 for certificate gate), and 70 MFLSRESPONDENT rows. BLL calls OpenFlsInstance → all 70 get email with personalised token links.
Learners fill feedback: Over the next 3 days, learners click their link, fill 6 questions (takes ~3 minutes), and submit. Each submission fires FormSubmitted → TMS handler updates trainer rating aggregation.
Day 3 reminder: Quartz job runs MFLSREMINDERRULE → identifies 22 learners still Not Started → EIP sends reminder emails automatically.
Training Manager monitors: Opens FLS admin dashboard. Sees live progress via SignalR: 45/70 submitted (64%). Sends manual nudge to 3 overdue learners.
Certificate gating: 25 learners attempt to download certificate from TMS. SP_TMS_CHECKFEEDBACKBLOCK returns "blocked" for each — they see "Please submit your feedback to unlock your certificate."
Instance closes: After 7 days (ClosesOn date), instance auto-closes. Final trainer ratings: Knowledge=4.6, Clarity=4.2, Engagement=4.5, Overall=4.4. HR views Trainer Rating Card showing Q2 2026 performance.
Scenario 2 · HR Annual Appraisal (3-step Multi-step)
Scenario 2 — Annual Appraisal with Manager Review and HR Sign-off
Setup: HR creates Registration "Annual Appraisal 2026" with StepCount=3. Three instrument configs: #21 (self-assessment, 12 questions), #22 (manager review, 8 questions), #23 (HR sign-off, 4 questions).
Instance created: HR creates Instance "Appraisal Cycle Q4-2026" with 3 groups per department (200 employees, 45 managers, 5 HR reviewers). OpensFrom=1 Dec, ClosesOn=31 Dec.
Step 1 — Employee self-assessment: 200 employees receive token links. They fill 12-question self-assessment covering goals, competencies, achievements. Draft auto-saved; 180 submit by Dec 10.
BlockingFlag check: When all employees in a group submit Step 1, StepCompleted event fires → BlockingSp validates → Step 2 tokens dispatched to the 45 managers.
Step 2 — Manager review: Each manager sees their direct reports' Step 1 answers (read-only context) alongside 8 rating questions. Managers fill and submit by Dec 20.
Step 3 — HR sign-off: HR reviewers get Step 3 tokens with consolidated view of Steps 1+2. They finalise the grade and add notes. InstanceCompleted fires → HRMS annual review records updated.
Scenario 3 · 360° Anonymous Peer Review
Scenario 3 — 360° Anonymous Peer Review for Leadership Program
Instrument created: Survey #25 (360° Feedback), IsAnonymous=1. Questions: Leadership behaviour (5-star rating × 4 dimensions) + 2 open text questions. Respondent names will NOT appear in results.
Instance created: "Leadership 360 — Kavitha Reddy". Group: 7 respondents (5 peers, 1 manager, 1 subordinate). RespondentType codes used to classify rater relationship.
Responses collected: All 7 raters fill anonymously. Each sees only the questions, not who else is participating. Answers stored with FlsRespondentId but no name in results query.
Results viewed: HR and Kavitha's manager view the results dashboard. They see average ratings per dimension and anonymised text comments — but cannot identify who gave which rating.
Scenario 4 · Post-Event Satisfaction Poll
Scenario 4 — Post-Conference Satisfaction Poll (No GB5 Login Required)
Quick setup: 3-question poll created: "Overall rating (1-5 stars)", "Would you attend again? (Yes/No)", "What could be improved? (free text)". IsAnonymous=1. TokenExpiryHours=72.
200 attendees added: Bulk CSV import of attendee emails. FLS generates 200 tokens. Instance opened; EIP sends personalised token links in the post-event thank-you email.
No login needed: Attendees click link from their personal email. No GB5 account required. Form loads immediately with the 3 questions. Takes 90 seconds to complete.
Auto-close: After 3 days, instance auto-closes. Results: Overall avg 4.1, 78% would attend again, 150 text comments aggregated.
Scenario 5 · Inline Quick Trainer Rating
Scenario 5 — Learner Rates Trainer with QuickRating Widget (No Survey)
Widget configured: QuickRating Config #5 — ObjectTypeId=3 (Trainer), ScaleMax=5 (stars), AllowComment=1 (optional), AllowMultiRating=0 (rate once per session).
Widget appears: When Bhavana opens her training batch card in TMS, the widget renders inline: "⭐⭐⭐⭐⭐ Rate this trainer". Below it, a summary badge shows "4.3 avg from 87 ratings".
Bhavana rates: She clicks 4 stars → optional comment textarea appears → types "Clear explanations, very patient." → clicks Submit.
Immediate feedback: Widget transitions to "Thank you for your rating!" and the summary badge updates to "4.3 avg from 88 ratings" (live update via SubmitRating response).
No instance needed: This entire flow used zero FLS instances, zero sessions, zero Survey Engine calls. Just a single QuickRating API call.
System Admin
System Admin
Full AccessThe System Admin has unrestricted access to all FLS data across all tenants. They configure the foundational wiring that other roles depend on.
- Create and manage FLS Registrations (master configs)
- Configure Bridge Config rows linking modules to FLS events
- Manage EIP templates for FLS dispatch emails
- View and manage all instances across all registrations
- Grant/revoke Access Rules for HR Admins and Incharges
- Monitor LFLSEVENTLOG for failed event deliveries
- Archive completed instances
HR Admin
HR Admin
AccessType = ManageHR Admins own specific registrations granted to them. They create and operate instances for HR-driven processes (appraisals, satisfaction surveys, policy acknowledgements).
- Design Survey Instruments (sections, questions, anonymous settings)
- Create instances, schedule opens/closes, add groups
- Add respondents individually or via bulk CSV import
- View all results including individual responses
- Send reminders and nudges to pending respondents
- Pause, resume, or close instances
- Export results to CSV / Excel
Instance Incharge
Instance Incharge
AccessType = ViewSummary or ViewResponsesIncharges are assigned to specific instances (e.g., a Training Manager is incharge of the TMS feedback instance for their batch). They monitor progress and manage respondents but cannot create registrations.
- View completion dashboard for their assigned instances
- Send reminders to pending/overdue respondents
- View aggregated survey results (always)
- View individual responses (only if AccessType=ViewResponses)
- View real-time completion via SignalR monitor
- Add respondents if AllowRespondentAdd is enabled in Bridge Config
Respondent
Respondent
Token access onlyThe person who fills the form. They interact with FLS exclusively through their unique token link — no GoodBooks login required unless the survey is configured for authenticated access.
- Open form via personalised token link (email/SMS)
- Fill form across one or more sections
- Save draft (auto-saves every answer change)
- Submit form (finalises response — cannot change after)
- Opt out via the form footer opt-out link (if AllowOptOut is enabled)
- See their own submitted answers if instrument shows confirmation page
Module Integrator (Developer)
Module Integrator
Developer roleDevelopers who integrate a new GB5 module (or external system) with FLS. They configure Bridge Config rows, implement event handlers, and build dispatch logic using FLS APIs.
- Create MFLSBRIDGECONFIG row for the new module
- Subscribe to relevant FlsEventTypes (FormSubmitted, InstanceCompleted, etc.)
- Implement Dapr subscriber or HTTP webhook for event handling
- Call FLS APIs (dispatch, status, nudge) from module BLL
- Store FlsInstanceId in module tables for cross-reference
- Use GetFlsInstanceSummary for embedding completion widgets
GoodBooks GB5 · FLS Platform Overview · 2026-07-01