- Fix signature-document reads picking the oldest upload instead of the latest across 7 call sites (CKYC tab, view/delete-signature dialogs, edit-wizard preview, cashier transaction entry, signatory service, record-master) by sorting on document id instead of an unsorted find(). - Add Monthly Turnover and Annual Income fields alongside the renamed Yearly Turnover field. - Add Senior Citizen (auto-detected from DOB) and Person with Disability classification, with a required disability-certificate upload gate before client creation can proceed. - Add Graduate and Diploma as distinct Education Levels, with diploma-specific degree options. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
91 lines
2.7 KiB
TypeScript
91 lines
2.7 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/.
|
|
*/
|
|
|
|
/** Angular Imports */
|
|
import { Component, OnInit, inject } from '@angular/core';
|
|
import {
|
|
MatDialogRef,
|
|
MAT_DIALOG_DATA,
|
|
MatDialogTitle,
|
|
MatDialogContent,
|
|
MatDialogActions,
|
|
MatDialogClose
|
|
} from '@angular/material/dialog';
|
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
|
|
/** Custom Services */
|
|
import { ClientsService } from 'app/clients/clients.service';
|
|
|
|
/** Node Types */
|
|
import { Buffer } from 'buffer';
|
|
import { CdkScrollable } from '@angular/cdk/scrolling';
|
|
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
|
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
|
|
|
/**
|
|
* View signature dialog component.
|
|
*/
|
|
@Component({
|
|
selector: 'mifosx-view-signature-dialog',
|
|
templateUrl: './view-signature-dialog.component.html',
|
|
styleUrls: ['./view-signature-dialog.component.scss'],
|
|
imports: [
|
|
...STANDALONE_SHARED_IMPORTS,
|
|
MatDialogTitle,
|
|
CdkScrollable,
|
|
MatDialogContent,
|
|
MatDialogActions,
|
|
MatDialogClose,
|
|
FaIconComponent
|
|
]
|
|
})
|
|
export class ViewSignatureDialogComponent implements OnInit {
|
|
dialogRef = inject<MatDialogRef<ViewSignatureDialogComponent>>(MatDialogRef);
|
|
private clientsService = inject(ClientsService);
|
|
private sanitizer = inject(DomSanitizer);
|
|
data = inject<{
|
|
documents: any[];
|
|
id: string;
|
|
}>(MAT_DIALOG_DATA);
|
|
|
|
/** Id of client signature in documents */
|
|
signatureId: any;
|
|
/** Signature Image */
|
|
signatureImage: any;
|
|
/** Client Id */
|
|
clientId: any;
|
|
|
|
/**
|
|
* @param {MatDialogRef} dialogRef Component reference to dialog.
|
|
* @param {any} data Documents data
|
|
*/
|
|
constructor() {
|
|
// Multiple 'clientSignature' documents can exist for clients who re-cropped/replaced their
|
|
// signature before uploads became single-slot, so pick the highest id (latest) rather than
|
|
// the first unordered match.
|
|
const signature =
|
|
this.data.documents
|
|
.filter((document: any) => document.name === 'clientSignature')
|
|
.sort((a: any, b: any) => b.id - a.id)[0] || {};
|
|
this.signatureId = signature.id;
|
|
this.clientId = this.data.id;
|
|
}
|
|
|
|
ngOnInit() {
|
|
if (this.signatureId) {
|
|
this.clientsService.getClientSignatureImage(this.clientId, this.signatureId).subscribe(
|
|
async (blob: any) => {
|
|
const buffer = Buffer.from(await blob.arrayBuffer());
|
|
this.signatureImage = 'data:' + blob.type + ';base64,' + buffer.toString('base64');
|
|
},
|
|
(error: any) => {}
|
|
);
|
|
}
|
|
}
|
|
}
|