Files
cbsnexora/src/app/clients/client-stepper/client-entity-kyc-step/client-entity-kyc-step.component.ts
T
Nitesh YadavandClaude Sonnet 4.6 d367e76104 merging code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 14:26:25 +05:30

392 lines
10 KiB
TypeScript

/**
* Copyright since 2025 Mifos Initiative
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
import { Component, Input, OnInit, OnChanges, SimpleChanges, inject } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatIcon } from '@angular/material/icon';
import { MatTooltip } from '@angular/material/tooltip';
import { MatProgressSpinner } from '@angular/material/progress-spinner';
import { MatSlideToggle } from '@angular/material/slide-toggle';
import { ClientsService } from '../../clients.service';
import { SettingsService } from 'app/settings/settings.service';
import { Dates } from 'app/core/utils/dates';
export interface CategoryMeta {
id: string;
label: string;
tag: string;
tagColor: string;
tagBg: string;
desc: string;
icon: string;
}
@Component({
selector: 'mifosx-client-entity-kyc-step',
templateUrl: './client-entity-kyc-step.component.html',
styleUrls: ['./client-entity-kyc-step.component.scss'],
imports: [
...STANDALONE_SHARED_IMPORTS,
FaIconComponent,
MatCheckbox,
MatIcon,
MatTooltip,
MatProgressSpinner,
MatSlideToggle
]
})
export class ClientEntityKycStepComponent implements OnInit, OnChanges {
private fb = inject(UntypedFormBuilder);
private clientService = inject(ClientsService);
private settingsService = inject(SettingsService);
private dateUtils = inject(Dates);
@Input() clientId: string = '';
@Input() constitutionType: string = '';
/** Read-only mode — disables form editing until user clicks edit icon */
@Input() readOnly = false;
today = new Date();
/** Category metadata */
categories: CategoryMeta[] = [
{
id: 'msme',
label: 'MSME',
tag: 'Udyam / MSME',
tagColor: '#0A5C6B',
tagBg: '#E6F4F6',
desc: 'Micro, Small & Medium Enterprise — Ministry of MSME / Udyam Registration',
icon: 'cogs'
},
{
id: 'startup',
label: 'Startup India Registered',
tag: 'DPIIT',
tagColor: '#1A5FAB',
tagBg: '#EAF2FB',
desc: 'DPIIT recognition under Startup India initiative',
icon: 'rocket'
},
{
id: 'mudra',
label: 'Mudra Borrower',
tag: 'PMMY',
tagColor: '#8A5A00',
tagBg: '#FEF3DC',
desc: 'Pradhan Mantri Mudra Yojana — SIDBI / Mudra scheme',
icon: 'hand-holding-usd'
},
{
id: 'eou',
label: 'Export Oriented Unit',
tag: 'EOU',
tagColor: '#1B7A4A',
tagBg: '#E8F5EE',
desc: 'Customs-registered EOU under DGFT / Ministry of Commerce',
icon: 'ship'
},
{
id: 'importexport',
label: 'Import Export Business',
tag: 'DGFT / IEC',
tagColor: '#5B3A8A',
tagBg: '#F0EBF8',
desc: 'Entity with valid DGFT Importer Exporter Code',
icon: 'exchange-alt'
},
{
id: 'psl',
label: 'Priority Sector Borrower',
tag: 'RBI PSL',
tagColor: '#7B1F1F',
tagBg: '#FCEAEA',
desc: 'Eligible under RBI Priority Sector Lending guidelines',
icon: 'bullseye'
},
{
id: 'nps',
label: 'Non-Priority Sector',
tag: 'General',
tagColor: '#444441',
tagBg: '#F1EFE8',
desc: 'Standard corporate — no special priority sector classification',
icon: 'building'
}
];
/** Toggle & expand state per category */
enabled: Record<string, boolean> = {};
expanded: Record<string, boolean> = {};
/** Forms per category */
msmeForm!: UntypedFormGroup;
startupForm!: UntypedFormGroup;
mudraForm!: UntypedFormGroup;
eouForm!: UntypedFormGroup;
importexportForm!: UntypedFormGroup;
pslForm!: UntypedFormGroup;
npsForm!: UntypedFormGroup;
/** Saving state */
saving: Record<string, boolean> = {};
saved: Record<string, boolean> = {};
ngOnInit() {
this.initForms();
if (this.clientId) {
this.loadExisting();
}
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['readOnly']) {
const forms = [
this.msmeForm,
this.startupForm,
this.mudraForm,
this.eouForm,
this.importexportForm,
this.pslForm,
this.npsForm
];
for (const form of forms) {
if (!form) continue;
if (this.readOnly) {
form.disable({ emitEvent: false });
} else {
form.enable({ emitEvent: false });
}
}
}
}
private initForms() {
this.msmeForm = this.fb.group({
udyamRegistrationNumber: [''],
registrationDate: [''],
registrationStatus: [''],
msmeClassification: [''],
enterpriseType: [''],
nicActivityCode: [''],
annualTurnover: [''],
investmentPlantMachinery: [''],
financialYearAssessment: [''],
socialCategoryOwner: [''],
genderPrimaryOwner: [''],
noOfEmployees: [''],
womenLedEnterprise: [false],
divyangPwdOwned: [false]
});
this.startupForm = this.fb.group({
dpiitRecognitionNumber: [''],
recognitionDate: [''],
certificateExpiryDate: [''],
entityStage: [''],
sectorAsDpiit: [''],
nicIndustryCode: [''],
taxExemption80iac: [false],
sidbiFund: [false],
selfCertification: [false],
fastTrackPatent: [false],
govtTenderExemption: [false],
creditGuaranteeCgss: [false],
pslLoanLimit: [''],
pslSubCategory: ['']
});
this.mudraForm = this.fb.group({
mudraCategory: [''],
mudraLoanAccountNo: [''],
lendingInstitutionName: [''],
sanctionedAmount: [''],
disbursementDate: [''],
loanPurpose: [''],
mudraCardNumber: [''],
currentOutstanding: [''],
repaymentStatus: [''],
npaFlag: [false]
});
this.eouForm = this.fb.group({
eouRegistrationNumber: [''],
registeredDcZone: [''],
bondLutNumber: [''],
validityFrom: [''],
validityTo: [''],
gstinEou: [''],
annualExportObligation: [''],
nfeTarget: [''],
softexFilingStatus: [''],
brcSubmissionStatus: [''],
adCategoryBankCode: [''],
femaDeclarationDate: ['']
});
this.importexportForm = this.fb.group({
iecCode: [''],
iecIssueDate: [''],
iecStatus: [''],
tradeType: [''],
primaryHsCode: [''],
keyTradingCountries: [''],
adCategoryBankCode: [''],
ecgcPolicyNumber: [''],
ecgcPolicyExpiry: [''],
eefcAccountRequired: [false],
pcfcFacilityRequired: [false],
femaDeclarationObtained: [false]
});
this.pslForm = this.fb.group({
pslCategory: [''],
pslSubCategory: [''],
pslLoanPurposeCode: [''],
pslEligibilityBasis: [''],
fiddReportingCode: [''],
pslSanctionedLimit: [''],
msmeClassification: [''],
udyamRegistrationNumber: [''],
udyamRegistrationDate: [''],
annualTurnover: [''],
investmentPlantMachinery: [''],
weakerSectionFlag: [false],
scStBorrowerFlag: [false],
womenEntrepreneurFlag: [false],
minorityCommunityFlag: [false]
});
this.npsForm = this.fb.group({
industrySector: [''],
nicCode: [''],
industryDescription: [''],
annualRevenueBand: [''],
riskCategory: [''],
customerRiskScore: [''],
amlRiskClassification: [''],
pepFlag: [false],
amlWatchlistMatch: [false],
adverseMediaFlag: [false]
});
}
getForm(categoryId: string): UntypedFormGroup {
switch (categoryId) {
case 'msme':
return this.msmeForm;
case 'startup':
return this.startupForm;
case 'mudra':
return this.mudraForm;
case 'eou':
return this.eouForm;
case 'importexport':
return this.importexportForm;
case 'psl':
return this.pslForm;
case 'nps':
return this.npsForm;
default:
return this.fb.group({});
}
}
toggleCategory(id: string) {
this.enabled[id] = !this.enabled[id];
if (this.enabled[id]) {
this.expanded[id] = true;
}
}
toggleExpand(id: string) {
this.expanded[id] = !this.expanded[id];
}
get enabledCategories(): CategoryMeta[] {
return this.categories.filter((c) => this.enabled[c.id]);
}
get enabledCount(): number {
return this.enabledCategories.length;
}
removeCategory(id: string) {
this.enabled[id] = false;
this.expanded[id] = false;
}
/** Save a single category */
saveCategory(categoryId: string) {
if (!this.clientId) return;
this.saving[categoryId] = true;
const form = this.getForm(categoryId);
const payload: any = { ...form.value, enabled: true, locale: 'en', dateFormat: this.settingsService.dateFormat };
// Format date fields
for (const key of Object.keys(payload)) {
if (payload[key] instanceof Date) {
payload[key] = this.dateUtils.formatDate(payload[key], this.settingsService.dateFormat);
}
}
this.clientService.saveEntityClassification(this.clientId, categoryId, payload).subscribe({
next: () => {
this.saving[categoryId] = false;
this.saved[categoryId] = true;
setTimeout(() => (this.saved[categoryId] = false), 3000);
},
error: () => {
this.saving[categoryId] = false;
}
});
}
/** Load existing classifications */
private loadExisting() {
this.clientService.getEntityClassifications(this.clientId).subscribe({
next: (data: any) => {
if (!data) return;
for (const cat of this.categories) {
const catData = data[cat.id];
if (catData && catData.enabled) {
this.enabled[cat.id] = true;
this.getForm(cat.id).patchValue(catData);
}
}
}
});
}
/** Get all classification data for parent */
get classificationData(): any {
const result: any = {};
for (const cat of this.categories) {
if (this.enabled[cat.id]) {
result[cat.id] = { ...this.getForm(cat.id).value, enabled: true };
}
}
return result;
}
get hasClassificationData(): boolean {
return this.enabledCount > 0;
}
// Keep old getter for backward compatibility
get entityKycData(): any {
return this.classificationData;
}
get hasEntityKycData(): boolean {
return this.hasClassificationData;
}
}