feat(savings,deposits,current-accounts): streamline account activation flow
Matches the backend change that stopped auto-depositing money at activation: removes the opening-balance field from every Activate screen (Savings, Current, FD, RD) since funding now happens as a separate deposit afterward, and removes the Digital-Facility step from every Create wizard since every facility starts disabled by default and gets turned on later through Edit Nominee & Features. Also merges Approve+Activate into a single action for Savings, Current, FD and RD accounts -- one click takes the account straight to Active instead of two separate screens.
This commit is contained in:
+2
-31
@@ -12,9 +12,7 @@
|
|||||||
<fa-icon icon="university" class="cca-header__icon"></fa-icon>
|
<fa-icon icon="university" class="cca-header__icon"></fa-icon>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="cca-header__title">Create Current Account</h2>
|
<h2 class="cca-header__title">Create Current Account</h2>
|
||||||
<div class="cca-header__sub">
|
<div class="cca-header__sub">Pick a product, confirm currency and review before submit.</div>
|
||||||
Pick a product, confirm currency, set digital channels and review before submit.
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -78,34 +76,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
||||||
<!-- Tab 3: Digital -->
|
<!-- Tab 3: Preview -->
|
||||||
<mat-tab [disabled]="!currentAccountProductTemplate">
|
|
||||||
<ng-template mat-tab-label>
|
|
||||||
<fa-icon icon="mobile-alt" class="cca-tab__icon"></fa-icon>
|
|
||||||
Digital
|
|
||||||
</ng-template>
|
|
||||||
<div class="cca-tab-body">
|
|
||||||
@if (currentAccountProductTemplate) {
|
|
||||||
<mifosx-current-account-digital-step
|
|
||||||
[currentAccountProductTemplate]="currentAccountProductTemplate"
|
|
||||||
></mifosx-current-account-digital-step>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="cca-actions">
|
|
||||||
<button mat-stroked-button (click)="prev()">
|
|
||||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
|
||||||
{{ 'labels.buttons.Previous' | translate }}
|
|
||||||
</button>
|
|
||||||
<span class="cca-actions__spacer"></span>
|
|
||||||
<button mat-raised-button color="primary" (click)="next()">
|
|
||||||
{{ 'labels.buttons.Next' | translate }}
|
|
||||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</mat-tab>
|
|
||||||
|
|
||||||
<!-- Tab 4: Preview -->
|
|
||||||
<mat-tab [disabled]="!currentAccountProductTemplate">
|
<mat-tab [disabled]="!currentAccountProductTemplate">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<fa-icon icon="eye" class="cca-tab__icon"></fa-icon>
|
<fa-icon icon="eye" class="cca-tab__icon"></fa-icon>
|
||||||
|
|||||||
@@ -57,8 +57,8 @@ export class CreateCurrentAccountComponent {
|
|||||||
currentAccountProductTemplate: any;
|
currentAccountProductTemplate: any;
|
||||||
/** Currently visible wizard tab (0-indexed). */
|
/** Currently visible wizard tab (0-indexed). */
|
||||||
selectedTabIndex = 0;
|
selectedTabIndex = 0;
|
||||||
/** Total wizard tabs — Product, Currency, Digital, Preview. */
|
/** Total wizard tabs — Product, Currency, Preview. */
|
||||||
private readonly totalTabs = 4;
|
private readonly totalTabs = 3;
|
||||||
|
|
||||||
@ViewChild(CurrentAccountDetailsStepComponent, { static: true })
|
@ViewChild(CurrentAccountDetailsStepComponent, { static: true })
|
||||||
currentAccountDetailsStep: CurrentAccountDetailsStepComponent;
|
currentAccountDetailsStep: CurrentAccountDetailsStepComponent;
|
||||||
|
|||||||
-12
@@ -30,18 +30,6 @@
|
|||||||
</mat-error>
|
</mat-error>
|
||||||
}
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field class="flex-fill">
|
|
||||||
<mat-label>Opening Balance</mat-label>
|
|
||||||
<input matInput type="number" [min]="minRequiredOpeningBalance ?? 0" formControlName="openingBalance" />
|
|
||||||
<span matPrefix>₹ </span>
|
|
||||||
@if (minRequiredOpeningBalance) {
|
|
||||||
<mat-hint>Minimum required: ₹{{ minRequiredOpeningBalance }}</mat-hint>
|
|
||||||
}
|
|
||||||
@if (activateCurrentAccountForm.controls.openingBalance.hasError('min')) {
|
|
||||||
<mat-error>Opening balance must be at least ₹{{ minRequiredOpeningBalance ?? 0 }}</mat-error>
|
|
||||||
}
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
</div>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
|
|
||||||
|
|||||||
+1
-11
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** Angular Imports */
|
/** Angular Imports */
|
||||||
import { Component, OnInit, Input, inject } from '@angular/core';
|
import { Component, OnInit, inject } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||||
import { Dates } from 'app/core/utils/dates';
|
import { Dates } from 'app/core/utils/dates';
|
||||||
@@ -36,8 +36,6 @@ export class ActivateCurrentAccountComponent implements OnInit {
|
|||||||
private router = inject(Router);
|
private router = inject(Router);
|
||||||
private settingsService = inject(SettingsService);
|
private settingsService = inject(SettingsService);
|
||||||
|
|
||||||
@Input() minRequiredOpeningBalance: number | null = null;
|
|
||||||
|
|
||||||
/** Minimum date allowed. */
|
/** Minimum date allowed. */
|
||||||
minDate = new Date(2000, 0, 1);
|
minDate = new Date(2000, 0, 1);
|
||||||
/** Maximum date allowed. */
|
/** Maximum date allowed. */
|
||||||
@@ -71,18 +69,10 @@ export class ActivateCurrentAccountComponent implements OnInit {
|
|||||||
* Creates the activate current account form.
|
* Creates the activate current account form.
|
||||||
*/
|
*/
|
||||||
createActivateCurrentAccountForm() {
|
createActivateCurrentAccountForm() {
|
||||||
const minBalance = this.minRequiredOpeningBalance ?? 0;
|
|
||||||
this.activateCurrentAccountForm = this.formBuilder.group({
|
this.activateCurrentAccountForm = this.formBuilder.group({
|
||||||
activatedOnDate: [
|
activatedOnDate: [
|
||||||
'',
|
'',
|
||||||
Validators.required
|
Validators.required
|
||||||
],
|
|
||||||
openingBalance: [
|
|
||||||
minBalance,
|
|
||||||
[
|
|
||||||
Validators.required,
|
|
||||||
Validators.min(minBalance)
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -10,6 +10,7 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<form [formGroup]="approveCurrentAccountForm" (ngSubmit)="submit()">
|
<form [formGroup]="approveCurrentAccountForm" (ngSubmit)="submit()">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
|
<p class="mat-body-2">This approves and activates the account in one step -- it goes straight to Active.</p>
|
||||||
<div class="layout-column">
|
<div class="layout-column">
|
||||||
<mat-form-field (click)="approvedOnDatePicker.open()">
|
<mat-form-field (click)="approvedOnDatePicker.open()">
|
||||||
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
||||||
|
|||||||
+13
-3
@@ -81,8 +81,9 @@ export class ApproveCurrentAccountComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits the form and approves the current account,
|
* Submits the form, approves the current account, then immediately activates it on the same
|
||||||
* if successful redirects to the current account.
|
* date -- Approve and Activate are still two separate Fineract commands underneath (each shows
|
||||||
|
* up in the audit trail), but the officer only sees and clicks through one step.
|
||||||
*/
|
*/
|
||||||
submit() {
|
submit() {
|
||||||
const approveCurrentAccountFormData = this.approveCurrentAccountForm.value;
|
const approveCurrentAccountFormData = this.approveCurrentAccountForm.value;
|
||||||
@@ -98,7 +99,16 @@ export class ApproveCurrentAccountComponent implements OnInit {
|
|||||||
locale
|
locale
|
||||||
};
|
};
|
||||||
this.currentAccountsService.executeCurrentAccountCommand(this.accountId, 'approve', data).subscribe(() => {
|
this.currentAccountsService.executeCurrentAccountCommand(this.accountId, 'approve', data).subscribe(() => {
|
||||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
const activationData = {
|
||||||
|
activatedOnDate: approveCurrentAccountFormData.approvedOnDate,
|
||||||
|
dateFormat,
|
||||||
|
locale
|
||||||
|
};
|
||||||
|
this.currentAccountsService
|
||||||
|
.executeCurrentAccountCommand(this.accountId, 'activate', activationData)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -13,9 +13,7 @@
|
|||||||
<mifosx-reject-current-account></mifosx-reject-current-account>
|
<mifosx-reject-current-account></mifosx-reject-current-account>
|
||||||
}
|
}
|
||||||
@if (actions['Activate']) {
|
@if (actions['Activate']) {
|
||||||
<mifosx-activate-current-account
|
<mifosx-activate-current-account></mifosx-activate-current-account>
|
||||||
[minRequiredOpeningBalance]="accountData?.minRequiredOpeningBalance"
|
|
||||||
></mifosx-activate-current-account>
|
|
||||||
}
|
}
|
||||||
@if (actions['Undo Approval']) {
|
@if (actions['Undo Approval']) {
|
||||||
<mifosx-undo-approval-current-account></mifosx-undo-approval-current-account>
|
<mifosx-undo-approval-current-account></mifosx-undo-approval-current-account>
|
||||||
|
|||||||
-1
@@ -15,7 +15,6 @@
|
|||||||
<h3 class="dig-header__title">Digital & Account Features</h3>
|
<h3 class="dig-header__title">Digital & Account Features</h3>
|
||||||
<p class="dig-header__sub">Toggle the facilities available for this account (as per RBI guidelines)</p>
|
<p class="dig-header__sub">Toggle the facilities available for this account (as per RBI guidelines)</p>
|
||||||
</div>
|
</div>
|
||||||
<span class="dig-header__badge">FROM PRODUCT</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dig-grid">
|
<div class="dig-grid">
|
||||||
|
|||||||
+4
-5
@@ -52,12 +52,11 @@ export class CurrentAccountDigitalStepComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: a new account always starts with every digital facility off, even if the product has
|
||||||
|
// its own defaults configured -- those are enabled deliberately, one at a time, after the
|
||||||
|
// account is created and active, not inherited automatically at opening.
|
||||||
@Input()
|
@Input()
|
||||||
set currentAccountProductTemplate(value: any) {
|
currentAccountProductTemplate: any;
|
||||||
if (!this.hasExistingAccount && value?.accountFacilityConfig) {
|
|
||||||
this.facilityConfig = { ...DEFAULT_FACILITY_CONFIG, ...value.accountFacilityConfig };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get currentAccountDigital() {
|
get currentAccountDigital() {
|
||||||
return { accountFacilityConfig: { ...this.facilityConfig } };
|
return { accountFacilityConfig: { ...this.facilityConfig } };
|
||||||
|
|||||||
+4
-5
@@ -136,12 +136,11 @@ export class CurrentAccountPreviewStepComponent implements OnChanges {
|
|||||||
return this.currentAccountSettingsForm?.getRawValue?.() || this.currentAccount || {};
|
return this.currentAccountSettingsForm?.getRawValue?.() || this.currentAccount || {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Digital facility config as actually captured by a digital step in this wizard -- no fallback
|
||||||
|
* to the product's own defaults, since account creation no longer has a digital step at all and
|
||||||
|
* must not preview facilities the officer never actually chose. */
|
||||||
get digitalFacilityConfig(): any {
|
get digitalFacilityConfig(): any {
|
||||||
return (
|
return this.currentAccountDigital?.accountFacilityConfig ?? null;
|
||||||
this.currentAccountDigital?.accountFacilityConfig ??
|
|
||||||
this.currentAccountProductTemplate?.accountFacilityConfig ??
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasDigitalSection(): boolean {
|
get hasDigitalSection(): boolean {
|
||||||
|
|||||||
+1
@@ -10,6 +10,7 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<form [formGroup]="approveFixedDepositsAccountForm" (ngSubmit)="submit()">
|
<form [formGroup]="approveFixedDepositsAccountForm" (ngSubmit)="submit()">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
|
<p class="mat-body-2">This approves and activates the account in one step -- it goes straight to Active.</p>
|
||||||
<div class="layout-column">
|
<div class="layout-column">
|
||||||
<mat-form-field (click)="approvedOnDatePicker.open()">
|
<mat-form-field (click)="approvedOnDatePicker.open()">
|
||||||
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
||||||
|
|||||||
+13
-3
@@ -81,8 +81,9 @@ export class ApproveFixedDepositsAccountComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits the form and approves the fixed deposit account,
|
* Submits the form, approves the fixed deposit account, then immediately activates it on the
|
||||||
* if successful redirects to the fixed deposit account.
|
* same date -- Approve and Activate are still two separate Fineract commands underneath (each
|
||||||
|
* shows up in the audit trail), but the officer only sees and clicks through one step.
|
||||||
*/
|
*/
|
||||||
submit() {
|
submit() {
|
||||||
const approveFixedDepositsAccountFormData = this.approveFixedDepositsAccountForm.value;
|
const approveFixedDepositsAccountFormData = this.approveFixedDepositsAccountForm.value;
|
||||||
@@ -98,7 +99,16 @@ export class ApproveFixedDepositsAccountComponent implements OnInit {
|
|||||||
locale
|
locale
|
||||||
};
|
};
|
||||||
this.fixedDepositsService.executeFixedDepositsAccountCommand(this.accountId, 'approve', data).subscribe(() => {
|
this.fixedDepositsService.executeFixedDepositsAccountCommand(this.accountId, 'approve', data).subscribe(() => {
|
||||||
this.router.navigate(['../../'], { relativeTo: this.route });
|
const activationData = {
|
||||||
|
activatedOnDate: approveFixedDepositsAccountFormData.approvedOnDate,
|
||||||
|
dateFormat,
|
||||||
|
locale
|
||||||
|
};
|
||||||
|
this.fixedDepositsService
|
||||||
|
.executeFixedDepositsAccountCommand(this.accountId, 'activate', activationData)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.router.navigate(['../../'], { relativeTo: this.route });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -10,6 +10,7 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<form [formGroup]="approveRecurringDepositsAccountForm" (ngSubmit)="submit()">
|
<form [formGroup]="approveRecurringDepositsAccountForm" (ngSubmit)="submit()">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
|
<p class="mat-body-2">This approves and activates the account in one step -- it goes straight to Active.</p>
|
||||||
<div class="layout-column">
|
<div class="layout-column">
|
||||||
<mat-form-field (click)="approvedOnDatePicker.open()">
|
<mat-form-field (click)="approvedOnDatePicker.open()">
|
||||||
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
||||||
|
|||||||
+13
-3
@@ -81,8 +81,9 @@ export class ApproveRecurringDepositsAccountComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits the form and approves the recurring deposit account,
|
* Submits the form, approves the recurring deposit account, then immediately activates it on
|
||||||
* if successful redirects to the recurring deposit account.
|
* the same date -- Approve and Activate are still two separate Fineract commands underneath
|
||||||
|
* (each shows up in the audit trail), but the officer only sees and clicks through one step.
|
||||||
*/
|
*/
|
||||||
submit() {
|
submit() {
|
||||||
const approveRecurringDepositsAccountFormData = this.approveRecurringDepositsAccountForm.value;
|
const approveRecurringDepositsAccountFormData = this.approveRecurringDepositsAccountForm.value;
|
||||||
@@ -103,7 +104,16 @@ export class ApproveRecurringDepositsAccountComponent implements OnInit {
|
|||||||
this.recurringDepositsService
|
this.recurringDepositsService
|
||||||
.executeRecurringDepositsAccountCommand(this.accountId, 'approve', data)
|
.executeRecurringDepositsAccountCommand(this.accountId, 'approve', data)
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.router.navigate(['../../'], { relativeTo: this.route });
|
const activationData = {
|
||||||
|
activatedOnDate: approveRecurringDepositsAccountFormData.approvedOnDate,
|
||||||
|
dateFormat,
|
||||||
|
locale
|
||||||
|
};
|
||||||
|
this.recurringDepositsService
|
||||||
|
.executeRecurringDepositsAccountCommand(this.accountId, 'activate', activationData)
|
||||||
|
.subscribe(() => {
|
||||||
|
this.router.navigate(['../../'], { relativeTo: this.route });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,7 @@
|
|||||||
<fa-icon icon="piggy-bank" class="csa-header__icon"></fa-icon>
|
<fa-icon icon="piggy-bank" class="csa-header__icon"></fa-icon>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="csa-header__title">Create Savings Account</h2>
|
<h2 class="csa-header__title">Create Savings Account</h2>
|
||||||
<div class="csa-header__sub">
|
<div class="csa-header__sub">Pick a product, confirm currency and review before submit.</div>
|
||||||
Pick a product, confirm currency, set digital channels and review before submit.
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -76,33 +74,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
||||||
<!-- Tab 3: Digital -->
|
<!-- Tab 3: Preview / Submit -->
|
||||||
<mat-tab [disabled]="!savingsAccountProductTemplate">
|
|
||||||
<ng-template mat-tab-label>
|
|
||||||
<fa-icon icon="mobile-alt" class="csa-tab__icon"></fa-icon>
|
|
||||||
Digital
|
|
||||||
</ng-template>
|
|
||||||
<div class="csa-tab-body">
|
|
||||||
@if (savingsAccountProductTemplate) {
|
|
||||||
<mifosx-savings-account-digital-step [savingsAccountProductTemplate]="savingsAccountProductTemplate">
|
|
||||||
</mifosx-savings-account-digital-step>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="csa-actions">
|
|
||||||
<button mat-stroked-button (click)="prev()">
|
|
||||||
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
|
||||||
{{ 'labels.buttons.Previous' | translate }}
|
|
||||||
</button>
|
|
||||||
<span class="csa-actions__spacer"></span>
|
|
||||||
<button mat-raised-button color="primary" (click)="next()">
|
|
||||||
{{ 'labels.buttons.Next' | translate }}
|
|
||||||
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</mat-tab>
|
|
||||||
|
|
||||||
<!-- Tab 4: Preview / Submit -->
|
|
||||||
<mat-tab [disabled]="!savingsAccountProductTemplate">
|
<mat-tab [disabled]="!savingsAccountProductTemplate">
|
||||||
<ng-template mat-tab-label>
|
<ng-template mat-tab-label>
|
||||||
<fa-icon icon="eye" class="csa-tab__icon"></fa-icon>
|
<fa-icon icon="eye" class="csa-tab__icon"></fa-icon>
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ export class CreateSavingsAccountComponent {
|
|||||||
savingsAccountProductTemplate: any;
|
savingsAccountProductTemplate: any;
|
||||||
/** Currently visible wizard tab (0-indexed). */
|
/** Currently visible wizard tab (0-indexed). */
|
||||||
selectedTabIndex = 0;
|
selectedTabIndex = 0;
|
||||||
/** Total wizard tabs — Product, Currency, Digital, Preview. */
|
/** Total wizard tabs — Product, Currency, Preview. */
|
||||||
private readonly totalTabs = 4;
|
private readonly totalTabs = 3;
|
||||||
/** Guards against duplicate submissions from a double-click while the create request is in flight. */
|
/** Guards against duplicate submissions from a double-click while the create request is in flight. */
|
||||||
submitting = false;
|
submitting = false;
|
||||||
|
|
||||||
|
|||||||
+3
-13
@@ -14,7 +14,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h2 class="act-savings__title">Activate Savings Account</h2>
|
<h2 class="act-savings__title">Activate Savings Account</h2>
|
||||||
<p class="act-savings__sub">Set the activation date and opening balance to bring this account live.</p>
|
<p class="act-savings__sub">
|
||||||
|
Set the activation date to bring this account live -- funding happens afterwards, as a separate deposit.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -45,18 +47,6 @@
|
|||||||
</mat-error>
|
</mat-error>
|
||||||
}
|
}
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
|
|
||||||
<mat-form-field appearance="outline" class="act-savings__field">
|
|
||||||
<mat-label>Opening Balance</mat-label>
|
|
||||||
<input matInput type="number" [min]="minRequiredOpeningBalance ?? 0" formControlName="openingBalance" />
|
|
||||||
<span matPrefix class="act-savings__prefix">₹ </span>
|
|
||||||
@if (minRequiredOpeningBalance) {
|
|
||||||
<mat-hint>Minimum required: ₹{{ minRequiredOpeningBalance }}</mat-hint>
|
|
||||||
}
|
|
||||||
@if (activateSavingsAccountForm.controls.openingBalance.hasError('min')) {
|
|
||||||
<mat-error>Opening balance must be at least ₹{{ minRequiredOpeningBalance ?? 0 }}</mat-error>
|
|
||||||
}
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="act-savings__actions">
|
<div class="act-savings__actions">
|
||||||
|
|||||||
+1
-14
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/** Angular Imports */
|
/** Angular Imports */
|
||||||
import { Component, OnInit, Input, inject } from '@angular/core';
|
import { Component, OnInit, inject } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||||
import { Dates } from 'app/core/utils/dates';
|
import { Dates } from 'app/core/utils/dates';
|
||||||
@@ -41,8 +41,6 @@ export class ActivateSavingsAccountComponent implements OnInit {
|
|||||||
private router = inject(Router);
|
private router = inject(Router);
|
||||||
private settingsService = inject(SettingsService);
|
private settingsService = inject(SettingsService);
|
||||||
|
|
||||||
@Input() minRequiredOpeningBalance: number | null = null;
|
|
||||||
|
|
||||||
/** Minimum date allowed. */
|
/** Minimum date allowed. */
|
||||||
minDate = new Date(2000, 0, 1);
|
minDate = new Date(2000, 0, 1);
|
||||||
/** Maximum date allowed. */
|
/** Maximum date allowed. */
|
||||||
@@ -76,18 +74,10 @@ export class ActivateSavingsAccountComponent implements OnInit {
|
|||||||
* Creates the activate savings account form.
|
* Creates the activate savings account form.
|
||||||
*/
|
*/
|
||||||
createActivateSavingsAccountForm() {
|
createActivateSavingsAccountForm() {
|
||||||
const minBalance = this.minRequiredOpeningBalance ?? 0;
|
|
||||||
this.activateSavingsAccountForm = this.formBuilder.group({
|
this.activateSavingsAccountForm = this.formBuilder.group({
|
||||||
activatedOnDate: [
|
activatedOnDate: [
|
||||||
'',
|
'',
|
||||||
Validators.required
|
Validators.required
|
||||||
],
|
|
||||||
openingBalance: [
|
|
||||||
minBalance,
|
|
||||||
[
|
|
||||||
Validators.required,
|
|
||||||
Validators.min(minBalance)
|
|
||||||
]
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -109,9 +99,6 @@ export class ActivateSavingsAccountComponent implements OnInit {
|
|||||||
dateFormat,
|
dateFormat,
|
||||||
locale
|
locale
|
||||||
};
|
};
|
||||||
if (data.openingBalance === 0 || data.openingBalance === null) {
|
|
||||||
delete data.openingBalance;
|
|
||||||
}
|
|
||||||
this.savingsService.executeSavingsAccountCommand(this.accountId, 'activate', data).subscribe(() => {
|
this.savingsService.executeSavingsAccountCommand(this.accountId, 'activate', data).subscribe(() => {
|
||||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||||
});
|
});
|
||||||
|
|||||||
+1
@@ -10,6 +10,7 @@
|
|||||||
<mat-card>
|
<mat-card>
|
||||||
<form [formGroup]="approveSavingsAccountForm" (ngSubmit)="submit()">
|
<form [formGroup]="approveSavingsAccountForm" (ngSubmit)="submit()">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
|
<p class="mat-body-2">This approves and activates the account in one step -- it goes straight to Active.</p>
|
||||||
<div class="layout-column">
|
<div class="layout-column">
|
||||||
<mat-form-field (click)="approvedOnDatePicker.open()">
|
<mat-form-field (click)="approvedOnDatePicker.open()">
|
||||||
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
||||||
|
|||||||
+11
-3
@@ -81,8 +81,9 @@ export class ApproveSavingsAccountComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submits the form and approves the saving account,
|
* Submits the form, approves the saving account, then immediately activates it on the same
|
||||||
* if successful redirects to the saving account.
|
* date -- Approve and Activate are still two separate Fineract commands underneath (each shows
|
||||||
|
* up in the audit trail), but the officer only sees and clicks through one step.
|
||||||
*/
|
*/
|
||||||
submit() {
|
submit() {
|
||||||
const approveSavingsAccountFormData = this.approveSavingsAccountForm.value;
|
const approveSavingsAccountFormData = this.approveSavingsAccountForm.value;
|
||||||
@@ -98,7 +99,14 @@ export class ApproveSavingsAccountComponent implements OnInit {
|
|||||||
locale
|
locale
|
||||||
};
|
};
|
||||||
this.savingsService.executeSavingsAccountCommand(this.accountId, 'approve', data).subscribe(() => {
|
this.savingsService.executeSavingsAccountCommand(this.accountId, 'approve', data).subscribe(() => {
|
||||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
const activationData = {
|
||||||
|
activatedOnDate: approveSavingsAccountFormData.approvedOnDate,
|
||||||
|
dateFormat,
|
||||||
|
locale
|
||||||
|
};
|
||||||
|
this.savingsService.executeSavingsAccountCommand(this.accountId, 'activate', activationData).subscribe(() => {
|
||||||
|
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,7 @@
|
|||||||
<mifosx-reject-savings-account></mifosx-reject-savings-account>
|
<mifosx-reject-savings-account></mifosx-reject-savings-account>
|
||||||
}
|
}
|
||||||
@if (actions['Activate']) {
|
@if (actions['Activate']) {
|
||||||
<mifosx-activate-savings-account
|
<mifosx-activate-savings-account></mifosx-activate-savings-account>
|
||||||
[minRequiredOpeningBalance]="accountData?.minRequiredOpeningBalance"
|
|
||||||
></mifosx-activate-savings-account>
|
|
||||||
}
|
}
|
||||||
@if (actions['Undo Approval']) {
|
@if (actions['Undo Approval']) {
|
||||||
<mifosx-undo-approval-savings-account></mifosx-undo-approval-savings-account>
|
<mifosx-undo-approval-savings-account></mifosx-undo-approval-savings-account>
|
||||||
|
|||||||
-1
@@ -15,7 +15,6 @@
|
|||||||
<h3 class="dig-header__title">Digital & Account Features</h3>
|
<h3 class="dig-header__title">Digital & Account Features</h3>
|
||||||
<p class="dig-header__sub">Toggle the facilities available for this account (as per RBI guidelines)</p>
|
<p class="dig-header__sub">Toggle the facilities available for this account (as per RBI guidelines)</p>
|
||||||
</div>
|
</div>
|
||||||
<span class="dig-header__badge">FROM PRODUCT</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dig-grid">
|
<div class="dig-grid">
|
||||||
|
|||||||
+4
-5
@@ -50,12 +50,11 @@ export class SavingsAccountDigitalStepComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: a new account always starts with every digital facility off, even if the product has
|
||||||
|
// its own defaults configured -- those are enabled deliberately, one at a time, after the
|
||||||
|
// account is created and active, not inherited automatically at opening.
|
||||||
@Input()
|
@Input()
|
||||||
set savingsAccountProductTemplate(value: any) {
|
savingsAccountProductTemplate: any;
|
||||||
if (!this.hasExistingAccount && value?.accountFacilityConfig) {
|
|
||||||
this.facilityConfig = { ...DEFAULT_FACILITY_CONFIG, ...value.accountFacilityConfig };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get savingsAccountDigital() {
|
get savingsAccountDigital() {
|
||||||
return { accountFacilityConfig: { ...this.facilityConfig } };
|
return { accountFacilityConfig: { ...this.facilityConfig } };
|
||||||
|
|||||||
+4
-6
@@ -124,13 +124,11 @@ export class SavingsAccountPreviewStepComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns user-modified digital config (from digital step), falling back to product template */
|
/** Digital facility config as actually captured by a digital step in this wizard -- no fallback
|
||||||
|
* to the product's own defaults, since account creation no longer has a digital step at all and
|
||||||
|
* must not preview facilities the officer never actually chose. */
|
||||||
get digitalFacilityConfig(): any {
|
get digitalFacilityConfig(): any {
|
||||||
return (
|
return this.savingsAccountDigital?.accountFacilityConfig ?? null;
|
||||||
this.savingsAccountDigital?.accountFacilityConfig ??
|
|
||||||
this.savingsAccountProductTemplate?.accountFacilityConfig ??
|
|
||||||
null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasDigitalSection(): boolean {
|
get hasDigitalSection(): boolean {
|
||||||
|
|||||||
Reference in New Issue
Block a user