feat(election): add guarantor status section to nomination-apply page

Shows whether the selected nominee is a guarantor on any loan, with loan health indicator, borrower details, savings account, guaranteed/released/remaining amounts, and loan timeline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-06-24 13:12:08 +05:30
co-authored by Claude Sonnet 4.6
parent 3d9b0480c6
commit 71552d6875
14 changed files with 2532 additions and 749 deletions
@@ -104,116 +104,90 @@
</div>
</div>
</div>
<table
class="flex-fill"
mat-table
[dataSource]="guarantorDetails | accountsFilter: 'guarantor' : showDeletedGuarantorsAccounts"
>
<table mat-table [dataSource]="guarantorDetails | accountsFilter: 'guarantor' : showDeletedGuarantorsAccounts">
<ng-container matColumnDef="fullname">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.name' | translate }}</th>
<td mat-cell *matCellDef="let guarantor">
@if (!guarantor.guarantorFundingDetails) {
<span> {{ guarantor.firstname }} &nbsp; {{ guarantor.lastname }} </span>
}
<span> {{ guarantor.firstname }} &nbsp; {{ guarantor.lastname }} </span>
</td>
</ng-container>
<ng-container matColumnDef="relationship">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Relationship' | translate }}</th>
<td mat-cell *matCellDef="let guarantor">
@if (!guarantor.guarantorFundingDetails) {
<span>
{{ guarantor.clientRelationshipType?.name }}
</span>
}
<span>{{ guarantor.clientRelationshipType?.name }}</span>
</td>
</ng-container>
<ng-container matColumnDef="guarantortype">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Guarantor Type' | translate }}</th>
<td mat-cell *matCellDef="let guarantor">
@if (!guarantor.guarantorFundingDetails) {
<span>
{{ guarantor.guarantorType.value }}
</span>
}
<span>{{ guarantor.guarantorType.value }}</span>
</td>
</ng-container>
<ng-container matColumnDef="depositAccount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Deposit Account' | translate }}</th>
<td mat-cell *matCellDef="let guarantor">
@if (!guarantor.guarantorFundingDetails) {
<span> </span>
@if (guarantor.guarantorFundingDetails?.length) {
<span>{{ guarantor.guarantorFundingDetails[0].savingsAccount?.accountNo }}</span>
}
</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
<td mat-cell *matCellDef="let guarantor">
@if (!guarantor.guarantorFundingDetails) {
<span> </span>
@if (guarantor.guarantorFundingDetails?.length) {
<span>{{ guarantor.guarantorFundingDetails[0].amount | formatNumber }}</span>
}
</td>
</ng-container>
<ng-container matColumnDef="remainingAmount">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Remaining Amount' | translate }}</th>
<td mat-cell *matCellDef="let guarantor">
@if (!guarantor.guarantorFundingDetails) {
<span> </span>
@if (guarantor.guarantorFundingDetails?.length) {
<span>{{ guarantor.guarantorFundingDetails[0].amountRemaining | formatNumber }}</span>
}
</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Status' | translate }}</th>
<td mat-cell *matCellDef="let guarantor">
@if (!guarantor.guarantorFundingDetails) {
<span>
@if (guarantor.status) {
<span>
{{ 'labels.inputs.Active' | translate }}
</span>
}
@if (!guarantor.status) {
<span>
{{ 'labels.inputs.Deleted' | translate }}
</span>
}
</span>
@if (guarantor.status) {
<span>{{ 'labels.inputs.Active' | translate }}</span>
}
@if (!guarantor.status) {
<span>{{ 'labels.inputs.Deleted' | translate }}</span>
}
</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Action' | translate }}</th>
<td mat-cell *matCellDef="let guarantor; let id = index">
@if (!guarantor.guarantorFundingDetails) {
<span>
<span>
<button
mat-raised-button
class="account-action-button"
color="primary"
*mifosxHasPermission="'READ_SAVINGSACCOUNT'"
(click)="viewGuarantorDetails(guarantor)"
>
<fa-icon icon="eye" class="m-r-10"></fa-icon>
</button>
@if (guarantor.status && guarantor.guarantorType.id === 3 && guarantor.id) {
<button mat-raised-button class="account-action-button" color="primary">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
</button>
}
@if (guarantor.status) {
<button
mat-raised-button
class="account-action-button"
color="primary"
*mifosxHasPermission="'READ_SAVINGSACCOUNT'"
(click)="viewGuarantorDetails(guarantor)"
color="warn"
*mifosxHasPermission="'DELETE_GUARANTOR'"
(click)="deleteGuarantor(guarantor.id)"
>
<fa-icon icon="eye" class="m-r-10"></fa-icon>
<fa-icon icon="trash" class="m-r-10"></fa-icon>
</button>
@if (guarantor.status && guarantor.guarantorType.id === 3 && guarantor.id) {
<button mat-raised-button class="account-action-button" color="primary">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
</button>
}
@if (guarantor.status) {
<span>
<button
mat-raised-button
class="account-action-button"
color="warn"
*mifosxHasPermission="'DELETE_GUARANTOR'"
(click)="deleteGuarantor(guarantor.id)"
>
<fa-icon icon="trash" class="m-r-10"></fa-icon>
</button>
</span>
}
</span>
}
}
</span>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="guarantorsDisplayedColumns"></tr>
+4
View File
@@ -800,4 +800,8 @@ export class LoansService {
const httpParams = new HttpParams().set('offset', offset.toString()).set('limit', limit.toString());
return this.http.get('/entityDatatableChecks', { params: httpParams });
}
getLoanGuarantors(loanId: string): Observable<any> {
return this.http.get(`/loans/${loanId}/guarantors`);
}
}