CTR/STR report and Risk Category auto mark on bases of person occupation and anual salary enter
This commit is contained in:
@@ -70,6 +70,7 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
@Input() entityName: string = '';
|
||||
/** Read-only mode — disables form editing until user clicks edit icon */
|
||||
@Input() readOnly = false;
|
||||
@Input() calculatedRisk: { category: number; reason: string } | null = null;
|
||||
|
||||
today = new Date();
|
||||
kycId: string = '';
|
||||
@@ -170,6 +171,17 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
{ name: 'Birth Certificate', code: 'BIRTH_CERTIFICATE' },
|
||||
{ name: 'School ID Card', code: 'SCHOOL_ID_CARD' }
|
||||
];
|
||||
/** Generic RBI-prescribed KYC documents for legal entities (Master Direction on KYC,
|
||||
* Annexure I) — shown for non-individual clients before a specific constitution type is
|
||||
* picked. Individual OVDs (Aadhaar/Passport/DL/Voter ID/NREGA/NPR) don't apply to entities. */
|
||||
private nonIndividualDefaultDocTypes = [
|
||||
{ name: 'Certificate of Incorporation / Registration Certificate', code: 'CERT_INCORPORATION' },
|
||||
{ name: 'PAN Card of Entity', code: 'ENTITY_PAN' },
|
||||
{ name: 'Memorandum & Articles of Association / Partnership Deed / Trust Deed', code: 'CONSTITUTIVE_DOC' },
|
||||
{ name: 'Board Resolution / Authorization Letter', code: 'BOARD_RESOLUTION' },
|
||||
{ name: 'KYC of Authorized Signatory / Power of Attorney Holder', code: 'AUTH_SIGNATORY_KYC' },
|
||||
{ name: 'GST Registration Certificate', code: 'GST_CERTIFICATE' }
|
||||
];
|
||||
/** Constitution-based KYC document types for non-individual clients */
|
||||
private constitutionDocTypes: Record<string, { name: string; mandatory: boolean }[]> = {
|
||||
HUF: [
|
||||
@@ -250,6 +262,9 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
{ value: 3, label: 'High Risk', years: 2, color: 'red' }
|
||||
];
|
||||
|
||||
riskCalculationReason = '';
|
||||
showRiskRulesTable = false;
|
||||
|
||||
/** PAN verification */
|
||||
panVerifyStatus: 'NONE' | 'VERIFIED' | 'FAILED' = 'NONE';
|
||||
panVerifying = false;
|
||||
@@ -441,6 +456,7 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
kycDocIssueDate: [''],
|
||||
kycDocExpiryDate: [''],
|
||||
riskCategory: [1],
|
||||
allowRiskOverride: [false],
|
||||
remarks: [''],
|
||||
amlCheckStatus: [
|
||||
'CLEAR',
|
||||
@@ -488,6 +504,14 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
return docs.filter((d) => !ClientKycStepComponent.MINOR_ONLY_DOC_CODES.has((d.code || '').toUpperCase()));
|
||||
}
|
||||
|
||||
/** Individual-only OVDs vs. entity-only RBI docs — never both, and minor filtering only
|
||||
* ever applies to individuals. */
|
||||
private getDefaultDocTypes(): { name: string; code: string }[] {
|
||||
return this.isNonIndividual
|
||||
? this.nonIndividualDefaultDocTypes
|
||||
: this.filterDocTypesForMinor(this.defaultDocumentTypes);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.seedDefaultDocTypes();
|
||||
this.loadExistingKycIfNeeded();
|
||||
@@ -495,20 +519,36 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
if (this.isNonIndividual && this.constitutionMeta) {
|
||||
this.updateDocTypesForConstitution();
|
||||
}
|
||||
|
||||
this.kycForm.get('allowRiskOverride')?.valueChanges.subscribe((allowed: boolean) => {
|
||||
const riskControl = this.kycForm.get('riskCategory');
|
||||
if (allowed) {
|
||||
if (!this.readOnly) {
|
||||
riskControl?.enable();
|
||||
}
|
||||
} else {
|
||||
riskControl?.disable();
|
||||
if (this.calculatedRisk) {
|
||||
riskControl?.setValue(this.calculatedRisk.category);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.kycForm.get('allowRiskOverride')?.value) {
|
||||
this.kycForm.get('riskCategory')?.disable();
|
||||
}
|
||||
}
|
||||
|
||||
/** Seed the document-type picker from defaults, filtered by the current isMinor input.
|
||||
* Only seeds when the list is empty — the template API (loadKycTemplate) takes over once
|
||||
* a clientId is available. */
|
||||
/** Seed the document-type picker from defaults (entity RBI docs vs. individual OVDs,
|
||||
* filtered by the current isMinor input for individuals). Only seeds when the list is
|
||||
* empty — the template API (loadKycTemplate) takes over once a clientId is available. */
|
||||
private seedDefaultDocTypes(): void {
|
||||
if (this.kycDocumentTypes.length) return;
|
||||
this.kycDocumentTypes = this.filterDocTypesForMinor(
|
||||
this.defaultDocumentTypes.map((d) => ({
|
||||
name: d.name,
|
||||
code: d.code,
|
||||
mandatory: false
|
||||
}))
|
||||
);
|
||||
this.kycDocumentTypes = this.getDefaultDocTypes().map((d) => ({
|
||||
name: d.name,
|
||||
code: d.code,
|
||||
mandatory: false
|
||||
}));
|
||||
this.rebuildKycDocPicker();
|
||||
}
|
||||
|
||||
@@ -526,6 +566,7 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.kycForm.reset({
|
||||
hasPan: true,
|
||||
riskCategory: 1,
|
||||
allowRiskOverride: false,
|
||||
amlCheckStatus: 'CLEAR',
|
||||
bannedEntityMatch: 'NO',
|
||||
willfulDefaulter: 'NO',
|
||||
@@ -546,6 +587,8 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.kycDocMergedFile = null;
|
||||
this.kycDocMergedPreview = null;
|
||||
this.existingKycIdentifierId = null;
|
||||
this.riskCalculationReason = '';
|
||||
this.showRiskRulesTable = false;
|
||||
this.existingKycDocuments = [];
|
||||
this.photoSigTouched = false;
|
||||
this.panVerifyStatus = 'NONE';
|
||||
@@ -598,12 +641,41 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
this.kycForm.disable({ emitEvent: false });
|
||||
} else {
|
||||
this.kycForm.enable({ emitEvent: false });
|
||||
if (!this.kycForm.get('allowRiskOverride')?.value) {
|
||||
this.kycForm.get('riskCategory')?.disable({ emitEvent: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
if (changes['calculatedRisk']) {
|
||||
const newRisk = changes['calculatedRisk'].currentValue;
|
||||
if (newRisk) {
|
||||
this.riskCalculationReason = newRisk.reason;
|
||||
const allowOverride = this.kycForm.get('allowRiskOverride')?.value;
|
||||
const riskControl = this.kycForm.get('riskCategory');
|
||||
if (!allowOverride && riskControl && riskControl.value !== newRisk.category) {
|
||||
riskControl.setValue(newRisk.category);
|
||||
riskControl.markAsDirty();
|
||||
}
|
||||
} else {
|
||||
this.riskCalculationReason = '';
|
||||
}
|
||||
}
|
||||
if (changes['constitutionMeta'] && this.isNonIndividual) {
|
||||
this.updateDocTypesForConstitution();
|
||||
}
|
||||
if (changes['isMinor']) {
|
||||
// Legal form toggled on an already-initialized instance (route-reuse keeps this
|
||||
// component alive across create sessions) — the individual OVD list and the entity RBI
|
||||
// doc list are mutually exclusive, so re-seed from scratch rather than filtering in place.
|
||||
if (changes['isNonIndividual'] && !changes['isNonIndividual'].firstChange && !this.kycTemplateLoaded) {
|
||||
this.kycDocumentTypes = [];
|
||||
this.selectedKycDoc = null;
|
||||
this.kycForm.get('kycDocumentName')?.setValue('');
|
||||
this.seedDefaultDocTypes();
|
||||
if (this.isNonIndividual && this.constitutionMeta) {
|
||||
this.updateDocTypesForConstitution();
|
||||
}
|
||||
}
|
||||
if (changes['isMinor'] && !this.isNonIndividual) {
|
||||
if (this.isMinor) {
|
||||
this.kycForm.get('hasPan')?.setValue(false);
|
||||
this.kycForm.get('panNumber')?.setValue('');
|
||||
@@ -797,6 +869,7 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
kycDocExpiryDate: parseDate(data.kycDocExpiryDate),
|
||||
// Risk & Remarks
|
||||
riskCategory: data.riskCategory || 1,
|
||||
allowRiskOverride: this.calculatedRisk ? this.calculatedRisk.category !== (data.riskCategory || 1) : false,
|
||||
remarks: data.remarks || '',
|
||||
hasPan: !!data.panNumber,
|
||||
// AML & Compliance
|
||||
@@ -1015,13 +1088,11 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
error: () => {
|
||||
// Fallback to defaults if template API unavailable
|
||||
this.kycTemplateLoaded = true;
|
||||
this.kycDocumentTypes = this.filterDocTypesForMinor(
|
||||
this.defaultDocumentTypes.map((d) => ({
|
||||
name: d.name,
|
||||
code: d.code,
|
||||
mandatory: false
|
||||
}))
|
||||
);
|
||||
this.kycDocumentTypes = this.getDefaultDocTypes().map((d) => ({
|
||||
name: d.name,
|
||||
code: d.code,
|
||||
mandatory: false
|
||||
}));
|
||||
this.rebuildKycDocPicker();
|
||||
}
|
||||
});
|
||||
@@ -1664,7 +1735,7 @@ export class ClientKycStepComponent implements OnInit, OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
get kycData(): any {
|
||||
const formVal = this.readOnly ? this.kycForm.getRawValue() : this.kycForm.value;
|
||||
const formVal = this.kycForm.getRawValue();
|
||||
const aadhaarRaw = formVal.aadhaarNumber || '';
|
||||
const aadhaarMasked = aadhaarRaw.length === 12 ? 'XXXXXXXX' + aadhaarRaw.slice(-4) : null;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
|
||||
Reference in New Issue
Block a user