feat: Client & CKYC UI improvements — filters, KYC management, image crop+merge
- Clients list: CKYC icon, CKYC Number column, status/legal form/CKYC filters - CKYC: SFTP upload logs, date formatting, modal z-index fix, non-dismissible dialogs - KYC Management: new standalone module with alert dashboard, notification scheduler, audit inventory, account status - Image cropper: ngx-image-cropper integration for front+back document merge into single PNG - Sidebar: KYC Management menu entry after CKYC Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
79e455c4ed
commit
d72e969dc3
@@ -320,6 +320,80 @@ export class ClientsService {
|
||||
return this.http.get(`/clients/${clientId}/identifiers`);
|
||||
}
|
||||
|
||||
getKycProofTypes(type?: 'id' | 'address'): Observable<any> {
|
||||
const options = type ? { params: new HttpParams().set('type', type) } : {};
|
||||
return this.http.get(`/kyc/proof-types`, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 1 – Record Master: fetch clients missing CKYC registration
|
||||
* or artefacts. Backed by GET /ckyc/record-master.
|
||||
*/
|
||||
getCkycRecordMaster(filters: {
|
||||
officeId?: number | string;
|
||||
productId?: number | string;
|
||||
fromDate?: string;
|
||||
toDate?: string;
|
||||
missing?: 'photo' | 'signature' | 'id' | 'address' | 'any';
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
} = {}): Observable<any> {
|
||||
let params = new HttpParams();
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
if (value !== null && value !== undefined && value !== '') {
|
||||
params = params.set(key, String(value));
|
||||
}
|
||||
});
|
||||
return this.http.get(`/ckyc/record-master`, { params });
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 2 – Auto ZIP Creation: bundle selected clients into a CERSAI
|
||||
* ZIP on the server. Backed by POST /ckyc/batches.
|
||||
*/
|
||||
createCkycBatch(body: { clientIds: (number | string)[]; remarks?: string }): Observable<any> {
|
||||
return this.http.post(`/ckyc/batches`, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 2/3 – List CKYC batches. Supports filters and an optional
|
||||
* groupByDate=true to bucket results by created_on for the UI.
|
||||
*/
|
||||
getCkycBatches(filters: {
|
||||
fromDate?: string;
|
||||
toDate?: string;
|
||||
uploadedToCersai?: boolean;
|
||||
groupByDate?: boolean;
|
||||
} = {}): Observable<any> {
|
||||
let params = new HttpParams();
|
||||
Object.entries(filters).forEach(([key, value]) => {
|
||||
if (value !== null && value !== undefined && value !== '') {
|
||||
params = params.set(key, String(value));
|
||||
}
|
||||
});
|
||||
return this.http.get(`/ckyc/batches`, { params });
|
||||
}
|
||||
|
||||
/** Fetch a single CKYC batch with parsed manifest. */
|
||||
getCkycBatchById(id: number | string): Observable<any> {
|
||||
return this.http.get(`/ckyc/batches/${id}`);
|
||||
}
|
||||
|
||||
/** Download the ZIP attached to a batch (via generic document endpoint). */
|
||||
downloadCkycBatchZip(parentEntityId: number | string, documentId: number | string): Observable<Blob> {
|
||||
return this.http.get(`/ckyc_batch/${parentEntityId}/documents/${documentId}/attachment`, {
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase 3 – SFTP upload to CERSAI. Uploads the batch ZIP over the
|
||||
* SFTP channel and returns the ACK + per-client CKYC numbers.
|
||||
*/
|
||||
uploadCkycBatchToSftp(batchId: number | string): Observable<any> {
|
||||
return this.http.post(`/ckyc/batches/${batchId}/sftp-upload`, {});
|
||||
}
|
||||
|
||||
getClientIdentifierTemplate(clientId: string) {
|
||||
return this.http.get(`/clients/${clientId}/identifiers/template`);
|
||||
}
|
||||
@@ -653,6 +727,29 @@ export class ClientsService {
|
||||
return this.http.post(`/clients/${clientId}/kyc/${kycId}?command=verify-gstin`, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies DIN (Director Identification Number) for an authorized signatory.
|
||||
* Sends signatory clientId, DIN number and the non-individual entity name.
|
||||
* Backend saves DIN & verification status in KYC table and returns company list.
|
||||
* @param clientId Signatory's Client ID
|
||||
* @param kycId KYC record ID
|
||||
* @param dinNumber DIN number to verify
|
||||
* @param entityName Non-individual entity name (for company match)
|
||||
*/
|
||||
verifyDIN(clientId: string, kycId: string, dinNumber: string, entityName: string): Observable<any> {
|
||||
return this.http.post(`/clients/${clientId}/kyc/${kycId}?command=verify-din`, { dinNumber, entityName });
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes Re-KYC after uploading signed self-declaration form.
|
||||
* Updates Last Verified date to today and sets new Expiry Date (today + 10 years for low risk).
|
||||
* @param clientId Client ID
|
||||
* @param kycId KYC record ID
|
||||
*/
|
||||
completeReKyc(clientId: string, kycId: string): Observable<any> {
|
||||
return this.http.post(`/clients/${clientId}/kyc/${kycId}?command=complete-rekyc`, {});
|
||||
}
|
||||
|
||||
// ═══ Entity Classification APIs ═══
|
||||
|
||||
getEntityClassifications(clientId: string): Observable<any> {
|
||||
|
||||
Reference in New Issue
Block a user