feat(clients, alm): add CIN/MCA verification & authorized signatories tab; refactor ALM report print and export
This commit is contained in:
@@ -215,11 +215,18 @@
|
||||
</div>
|
||||
}
|
||||
<div class="tab-section">
|
||||
<!-- constitutionMeta and entityName are bound here exactly as they are in create-client.
|
||||
Without them an entity opened for edit falls back to the generic document list rather
|
||||
than the one its constitution actually uses, so the document type saved at creation
|
||||
can be missing from the picker; a proprietorship is also mis-rendered, since the
|
||||
proprietor-PAN branch keys off the constitution. -->
|
||||
<mifosx-client-kyc-step
|
||||
#clientKyc
|
||||
[isNonIndividual]="legalFormType === 2"
|
||||
[isMinor]="clientGeneralStep?.isMinor || false"
|
||||
[clientId]="clientId"
|
||||
[constitutionMeta]="clientGeneralStep?.selectedConstitution"
|
||||
[entityName]="clientGeneralStep?.createClientForm?.get('fullname')?.value || ''"
|
||||
[verificationName]="clientGeneralStep?.verificationName || ''"
|
||||
[verificationDateOfBirth]="clientGeneralStep?.verificationDateOfBirth || null"
|
||||
[readOnly]="isTabReadOnly(1)"
|
||||
|
||||
@@ -40,6 +40,7 @@ import { MatProgressSpinner } from '@angular/material/progress-spinner';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
import { ORIGINAL_VALUES_PAYLOAD_KEY, buildOriginalValuesSnapshot } from '../shared/client-edit-diff.util';
|
||||
import { toProperNameCase } from '../utils/name-case.util';
|
||||
|
||||
/**
|
||||
* Edit Client Component — uses the same wizard/stepper layout as Create Client.
|
||||
@@ -589,13 +590,11 @@ export class EditClientComponent {
|
||||
const kycId = this.clientKycStep.kycId;
|
||||
const isVerified = this.clientKycStep.isKycVerified;
|
||||
|
||||
// Validate remarks are present for verified KYC
|
||||
if (isVerified && !kycData.remarks?.trim()) {
|
||||
this.savingClient = false;
|
||||
this.clientKycStep.kycForm.get('remarks')?.markAsTouched();
|
||||
return;
|
||||
}
|
||||
|
||||
// Remarks are not demanded here. The server requires them only when a save actually
|
||||
// overwrites data the verified record already held, and it names the reason when it
|
||||
// refuses. Blocking every verified record up front aborted the save silently — the photo
|
||||
// upload above had already gone through, so the image changed, the button came back to
|
||||
// life, and nothing said why nothing had been saved.
|
||||
let saveObs;
|
||||
if (kycId && isVerified) {
|
||||
// VERIFIED → re-edit command
|
||||
@@ -628,8 +627,19 @@ export class EditClientComponent {
|
||||
this.saveKycDocProof(this.clientId);
|
||||
this.selectedTabIndex = this.selectedTabIndex + 1;
|
||||
},
|
||||
error: () => {
|
||||
// A rejected save used to just re-enable the button, which reads as "nothing happened".
|
||||
// The server's own message says what is missing — remarks on a re-edit, most often — so
|
||||
// it is shown rather than swallowed, and the KYC tab stays put for the officer to fix.
|
||||
error: (err: any) => {
|
||||
this.savingClient = false;
|
||||
const message =
|
||||
err?.error?.errors?.[0]?.defaultUserMessage ||
|
||||
err?.error?.defaultUserMessage ||
|
||||
'KYC could not be saved. Please review the KYC details and try again.';
|
||||
this.snackBar.open(message, 'Close', { duration: 6000 });
|
||||
if (isVerified) {
|
||||
this.clientKycStep?.kycForm.get('remarks')?.markAsTouched();
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
@@ -734,17 +744,20 @@ export class EditClientComponent {
|
||||
? this.toLocalDateString(oldDobRaw)
|
||||
: oldDobRaw || '';
|
||||
|
||||
// Both sides run through toProperNameCase so a casing-only difference — the stored
|
||||
// 'LINCPAY LTD' against the normalized 'Lincpay LTD' the form now submits — is not
|
||||
// mistaken for a real rename and does not force a PAN re-verification.
|
||||
const buildName = (parts: { firstname?: string; middlename?: string; lastname?: string; fullname?: string }) =>
|
||||
(
|
||||
toProperNameCase(
|
||||
parts.fullname ||
|
||||
[
|
||||
parts.firstname,
|
||||
parts.middlename,
|
||||
parts.lastname
|
||||
]
|
||||
.filter((p) => p && p.trim())
|
||||
.join(' ')
|
||||
).trim();
|
||||
[
|
||||
parts.firstname,
|
||||
parts.middlename,
|
||||
parts.lastname
|
||||
]
|
||||
.filter((p) => p && p.trim())
|
||||
.join(' ')
|
||||
);
|
||||
|
||||
const newName = buildName({
|
||||
firstname: form?.get('firstname')?.value || '',
|
||||
|
||||
Reference in New Issue
Block a user