feat: Pending and Rejected account tabs in Approval Center with tasks service

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-05-25 11:06:19 +05:30
co-authored by Claude Sonnet 4.6
parent b7d009b22a
commit 38c4a7d9e9
8 changed files with 181 additions and 8 deletions
@@ -19,9 +19,22 @@
/> />
</mat-form-field> </mat-form-field>
<div class="cv-action-buttons"> <div class="cv-action-buttons">
<button mat-stroked-button class="cv-btn cv-btn-approve" (click)="approveAccounts()"> <button
mat-stroked-button
class="cv-btn cv-btn-approve"
[disabled]="!selection.hasValue()"
(click)="approveAccounts()"
>
<fa-icon icon="check" class="m-r-10"></fa-icon>Approve <fa-icon icon="check" class="m-r-10"></fa-icon>Approve
</button> </button>
<button
mat-stroked-button
class="cv-btn cv-btn-reject"
[disabled]="!selection.hasValue()"
(click)="rejectAccounts()"
>
<fa-icon icon="ban" class="m-r-10"></fa-icon>Reject
</button>
</div> </div>
</div> </div>
@@ -103,8 +116,8 @@
<tr <tr
mat-row mat-row
*matRowDef="let row; columns: displayedColumns" *matRowDef="let row; columns: displayedColumns"
(click)="selection.toggle(row)" (click)="navigateToAccount(row)"
class="table-row" class="table-row clickable-row"
></tr> ></tr>
</table> </table>
</div> </div>
@@ -89,9 +89,34 @@ $text-muted: #64748b;
border-color: #16a34a; border-color: #16a34a;
color: #16a34a; color: #16a34a;
&:hover { &:hover:not([disabled]) {
background: #f0fdf4; background: #f0fdf4;
} }
&[disabled] {
opacity: 0.45;
}
}
.cv-btn-reject {
border-color: #dc2626;
color: #dc2626;
&:hover:not([disabled]) {
background: #fef2f2;
}
&[disabled] {
opacity: 0.45;
}
}
.clickable-row {
cursor: pointer;
&:hover td {
background: #f8fafc;
}
} }
.type-badge { .type-badge {
@@ -107,7 +107,25 @@ export class PendingAccountComponent {
this.dataSource.filter = filterValue.trim().toLowerCase(); this.dataSource.filter = filterValue.trim().toLowerCase();
} }
navigateToAccount(account: any): void {
const clientId = account.clientId;
const accountId = account.id;
const depositTypeId = account.depositType?.id;
let path: string;
if (account.accountType === 'Current') {
path = `/clients/${clientId}/current-accounts/${accountId}`;
} else if (depositTypeId === 200) {
path = `/clients/${clientId}/fixed-deposits-accounts/${accountId}`;
} else if (depositTypeId === 300) {
path = `/clients/${clientId}/recurring-deposits-accounts/${accountId}`;
} else {
path = `/clients/${clientId}/savings-accounts/${accountId}`;
}
this.router.navigate([path]);
}
approveAccounts() { approveAccounts() {
if (!this.selection.hasValue()) return;
const formfields: FormfieldBase[] = [ const formfields: FormfieldBase[] = [
new DatepickerBase({ new DatepickerBase({
controlName: 'approvedOnDate', controlName: 'approvedOnDate',
@@ -131,6 +149,60 @@ export class PendingAccountComponent {
}); });
} }
rejectAccounts() {
if (!this.selection.hasValue()) return;
const formfields: FormfieldBase[] = [
new DatepickerBase({
controlName: 'rejectedOnDate',
label: 'Rejected On Date',
value: new Date(),
type: 'datetime-local',
required: true
})
];
const dialogRef = this.dialog.open(FormDialogComponent, {
data: {
title: 'Enter Rejection Date',
layout: { addButtonText: 'Confirm' },
formfields
}
});
dialogRef.afterClosed().subscribe((response: any) => {
if (response?.data) {
this.bulkReject(response.data);
}
});
}
private bulkReject(submittedData: any) {
const dateFormat = this.settingsService.dateFormat;
const locale = this.settingsService.language.code;
const rejectedOnDate = this.dateUtils.formatDate(submittedData.value.rejectedOnDate, dateFormat);
const payload = { rejectedOnDate, dateFormat, locale };
const selected = this.selection.selected;
let done = 0;
selected.forEach((account: any) => {
const depositTypeId = account.depositType?.id;
let reject$;
if (account.accountType === 'Current') {
reject$ = this.tasksService.rejectCurrentAccount(account.id, payload);
} else if (depositTypeId === 200) {
reject$ = this.tasksService.rejectFDAccount(account.id, payload);
} else if (depositTypeId === 300) {
reject$ = this.tasksService.rejectRDAccount(account.id, payload);
} else {
reject$ = this.tasksService.rejectSavingsAccount(account.id, payload);
}
reject$.subscribe(() => {
done++;
if (done === selected.length) {
this.reload();
}
});
});
}
private bulkApprove(submittedData: any) { private bulkApprove(submittedData: any) {
const dateFormat = this.settingsService.dateFormat; const dateFormat = this.settingsService.dateFormat;
const locale = this.settingsService.language.code; const locale = this.settingsService.language.code;
@@ -83,7 +83,12 @@
</ng-container> </ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns" class="table-row"></tr> <tr
mat-row
*matRowDef="let row; columns: displayedColumns"
(click)="navigateToAccount(row)"
class="table-row"
></tr>
</table> </table>
</div> </div>
} }
@@ -63,6 +63,14 @@ $text-muted: #64748b;
} }
} }
.table-row {
cursor: pointer;
&:hover td {
background: #f8fafc;
}
}
.type-badge { .type-badge {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
@@ -7,7 +7,7 @@
*/ */
import { Component, inject } from '@angular/core'; import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { import {
MatTableDataSource, MatTableDataSource,
MatTable, MatTable,
@@ -47,6 +47,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
}) })
export class RejectedAccountComponent { export class RejectedAccountComponent {
private route = inject(ActivatedRoute); private route = inject(ActivatedRoute);
private router = inject(Router);
dataSource: MatTableDataSource<any>; dataSource: MatTableDataSource<any>;
showData = false; showData = false;
@@ -72,6 +73,23 @@ export class RejectedAccountComponent {
}); });
} }
navigateToAccount(account: any): void {
const clientId = account.clientId;
const accountId = account.id;
const depositTypeId = account.depositType?.id;
let path: string;
if (account.accountType === 'Current') {
path = `/clients/${clientId}/current-accounts/${accountId}`;
} else if (depositTypeId === 200) {
path = `/clients/${clientId}/fixed-deposits-accounts/${accountId}`;
} else if (depositTypeId === 300) {
path = `/clients/${clientId}/recurring-deposits-accounts/${accountId}`;
} else {
path = `/clients/${clientId}/savings-accounts/${accountId}`;
}
this.router.navigate([path]);
}
applyFilter(filterValue: string = '') { applyFilter(filterValue: string = '') {
this.dataSource.filter = filterValue.trim().toLowerCase(); this.dataSource.filter = filterValue.trim().toLowerCase();
} }
+32
View File
@@ -172,6 +172,38 @@ export class TasksService {
return this.http.post(`/currentaccounts/${accountId}`, data, { params: httpParams }); return this.http.post(`/currentaccounts/${accountId}`, data, { params: httpParams });
} }
/**
* Reject a savings account
*/
rejectSavingsAccount(accountId: any, data: any): Observable<any> {
const httpParams = new HttpParams().set('command', 'reject');
return this.http.post(`/savingsaccounts/${accountId}`, data, { params: httpParams });
}
/**
* Reject a fixed deposit account
*/
rejectFDAccount(accountId: any, data: any): Observable<any> {
const httpParams = new HttpParams().set('command', 'reject');
return this.http.post(`/fixeddepositaccounts/${accountId}`, data, { params: httpParams });
}
/**
* Reject a recurring deposit account
*/
rejectRDAccount(accountId: any, data: any): Observable<any> {
const httpParams = new HttpParams().set('command', 'reject');
return this.http.post(`/recurringdepositaccounts/${accountId}`, data, { params: httpParams });
}
/**
* Reject a current account
*/
rejectCurrentAccount(accountId: any, data: any): Observable<any> {
const httpParams = new HttpParams().set('command', 'reject');
return this.http.post(`/currentaccounts/${accountId}`, data, { params: httpParams });
}
/** /**
* Submit data in batches. * Submit data in batches.
* @param {data} Data to be submitted * @param {data} Data to be submitted
+2 -2
View File
@@ -9,8 +9,8 @@
/* tslint:disable */ /* tslint:disable */
export default { export default {
'mifos_x': { 'mifos_x': {
'version': '260522', 'version': '260525',
'hash': '64c76a98' 'hash': 'ad6f629c'
}, },
'allow_switching_backend_instance': true 'allow_switching_backend_instance': true
}; };