fix(savings): show a clear message when an action is parked for checker approval

Approve, close, reject, undo-approval, withdraw-by-client, and post-interest
on a savings account all silently behaved as if nothing happened when the
backend parks the command in the Checker Inbox instead of executing it
(HTTP 200 with rollbackTransaction: true) -- misleading the maker into
thinking the action either failed or quietly succeeded. Each now shows an
explicit alert naming what was sent for approval and that the account/
application is unchanged until a checker approves it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-10-05 16:14:24 +05:30
co-authored by Claude Sonnet 5
parent 174a2e7b6b
commit 244b70f926
6 changed files with 80 additions and 10 deletions
@@ -11,6 +11,7 @@ import { Component, OnInit, inject } from '@angular/core';
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { Dates } from 'app/core/utils/dates';
import { AlertService } from 'app/core/alert/alert.service';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
@@ -37,6 +38,7 @@ export class ApproveSavingsAccountComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private settingsService = inject(SettingsService);
private alertService = inject(AlertService);
/** Minimum date allowed. */
minDate = new Date(2000, 0, 1);
@@ -98,7 +100,19 @@ export class ApproveSavingsAccountComponent implements OnInit {
dateFormat,
locale
};
this.savingsService.executeSavingsAccountCommand(this.accountId, 'approve', data).subscribe(() => {
this.savingsService.executeSavingsAccountCommand(this.accountId, 'approve', data).subscribe((response: any) => {
// Parked in the Checker Inbox rather than executed (HTTP 200 with rollbackTransaction: true).
// The account is therefore still pending, so chaining activation onto it would be applied to an
// unapproved account -- stop here and say what is actually waiting.
if (response?.rollbackTransaction) {
this.alertService.alert({
type: 'Success',
message:
'This approval has been sent for checker approval. The account stays pending until a checker approves it.'
});
this.router.navigate(['../../transactions'], { relativeTo: this.route });
return;
}
const activationData = {
activatedOnDate: approveSavingsAccountFormData.approvedOnDate,
dateFormat,
@@ -20,6 +20,7 @@ import { Dates } from 'app/core/utils/dates';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
import { AlertService } from 'app/core/alert/alert.service';
import { SettingsService } from 'app/settings/settings.service';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatSlideToggle } from '@angular/material/slide-toggle';
@@ -47,6 +48,7 @@ export class CloseSavingsAccountComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private settingsService = inject(SettingsService);
private alertService = inject(AlertService);
/** Minimum date allowed. */
minDate = new Date(2000, 0, 1);
@@ -158,7 +160,15 @@ export class CloseSavingsAccountComponent implements OnInit {
dateFormat,
locale
};
this.savingsService.executeSavingsAccountCommand(this.accountId, 'close', data).subscribe(() => {
this.savingsService.executeSavingsAccountCommand(this.accountId, 'close', data).subscribe((response: any) => {
// Parked in the Checker Inbox rather than executed (HTTP 200 with rollbackTransaction: true),
// so the account is still open -- say so instead of letting that read as "nothing happened".
if (response?.rollbackTransaction) {
this.alertService.alert({
type: 'Success',
message: 'Closure has been sent for checker approval. The account is unchanged until a checker approves it.'
});
}
this.router.navigate(['../../transactions'], { relativeTo: this.route });
});
}
@@ -14,6 +14,7 @@ import { Dates } from 'app/core/utils/dates';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
import { AlertService } from 'app/core/alert/alert.service';
import { SettingsService } from 'app/settings/settings.service';
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -37,6 +38,7 @@ export class RejectSavingsAccountComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private settingsService = inject(SettingsService);
private alertService = inject(AlertService);
/** Minimum date allowed. */
minDate = new Date(2000, 0, 1);
@@ -97,7 +99,16 @@ export class RejectSavingsAccountComponent implements OnInit {
dateFormat,
locale
};
this.savingsService.executeSavingsAccountCommand(this.accountId, 'reject', data).subscribe(() => {
this.savingsService.executeSavingsAccountCommand(this.accountId, 'reject', data).subscribe((response: any) => {
// Parked in the Checker Inbox rather than executed (HTTP 200 with rollbackTransaction: true),
// so the application is still open -- say so instead of letting that read as "nothing happened".
if (response?.rollbackTransaction) {
this.alertService.alert({
type: 'Success',
message:
'Rejection has been sent for checker approval. The application is unchanged until a checker approves it.'
});
}
this.router.navigate(['../../'], { relativeTo: this.route });
});
}
@@ -13,6 +13,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
import { AlertService } from 'app/core/alert/alert.service';
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -33,6 +34,7 @@ export class UndoApprovalSavingsAccountComponent implements OnInit {
private savingsService = inject(SavingsService);
private route = inject(ActivatedRoute);
private router = inject(Router);
private alertService = inject(AlertService);
/** Undo Approval Savings Account form. */
undoApprovalSavingsAccountForm: UntypedFormGroup;
@@ -73,8 +75,19 @@ export class UndoApprovalSavingsAccountComponent implements OnInit {
const data = {
...this.undoApprovalSavingsAccountForm.value
};
this.savingsService.executeSavingsAccountCommand(this.accountId, 'undoapproval', data).subscribe(() => {
this.router.navigate(['../../transactions'], { relativeTo: this.route });
});
this.savingsService
.executeSavingsAccountCommand(this.accountId, 'undoapproval', data)
.subscribe((response: any) => {
// Parked in the Checker Inbox rather than executed (HTTP 200 with rollbackTransaction: true),
// so the account reloads unchanged -- say so instead of letting that read as "it worked".
if (response?.rollbackTransaction) {
this.alertService.alert({
type: 'Success',
message:
'Undo approval has been sent for checker approval. The account is unchanged until a checker approves it.'
});
}
this.router.navigate(['../../transactions'], { relativeTo: this.route });
});
}
}
@@ -14,6 +14,7 @@ import { Dates } from 'app/core/utils/dates';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
import { AlertService } from 'app/core/alert/alert.service';
import { SettingsService } from 'app/settings/settings.service';
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -37,6 +38,7 @@ export class WithdrawByClientSavingsAccountComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private settingsService = inject(SettingsService);
private alertService = inject(AlertService);
/** Minimum date allowed. */
minDate = new Date(2000, 0, 1);
@@ -97,8 +99,19 @@ export class WithdrawByClientSavingsAccountComponent implements OnInit {
dateFormat,
locale
};
this.savingsService.executeSavingsAccountCommand(this.accountId, 'withdrawnByApplicant', data).subscribe(() => {
this.router.navigate(['../../'], { relativeTo: this.route });
});
this.savingsService
.executeSavingsAccountCommand(this.accountId, 'withdrawnByApplicant', data)
.subscribe((response: any) => {
// Parked in the Checker Inbox rather than executed (HTTP 200 with rollbackTransaction: true),
// so the application is still open -- say so instead of letting that read as "nothing happened".
if (response?.rollbackTransaction) {
this.alertService.alert({
type: 'Success',
message:
'Withdrawal has been sent for checker approval. The application is unchanged until a checker approves it.'
});
}
this.router.navigate(['../../'], { relativeTo: this.route });
});
}
}
@@ -446,7 +446,16 @@ export class SavingsAccountViewComponent implements OnInit {
if (response.confirm) {
this.savingsService
.executeSavingsAccountCommand(this.savingsAccountData.id, 'postInterest', {})
.subscribe(() => {
.subscribe((commandResponse: any) => {
// Parked in the Checker Inbox rather than executed (HTTP 200 with
// rollbackTransaction: true), so the reload below shows no new interest posting.
if (commandResponse?.rollbackTransaction) {
this.alertService.alert({
type: 'Success',
message:
'Interest posting has been sent for checker approval. No interest is posted until a checker approves it.'
});
}
this.reload();
});
}