- Form 60 / 61
+ Form 97 / 98
@if (!kycForm.get('hasPan')?.value) {
Required — No PAN
}
@@ -1278,14 +1281,14 @@
@if (!kycForm.get('hasPan')?.value) {
warning
- Client does not have PAN. Form 60/61 is mandatory.
+ Client does not have PAN. Form 97/98 is mandatory.
Form Type
- Form 60
- Form 61
+ Form 97
+ Form 98
@@ -1296,26 +1299,26 @@
} @else {
-
Client has PAN — Form 60/61 not required.
+
Client has PAN — Form 97/98 not required.
}
-
+
- Form 15G / 15H
+ Form 121
- Form 15G/15H Applicable
+ Form 121 Applicable
@if (kycForm.get('form15Applicable')?.value) {
Form Type
- 15G (Below 60 years)
- 15H (Senior Citizen 60+)
+ Form 121 (Below 60 years)
+ Form 121 (Senior Citizen 60+)
diff --git a/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.ts b/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.ts
index ed8047b55..c3cf4edf8 100644
--- a/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.ts
+++ b/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.ts
@@ -61,6 +61,8 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
/** Set by parent after client is created */
@Input() clientId: string = '';
@Input() isNonIndividual = false;
+ /** Minor clients don't hold a PAN card — hides the PAN section on the individual KYC form */
+ @Input() isMinor = false;
/** Constitution metadata (panLabel, showCin, etc.) passed from general step */
@Input() constitutionMeta: any = null;
/** Entity full name (non-individual) — used for enterprise PAN verification */
@@ -163,7 +165,9 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
{ name: 'Driving Licence', code: 'DRIVING_LICENSE' },
{ name: 'Voter ID', code: 'VOTER_ID' },
{ name: 'NREGA Job Card', code: 'NREGA_JOB_CARD' },
- { name: 'National Population Register Letter', code: 'NPR_LETTER' }
+ { name: 'National Population Register Letter', code: 'NPR_LETTER' },
+ { name: 'Birth Certificate', code: 'BIRTH_CERTIFICATE' },
+ { name: 'School ID Card', code: 'SCHOOL_ID_CARD' }
];
/** Constitution-based KYC document types for non-individual clients */
private constitutionDocTypes: Record = {
@@ -458,15 +462,44 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
form15FY: ['']
});
+ /** RBI OVDs a minor cannot hold: Voter ID and Driving Licence require adult age,
+ * PAN and NREGA job cards are issued to adults. Aadhaar, Passport and NPR letters
+ * are unaffected by age and stay available. */
+ private static readonly MINOR_INELIGIBLE_DOC_KEYWORDS = [
+ 'pan',
+ 'driving',
+ 'voter',
+ 'nrega'
+ ];
+
+ /** Birth Certificate / School ID Card are minor-specific OVDs — not relevant once the
+ * client is an adult, so they're hidden the other direction. */
+ private static readonly MINOR_ONLY_DOC_CODES = new Set([
+ 'BIRTH_CERTIFICATE',
+ 'SCHOOL_ID_CARD'
+ ]);
+
+ private filterDocTypesForMinor(docs: T[]): T[] {
+ if (this.isMinor) {
+ return docs.filter((d) => {
+ const text = `${d.name || ''} ${d.code || ''}`.toLowerCase();
+ return !ClientKycStepComponent.MINOR_INELIGIBLE_DOC_KEYWORDS.some((k) => text.includes(k));
+ });
+ }
+ return docs.filter((d) => !ClientKycStepComponent.MINOR_ONLY_DOC_CODES.has((d.code || '').toUpperCase()));
+ }
+
ngOnInit(): void {
// Seed defaults immediately so the picker has options before clientId is set
// (template API requires clientId; user can still pick a type pre-save).
if (!this.kycDocumentTypes.length) {
- this.kycDocumentTypes = this.defaultDocumentTypes.map((d) => ({
- name: d.name,
- code: d.code,
- mandatory: false
- }));
+ this.kycDocumentTypes = this.filterDocTypesForMinor(
+ this.defaultDocumentTypes.map((d) => ({
+ name: d.name,
+ code: d.code,
+ mandatory: false
+ }))
+ );
this.rebuildKycDocPicker();
}
this.loadExistingKycIfNeeded();
@@ -496,6 +529,21 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
if (changes['constitutionMeta'] && this.isNonIndividual) {
this.updateDocTypesForConstitution();
}
+ if (changes['isMinor']) {
+ if (this.isMinor) {
+ this.kycForm.get('hasPan')?.setValue(false);
+ this.kycForm.get('panNumber')?.setValue('');
+ }
+ const filtered = this.filterDocTypesForMinor(this.kycDocumentTypes);
+ if (filtered.length !== this.kycDocumentTypes.length) {
+ this.kycDocumentTypes = filtered;
+ const currentName = this.kycForm.get('kycDocumentName')?.value;
+ if (currentName && !filtered.some((d) => d.name === currentName)) {
+ this.kycForm.get('kycDocumentName')?.setValue('');
+ }
+ this.rebuildKycDocPicker();
+ }
+ }
}
/** Update KYC document types based on selected constitution type */
@@ -879,11 +927,13 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
this.kycTemplate = template;
this.kycTemplateLoaded = true;
if (template?.requiredDocuments?.length > 0) {
- this.kycDocumentTypes = template.requiredDocuments.map((doc: any) => ({
- name: doc.name,
- code: doc.code || doc.name,
- mandatory: doc.mandatory ?? false
- }));
+ this.kycDocumentTypes = this.filterDocTypesForMinor(
+ template.requiredDocuments.map((doc: any) => ({
+ name: doc.name,
+ code: doc.code || doc.name,
+ mandatory: doc.mandatory ?? false
+ }))
+ );
// Update kycDocumentName validator based on mandatory docs
const hasMandatory = this.kycDocumentTypes.some((d) => d.mandatory);
if (hasMandatory) {
@@ -896,11 +946,13 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
error: () => {
// Fallback to defaults if template API unavailable
this.kycTemplateLoaded = true;
- this.kycDocumentTypes = this.defaultDocumentTypes.map((d) => ({
- name: d.name,
- code: d.code,
- mandatory: false
- }));
+ this.kycDocumentTypes = this.filterDocTypesForMinor(
+ this.defaultDocumentTypes.map((d) => ({
+ name: d.name,
+ code: d.code,
+ mandatory: false
+ }))
+ );
this.rebuildKycDocPicker();
}
});
diff --git a/src/app/clients/clients-routing.module.ts b/src/app/clients/clients-routing.module.ts
index 9109e1003..60dc5b155 100644
--- a/src/app/clients/clients-routing.module.ts
+++ b/src/app/clients/clients-routing.module.ts
@@ -191,7 +191,7 @@ const routes: Routes = [
{
path: 'form60',
component: Form60TabComponent,
- data: { title: 'Form 60', breadcrumb: 'Form 60', routeParamBreadcrumb: false }
+ data: { title: 'Form 97', breadcrumb: 'Form 97', routeParamBreadcrumb: false }
},
{
path: 'documents',
diff --git a/src/app/clients/clients-view/form60-tab/form60-tab.component.html b/src/app/clients/clients-view/form60-tab/form60-tab.component.html
index 97a73d9a8..3ec1df5f8 100644
--- a/src/app/clients/clients-view/form60-tab/form60-tab.component.html
+++ b/src/app/clients/clients-view/form60-tab/form60-tab.component.html
@@ -19,14 +19,14 @@
verified
-
Form 60 Not Required
+
Form 97 Not Required
PAN {{ panNumber }} is attached to this client.
@if (panVerified) {
check_circleVerified
}
-
As per Income Tax Rule 114B, Form 60 is only required when PAN is not available.
+
As per Income Tax Rule 114B, Form 97 is only required when PAN is not available.
}
@@ -36,7 +36,7 @@
warning_amber
- PAN not provided — Form 60 declaration is mandatory as per Income Tax Rule 114B.
+ PAN not provided — Form 97 declaration is mandatory as per Income Tax Rule 114B.
@@ -45,7 +45,7 @@
description
-
Form 60 Declaration
+
Form 97 Declaration
Submitted
diff --git a/src/app/clients/shared/kyc-proof-types.ts b/src/app/clients/shared/kyc-proof-types.ts
index b2351fcbc..c0d678aec 100644
--- a/src/app/clients/shared/kyc-proof-types.ts
+++ b/src/app/clients/shared/kyc-proof-types.ts
@@ -70,6 +70,19 @@ export const PROOF_META: Record> = {
documentKeyPlaceholder: 'NPR reference number',
info: 'NPR letter — upload full document.'
},
+ BIRTH_CERTIFICATE: {
+ sides: 1,
+ documentKeyLabel: 'Birth certificate registration number',
+ documentKeyPlaceholder: 'Registration / certificate number',
+ category: 'Government-issued ID',
+ info: 'Birth certificate issued by the Municipal Corporation / Registrar of Births & Deaths — accepted proof of identity for minor clients as per RBI KYC norms.'
+ },
+ SCHOOL_ID_CARD: {
+ sides: 1,
+ documentKeyLabel: 'School ID / admission number',
+ documentKeyPlaceholder: 'Student ID number',
+ info: 'School identity card bearing photograph — accepted proof of identity for minor clients as per RBI KYC norms.'
+ },
UTILITY_BILL: {
sides: 1,
category: 'Utility bills',
diff --git a/src/app/core/shell/shell.component.html b/src/app/core/shell/shell.component.html
index 27ba017cf..a6498fdfb 100644
--- a/src/app/core/shell/shell.component.html
+++ b/src/app/core/shell/shell.component.html
@@ -1468,13 +1468,13 @@
Balance Certificate