1. Stage 9 Objective
Stage 9 collects the remaining personal information, regulatory declarations, segment preferences, and nominee details required to complete the account opening form. It comprises four distinct sub-sections:
A
Personal Details — Education, occupation, annual income, family names, marital status, and investment preferences. Several fields are pre-filled from earlier stages (DigiLocker, KRA).
B
PEP Declaration — Politically Exposed Person declaration. If the customer declares PEP = Yes, the journey continues but the lead is flagged NON_STP and routed to the compliance queue after eSign (bypassing the standard verifier).
C
F&O Segment Selection — Optional toggle for Futures & Options. If enabled, income proof is collected via Account Aggregator (Onemoney). If AA succeeds, income proof is captured in this stage. If AA fails or the customer cancels, stage_10_required = true and the customer is routed to Stage 10 for manual document upload.
D
Nominee Management — Up to 3 nominees with name, relationship, DOB, share percentage, and optional PAN. Minor nominees require a guardian. A no-nominee declaration checkbox is mandatory if the customer opts out.
Key Routing Logic
If F&O is selected and Account Aggregator succeeds, income proof is captured here in Stage 9. If AA fails or is cancelled, the system sets stage_10_required = true and Stage 10 (manual document upload) is triggered. There is no minimum income threshold for F&O eligibility.
2. Preconditions
| Condition |
Expected Value |
Failure Action |
lead.state |
SIGNATURE_DONE |
Redirect to the appropriate earlier stage; return HTTP 409 |
| DigiLocker verification |
Completed (Stage 5) |
Father/Spouse name pre-fill will be empty; fields become editable |
| KRA check |
Completed (Stage 2 background) |
Marital status pre-fill from KRA unavailable; field becomes editable |
| Session / JWT |
Valid, non-expired |
HTTP 401 — redirect to login |
3. Section A — Personal Details & Investment Details
3.1 Personal Details Fields
| Field |
UI Control |
Source / Default |
Validation |
Required |
| Education |
Pill selector |
Config-driven from application_config + lookup tables |
Must be a valid lookup value |
Yes |
| Occupation |
Pill selector |
Config-driven from application_config + lookup tables |
Must be a valid lookup value |
Yes |
| Annual Income |
Dropdown |
Config-driven income slabs from lookup tables |
Must be a valid slab code |
Yes |
| Father / Spouse Name |
Text input |
Pre-filled from DigiLocker (Stage 5). Editable if DigiLocker data absent. |
Alphabetic + spaces, max 100 chars |
Yes |
| Mother Name |
Text input |
Blank (user entry) |
Alphabetic + spaces, max 100 chars |
No (optional) |
| Marital Status |
Dropdown / Pill |
Pre-filled from KRA response (Stage 2 background check) |
Must be a valid lookup value |
Yes |
Config-Driven Fields
Dropdown and pill-selector options are sourced from application_config and associated lookup tables. There is no hardcoded list in the backend. The frontend fetches valid options via a config API and the backend validates submitted values against these same tables.
3.2 Investment Details (Section A2)
| Field |
UI Control |
Default Value |
Notes |
| Investment Experience |
Dropdown / Pill |
<1 year |
Default to lowest experience bracket |
| Settlement Preference (T+1) |
Toggle / Radio |
Yes |
Default to opted-in for T+1 settlement |
| DIS Booklet |
Toggle / Radio |
No |
Default to not requested |
| MTF (Margin Trading Facility) |
Toggle / Radio |
No |
Default to not opted-in |
Defaults Behaviour
All investment detail fields are submitted with their defaults if the customer does not modify them. The backend persists the selected value regardless of whether it was changed from the default.
4. Section B — PEP Declaration
4.1 PEP Flow
1
Customer is presented with a Yes / No radio: "Are you a Politically Exposed Person (PEP)?"
2
PEP = No: Normal flow. pep_declared = false. No flag set.
3
PEP = Yes: Journey does NOT block. Sets pep_declared = true and stp_pep_flag = NON_STP. Customer continues normally through remaining stages including eSign.
4
After eSign is completed, the lead is routed to the compliance queue (not the standard verifier queue) for manual review.
PEP Does NOT Block the Journey
Unlike some other NON_STP conditions (e.g., PAN mismatch), PEP = Yes allows the customer to complete the entire journey through eSign. The compliance review happens post-eSign. The backend must set both pep_declared and stp_pep_flag but must not return a blocking error.
4.2 PEP Backend Logic
| Scenario |
pep_declared |
stp_pep_flag |
STP Impact |
Routing |
| PEP = No |
false |
null |
None — normal STP |
Standard verifier queue |
| PEP = Yes |
true |
NON_STP |
Entire lead becomes NON_STP |
Compliance queue (post-eSign) |
5. Section C — F&O Segment & Account Aggregator
5.1 F&O Toggle
The customer is presented with a Yes / No toggle (default: No) to opt into Futures & Options segment. If the customer selects Yes, income proof is required and collected via Account Aggregator.
No Minimum Income Threshold
There is no minimum annual income requirement to opt into F&O. The income proof is collected for regulatory compliance but does not gate eligibility.
5.2 Account Aggregator Flow (Onemoney)
1
Customer selects F&O = Yes. Backend presents two options: Account Aggregator (Onemoney) or Manual Upload.
2
AA Path: Backend initiates Onemoney consent flow. Customer authenticates via their bank's AA interface. On success, income data is fetched and stored. income_proof_source = 'AA'.
3
AA Success: Income proof is captured in Stage 9. stage_10_required = false. Customer proceeds directly past Stage 10.
4
AA Failure / Cancel / Timeout: Backend sets stage_10_required = true. Customer is routed to Stage 10 for manual document upload of income proof.
5
Manual Upload Path: Customer directly opts for manual upload. Backend sets stage_10_required = true and income_proof_source = 'MANUAL'. Routed to Stage 10.
5.3 AA Decision Matrix
| F&O Selected |
AA Attempted |
AA Result |
income_proof_source |
stage_10_required |
| No |
N/A |
N/A |
null |
false |
| Yes |
Yes |
Success |
AA |
false |
| Yes |
Yes |
Failure |
null |
true |
| Yes |
Yes |
Timeout |
null |
true |
| Yes |
Yes |
Cancelled |
null |
true |
| Yes |
No (manual) |
N/A |
MANUAL |
true |
6. Section D — Nominee Management
6.1 Nominee Rules
- Maximum 3 nominees per lead.
- Required fields per nominee: Name, Relationship, Date of Birth, Share Percentage (%).
- Nominee name must not match the lead name (case-insensitive comparison after trimming).
- Total share percentage across all nominees must equal exactly 100%. If it does not, the submission is blocked.
- If a nominee is a minor (age < 18 as of submission date), a guardian is mandatory: guardian name, guardian relationship.
- Nominee PAN is optional. If provided, it undergoes format-only validation (regex:
[A-Z]{5}[0-9]{4}[A-Z]{1}). There is no NSDL lookup for nominee PAN.
- Lead email and phone must not match nominee email or phone (if nominee contact info is collected).
6.2 No-Nominee Declaration
If the customer chooses not to add any nominee, a no-nominee declaration checkbox is required. The backend must verify that either at least one nominee is present OR the no-nominee declaration flag is true. Submitting with zero nominees and no_nominee_declaration = false is a validation error.
6.3 Nominee Data Model
| Field |
Type |
Required |
Validation |
name |
VARCHAR(100) |
Yes |
Alphabetic + spaces; must not match lead name |
relationship |
VARCHAR(50) |
Yes |
Valid lookup value from config |
date_of_birth |
DATE |
Yes |
Must be a past date; determines minor status |
share_percentage |
DECIMAL(5,2) |
Yes |
Range 0.01 – 100.00; sum across all nominees must = 100 |
pan |
VARCHAR(10) |
No |
Format-only: [A-Z]{5}[0-9]{4}[A-Z]{1}. No NSDL lookup. |
guardian_name |
VARCHAR(100) |
If minor |
Required when nominee age < 18 |
guardian_relationship |
VARCHAR(50) |
If minor |
Required when nominee age < 18; valid lookup value |
email |
VARCHAR(150) |
No |
If provided, must not match lead email |
phone |
VARCHAR(15) |
No |
If provided, must not match lead phone |
7. Backend Validations
| Validation Rule |
Condition |
Action |
Error Code |
| PEP = Yes |
pep_declared = true |
Set stp_pep_flag = NON_STP. Journey continues. Routed to compliance queue post-eSign. |
NON_STP—PEP_DECLARED (flag, not error) |
| Nominee share != 100% |
Sum of all share_percentage values does not equal 100 |
Block submission. Return validation error. |
FE_PERSONAL_004 |
| Lead contact = Nominee contact |
Lead email or phone matches any nominee email or phone |
Block submission. Return validation error. |
FE_PERSONAL_005 |
| AA Timeout |
Onemoney consent flow times out or returns error |
Set stage_10_required = true. Fallback to Stage 10 for manual upload. |
FE_PERSONAL_006 |
| Nominee name = Lead name |
Case-insensitive name match after trim |
Block submission. Return validation error. |
FE_PERSONAL_003 |
| Minor nominee without guardian |
Nominee DOB indicates age < 18, guardian fields empty |
Block submission. Return validation error. |
FE_PERSONAL_002 |
| No nominee and no declaration |
Zero nominees and no_nominee_declaration = false |
Block submission. Return validation error. |
FE_PERSONAL_001 |
| Invalid lookup values |
Education, occupation, income slab, relationship not in config |
Block submission. Return validation error. |
FE_PERSONAL_003 |
PEP Is a Flag, Not a Block
The NON_STP—PEP_DECLARED code is recorded as an STP flag on the lead, not returned to the frontend as a blocking error. The customer proceeds without interruption.
8. Existing Stored Procedure Mapping
The old monolith uses the following stored procedures. These must be understood for data migration and parallel-run validation.
Complexity Warning: 31 Tables
The primary GET procedure (USP_GET_PERSONAL_DETAILS_SJET) joins across 31 tables. The new backend must replicate the same data coverage but via clean, normalized service calls and targeted queries.
| Stored Procedure |
Purpose |
Direction |
Key Legacy Tables |
USP_GET_PERSONAL_DETAILS_SJET |
Fetch all personal details for the stage — joins 31 tables to assemble the full form state |
READ |
TBL_CLIENT_PERSONALDETAILS, TBL_CLIENT_WORKDETAILS, TBL_PERSONAL_FIELD_MASTER_SJET |
USP_UPDATE_PERSONAL_DETAILS_SJET |
Save / update personal details fields (education, occupation, income, names, marital status, investment prefs) |
WRITE |
TBL_CLIENT_PERSONALDETAILS, TBL_CLIENT_WORKDETAILS |
USP_INSERT_UPDATE_NOMINEEDETAILS_SJET |
Insert or update nominee records (upsert by nominee ID) |
WRITE |
TBL_CLIENT_NOMINEEDETAILS |
USP_GET_NOMINEE_DETAILS_BYID_SJET |
Fetch nominee details for a given lead / client ID |
READ |
TBL_CLIENT_NOMINEEDETAILS |
USP_INSERTUPDATE_CLIENT_SELECTEDSEGMENTS_SJET |
Save segment selections (Equity, F&O, etc.) |
WRITE |
TBL_CLIENT_SEGMENT, TBL_CLIENT_SELECTEDSEGMENTS |
USP_INSERT_UPDATE_CSAFE_PEP_SJET |
Save PEP declaration and compliance flags |
WRITE |
TBL_CLIENT_PERSONALDETAILS (PEP columns) |
8.1 Legacy Tables Reference
| Legacy Table |
Purpose |
New Backend Equivalent |
TBL_CLIENT_PERSONALDETAILS |
Core personal info, PEP flags, marital status, father/mother name |
personal_details |
TBL_CLIENT_NOMINEEDETAILS |
Nominee records with share %, guardian info |
nominees |
TBL_CLIENT_SEGMENT |
Available segment definitions |
application_config (segment config) |
TBL_CLIENT_SELECTEDSEGMENTS |
Customer's selected segments (Equity, F&O, etc.) |
personal_details (fno_selected flag) |
TBL_CLIENT_WORKDETAILS |
Occupation, employer, income details |
personal_details (occupation, annual_income columns) |
TBL_PERSONAL_FIELD_MASTER_SJET |
Master list of field definitions, dropdown options, field metadata |
application_config + lookup tables |
9. Error / Drop Codes
| Code |
Type |
Trigger |
User Impact |
FE_PERSONAL_001 |
Validation Error |
No nominees added and no-nominee declaration checkbox not checked |
Block — must add nominee or check declaration |
FE_PERSONAL_002 |
Validation Error |
Minor nominee (age < 18) submitted without guardian details |
Block — must provide guardian name and relationship |
FE_PERSONAL_003 |
Validation Error |
Nominee name matches lead name (case-insensitive) |
Block — nominee cannot be the account holder |
FE_PERSONAL_004 |
Validation Error |
Nominee share percentages do not sum to 100% |
Block — must adjust shares to total exactly 100% |
FE_PERSONAL_005 |
Validation Error |
Lead email or phone matches nominee email or phone |
Block — nominee contact must differ from lead |
FE_PERSONAL_006 |
Soft Error / Fallback |
Account Aggregator (Onemoney) timeout, failure, or cancellation |
Non-blocking — triggers Stage 10 for manual upload |
NON_STP—PEP_DECLARED |
STP Flag |
Customer declares PEP = Yes |
Non-blocking — journey continues; compliance review post-eSign |
10. Exit State
On successful submission of Stage 9, the following state is written:
| Field |
Value |
Notes |
lead.state |
DETAILS_DONE |
State transition from SIGNATURE_DONE |
occupation |
Selected occupation code |
From config-driven lookup |
annual_income |
Selected income slab code |
From config-driven lookup |
father_name |
Father / Spouse name |
Pre-filled from DigiLocker or user-entered |
marital_status |
Marital status code |
Pre-filled from KRA or user-entered |
pep_declared |
true / false |
If true, stp_pep_flag = NON_STP also set |
fno_selected |
true / false |
Whether F&O segment was opted into |
income_proof_source |
AA / MANUAL / null |
AA if Onemoney succeeded; MANUAL if direct upload chosen; null if F&O not selected |
nominee_count |
0 – 3 |
0 only if no-nominee declaration is checked |
stage_10_required |
true / false |
true if F&O selected and AA failed/cancelled/manual; false otherwise |
Stage 10 Routing
If stage_10_required = true, the next stage controller must route the customer to Stage 10 (manual document upload). If false, Stage 10 is skipped and the customer proceeds to the next applicable stage.
11. Vendor & Integration Calls
| Vendor / System |
Purpose |
Trigger |
Sync / Async |
Failure Handling |
| Onemoney (Account Aggregator) |
F&O income proof collection via AA consent flow |
Customer selects F&O = Yes and chooses AA path |
Sync (consent) + Async (data fetch) |
Timeout / failure / cancel → stage_10_required = true; fallback to manual upload |
| CleverTap |
Event tracking — stage completion, PEP flag, F&O selection, nominee count |
On stage submission |
Async (fire-and-forget) |
Log failure; do not block journey |
| Zoho |
CRM sync — update lead with personal details, occupation, segment info |
On stage submission |
Async |
Log failure; retry via downstream_events queue |
| CDP (Customer Data Platform) |
Profile enrichment with personal details and declarations |
On stage submission |
Async |
Log failure; retry via downstream_events queue |
| Datalake |
Analytics event push — personal details stage metrics, AA success/fail rates |
On stage submission |
Async |
Log failure; do not block journey |
Onemoney Integration Detail
The Onemoney AA flow involves: (1) consent creation via API, (2) redirect to bank's AA interface, (3) callback on consent approval/rejection, (4) data fetch on successful consent. The entire flow is tracked in the one_money_consents table. File storage for any downloaded statements uses the drive service (not local filesystem).
12. Database Tables (New Backend)
12.1 personal_details
NEW TABLE
| Column |
Type |
Nullable |
Notes |
id |
BIGINT (PK) |
No |
Auto-increment |
lead_id |
BIGINT (FK) |
No |
References leads.id |
education |
VARCHAR(50) |
No |
Lookup code from config |
occupation |
VARCHAR(50) |
No |
Lookup code from config |
annual_income |
VARCHAR(20) |
No |
Income slab code from config |
father_name |
VARCHAR(100) |
No |
Pre-filled from DigiLocker if available |
mother_name |
VARCHAR(100) |
Yes |
Optional |
marital_status |
VARCHAR(20) |
No |
Pre-filled from KRA if available |
investment_experience |
VARCHAR(20) |
No |
Default: <1_YEAR |
settlement_preference |
BOOLEAN |
No |
Default: true (T+1 opted) |
dis_booklet |
BOOLEAN |
No |
Default: false |
mtf_opted |
BOOLEAN |
No |
Default: false |
pep_declared |
BOOLEAN |
No |
Default: false |
stp_pep_flag |
VARCHAR(20) |
Yes |
NON_STP if PEP = Yes; null otherwise |
fno_selected |
BOOLEAN |
No |
Default: false |
income_proof_source |
VARCHAR(20) |
Yes |
AA, MANUAL, or null |
no_nominee_declaration |
BOOLEAN |
No |
Default: false |
stage_10_required |
BOOLEAN |
No |
Default: false |
created_at |
TIMESTAMP |
No |
Auto-set on insert |
updated_at |
TIMESTAMP |
No |
Auto-set on update |
12.2 nominees
NEW TABLE
| Column |
Type |
Nullable |
Notes |
id |
BIGINT (PK) |
No |
Auto-increment |
lead_id |
BIGINT (FK) |
No |
References leads.id |
name |
VARCHAR(100) |
No |
Must not match lead name |
relationship |
VARCHAR(50) |
No |
Lookup value from config |
date_of_birth |
DATE |
No |
Used for minor determination |
share_percentage |
DECIMAL(5,2) |
No |
Must sum to 100 across all nominees for lead |
pan |
VARCHAR(10) |
Yes |
Format-only validation; no NSDL lookup |
is_minor |
BOOLEAN |
No |
Computed from DOB at submission time |
guardian_name |
VARCHAR(100) |
Yes |
Required if is_minor = true |
guardian_relationship |
VARCHAR(50) |
Yes |
Required if is_minor = true |
email |
VARCHAR(150) |
Yes |
Must not match lead email |
phone |
VARCHAR(15) |
Yes |
Must not match lead phone |
created_at |
TIMESTAMP |
No |
Auto-set on insert |
updated_at |
TIMESTAMP |
No |
Auto-set on update |
12.3 one_money_consents
NEW TABLE
| Column |
Type |
Nullable |
Notes |
id |
BIGINT (PK) |
No |
Auto-increment |
lead_id |
BIGINT (FK) |
No |
References leads.id |
consent_id |
VARCHAR(100) |
No |
Onemoney consent reference ID |
consent_status |
VARCHAR(30) |
No |
INITIATED, APPROVED, REJECTED, TIMEOUT, CANCELLED |
data_fetch_status |
VARCHAR(30) |
Yes |
PENDING, SUCCESS, FAILED |
file_reference |
VARCHAR(255) |
Yes |
Drive reference for downloaded AA data / statements |
request_payload |
JSON |
Yes |
Onemoney API request (for debugging) |
response_payload |
JSON |
Yes |
Onemoney API response (for debugging) |
created_at |
TIMESTAMP |
No |
Auto-set on insert |
updated_at |
TIMESTAMP |
No |
Auto-set on update |
12.4 journey_stage_events
EXISTING TABLE
| Column |
Usage in Stage 9 |
lead_id |
FK to lead |
stage |
PERSONAL_DETAILS |
event_type |
STAGE_STARTED, AA_INITIATED, AA_SUCCESS, AA_FAILED, STAGE_COMPLETED |
metadata |
JSON — includes pep_declared, fno_selected, nominee_count, stage_10_required |
created_at |
Event timestamp |
12.5 downstream_events
EXISTING TABLE
| Column |
Usage in Stage 9 |
lead_id |
FK to lead |
event_type |
CLEVERTAP_PERSONAL_DETAILS, ZOHO_PERSONAL_DETAILS, CDP_PERSONAL_DETAILS, DATALAKE_PERSONAL_DETAILS |
status |
PENDING, SENT, FAILED |
payload |
JSON — event-specific data for each vendor |
retry_count |
Number of retry attempts |
created_at |
Event timestamp |
13. Implementation Notes
Config-Driven Values
All dropdown and pill-selector option values (education, occupation, income slabs, relationships, etc.) are sourced from application_config and associated lookup tables. There are no hardcoded enums in the backend code. The frontend calls a config API to fetch options, and the backend validates submitted values against the same config source.
File Storage
Any files related to Account Aggregator (downloaded bank statements, income proofs) are stored via the drive service. The file reference is saved in one_money_consents.file_reference. There is no local filesystem storage.
No Redis
Stage 9 does not use Redis for caching or session state. All data is persisted directly to the database. Config values may be cached at the application layer but there is no Redis dependency for this stage.
Nominee PAN — Format Only
Nominee PAN, if provided, is validated against the regex pattern [A-Z]{5}[0-9]{4}[A-Z]{1} only. There is no NSDL verification call for nominee PANs. This is intentionally different from the lead's own PAN validation in Stage 2.