From 73871a0993024aa54da5c611a455a6da8bbbb4a0 Mon Sep 17 00:00:00 2001 From: anshul Date: Thu, 1 Oct 2026 12:04:01 +0530 Subject: [PATCH] Enforce same-user maker-checker restriction --- .../client-kyc-step.component.html | 5 ++ .../client-kyc-step.component.ts | 48 ++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.html b/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.html index f139711f3..65d2d97da 100644 --- a/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.html +++ b/src/app/clients/client-stepper/client-kyc-step/client-kyc-step.component.html @@ -1321,6 +1321,11 @@ kycForm.get('kycDocumentNumber')?.hasError('pattern') && kycForm.get('kycDocumentNumber')?.touched ) { Only letters, numbers, hyphens and slashes allowed + } @else if ( + kycForm.get('kycDocumentNumber')?.hasError('aadhaarLast4Mismatch') && + kycForm.get('kycDocumentNumber')?.touched + ) { + Last 4 digits do not match the Aadhaar number entered above } 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 00d2afccd..cfca4fb8c 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 @@ -8,7 +8,14 @@ import { Component, Input, OnInit, OnChanges, OnDestroy, SimpleChanges, inject } from '@angular/core'; import { forkJoin, catchError, of } from 'rxjs'; -import { UntypedFormBuilder, UntypedFormGroup, Validators, FormsModule } from '@angular/forms'; +import { + UntypedFormBuilder, + UntypedFormGroup, + Validators, + FormsModule, + AbstractControl, + ValidationErrors +} from '@angular/forms'; import { MatDialog, MAT_DIALOG_DATA, @@ -567,6 +574,28 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy { /** Existing signature document ID (for re-upload/delete) */ existingSignatureDocId: string = ''; + /** + * Cross-field check for the OVD "Document Number" field (kycDocumentNumber): when Aadhaar Card + * is the selected KYC document, its value must identify the same Aadhaar as the aadhaarNumber + * field captured earlier in this step - the last 4 digits are what's compared, since + * aadhaarNumber may hold either the raw 12-digit number or a masked value (masking only ever + * obscures the first 8 digits - see aadhaarMasked in the kycData getter below - so the last 4 + * characters are always the real digits either way). Not applicable to any other document type, + * where kycDocumentNumber is unrelated to Aadhaar entirely. + */ + private aadhaarLast4MatchValidator = (control: AbstractControl): ValidationErrors | null => { + if (this.selectedKycDoc?.code !== 'AADHAAR') { + return null; + } + const docNumber = (control.value || '').toString().trim(); + const aadhaarValue = (control.parent?.get('aadhaarNumber')?.value || '').toString().trim(); + if (docNumber.length < 4 || aadhaarValue.length < 4) { + // Required/pattern validators already flag an empty or too-short value on their own. + return null; + } + return docNumber.slice(-4) === aadhaarValue.slice(-4) ? null : { aadhaarLast4Mismatch: true }; + }; + /** KYC Form */ kycForm: UntypedFormGroup = this.formBuilder.group({ hasPan: [true], @@ -616,7 +645,8 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy { [ Validators.required, Validators.pattern(/^[A-Za-z0-9\-\/\s]+$/), - Validators.maxLength(30) + Validators.maxLength(30), + this.aadhaarLast4MatchValidator ] ], kycDocIssueDate: [''], @@ -739,6 +769,14 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy { this.kycForm.get('ecgcSalFlag')?.disable(); this.kycForm.get('dormantFlag')?.disable(); } + + // aadhaarLast4MatchValidator (on kycDocumentNumber) reads this control's value directly rather + // than through its own valueChanges, so a re-check has to be triggered explicitly whenever the + // Aadhaar field itself changes - otherwise fixing aadhaarNumber after kycDocumentNumber was + // already entered would leave a stale mismatch error in place. + this.kycForm.get('aadhaarNumber')?.valueChanges.subscribe(() => { + this.kycForm.get('kycDocumentNumber')?.updateValueAndValidity({ onlySelf: true }); + }); } /** Seed the document-type picker from defaults (entity RBI docs vs. individual OVDs, @@ -1009,6 +1047,9 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy { // Reset uploads + merged preview when document type changes this.kycDocFiles = { front: null, back: null }; this.kycDocMergedPreview = null; + // aadhaarLast4MatchValidator only applies while Aadhaar Card is selected - re-check so switching + // to/away from it immediately picks up (or clears) the mismatch error. + this.kycForm.get('kycDocumentNumber')?.updateValueAndValidity({ onlySelf: true }); } isKycDocSelected(proof: ProofType): boolean { @@ -1189,6 +1230,9 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy { // Sync chip-picker selection with the prefilled document name if (data.kycDocumentName) { this.selectedKycDoc = this.findKycDocProofByName(data.kycDocumentName); + // patchValue above ran kycDocumentNumber's validators before selectedKycDoc was known, + // so aadhaarLast4MatchValidator needs a fresh check now that it is. + this.kycForm.get('kycDocumentNumber')?.updateValueAndValidity({ onlySelf: true }); } // Set verification statuses from existing data if (data.panVerified) {