feat: add Current Account module, DIP verification, charges integration, and translations
- Current Account module with full CRUD, transactions, charges, hold/release, block/unblock - Current Products management under Products module - DIP mobile number verification with real API call to /lookup/check - Sanctions verification dialog - Charges support for Current Account (chargeAppliesTo=5) in create/edit - Fixed permissions from SAVINGSACCOUNT to CURRENTACCOUNT across all current account components - Added all missing translation keys for Current Account in en-US.json Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
73aa69ee02
commit
0a32d7135e
+46
@@ -0,0 +1,46 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="activateCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field class="flex-fill" (click)="activatedOnDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Activated On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="activatedOnDatePicker"
|
||||
required
|
||||
formControlName="activatedOnDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="activatedOnDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #activatedOnDatePicker></mat-datepicker>
|
||||
@if (activateCurrentAccountForm.controls.activatedOnDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Activated On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../transactions']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!activateCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Activate Current Account Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-activate-current-account',
|
||||
templateUrl: './activate-current-account.component.html',
|
||||
styleUrls: ['./activate-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
]
|
||||
})
|
||||
export class ActivateCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Activate Current Account form. */
|
||||
activateCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the activate current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createActivateCurrentAccountForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the activate current account form.
|
||||
*/
|
||||
createActivateCurrentAccountForm() {
|
||||
this.activateCurrentAccountForm = this.formBuilder.group({
|
||||
activatedOnDate: [
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and activates the current account,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const activateCurrentAccountFormData = this.activateCurrentAccountForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevActivatedOnDate: Date = this.activateCurrentAccountForm.value.activatedOnDate;
|
||||
if (activateCurrentAccountFormData.activatedOnDate instanceof Date) {
|
||||
activateCurrentAccountFormData.activatedOnDate = this.dateUtils.formatDate(prevActivatedOnDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...activateCurrentAccountFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService.executeCurrentAccountCommand(this.accountId, 'activate', data).subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="currentAccountChargeForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Charge' | translate }}</mat-label>
|
||||
<mat-select required formControlName="chargeId">
|
||||
@for (currentAccountCharge of currentAccountChargeOptions; track currentAccountCharge) {
|
||||
<mat-option [value]="currentAccountCharge.id">
|
||||
{{ currentAccountCharge.name + ' (' + currentAccountCharge.currency.name + ')' }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (currentAccountChargeForm.controls.chargeId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Charge' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (chargeDetails) {
|
||||
<div class="layout-column">
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input type="number" required matInput formControlName="amount" />
|
||||
@if (currentAccountChargeForm.controls.amount.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Charge Calculation' | translate }}</mat-label>
|
||||
<mat-select formControlName="chargeCalculationType">
|
||||
@for (chargeCalculation of chargeDetails.chargeCalculationTypeOptions; track chargeCalculation) {
|
||||
<mat-option [value]="chargeCalculation.id">
|
||||
{{ chargeCalculation.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Charge time type' | translate }}</mat-label>
|
||||
<mat-select formControlName="chargeTimeType">
|
||||
@for (chargeTime of chargeDetails.chargeTimeTypeOptions; track chargeTime) {
|
||||
<mat-option [value]="chargeTime.id">
|
||||
{{ chargeTime.value }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
@if (currentAccountChargeForm.contains('dueDate')) {
|
||||
<mat-form-field (click)="dueDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Due for collection on' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="dueDatePicker"
|
||||
required
|
||||
formControlName="dueDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
@if (currentAccountChargeForm.controls.dueDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Due for collection on' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (currentAccountChargeForm.contains('feeOnMonthDay')) {
|
||||
<mat-form-field (click)="feeOnMonthDayPicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Due On' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="feeOnMonthDayPicker"
|
||||
required
|
||||
formControlName="feeOnMonthDay"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="feeOnMonthDayPicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #feeOnMonthDayPicker></mat-datepicker>
|
||||
@if (currentAccountChargeForm.controls.feeOnMonthDay.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Due Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (currentAccountChargeForm.contains('feeInterval')) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Repeats Every' | translate }}</mat-label>
|
||||
<input matInput formControlName="feeInterval" />
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<mat-card-actions class="layout-row layout-xs-column layout-align-center gap-5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../transactions']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!currentAccountChargeForm.valid">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</mat-card-content>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
width: 37rem;
|
||||
}
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* 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 {
|
||||
UntypedFormGroup,
|
||||
UntypedFormBuilder,
|
||||
Validators,
|
||||
UntypedFormControl,
|
||||
ReactiveFormsModule
|
||||
} from '@angular/forms';
|
||||
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from '../../current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Add Current Account Charge component.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-add-charge-current-account',
|
||||
templateUrl: './add-charge-current-account.component.html',
|
||||
styleUrls: ['./add-charge-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
]
|
||||
})
|
||||
export class AddChargeCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private dateUtils = inject(Dates);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum Due Date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum Due Date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Add Current Account Charge form. */
|
||||
currentAccountChargeForm: UntypedFormGroup;
|
||||
/** current account charge options. */
|
||||
currentAccountChargeOptions: any;
|
||||
/** current account Id of the current account. */
|
||||
currentAccountId: string;
|
||||
/** charge details */
|
||||
chargeDetails: any;
|
||||
|
||||
/**
|
||||
* Retrieves charge template data from `resolve`
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {SettingsService} settingsService Settings Service
|
||||
*/
|
||||
constructor() {
|
||||
this.route.data.subscribe((data: { currentAccountActionData: any }) => {
|
||||
this.currentAccountChargeOptions = data.currentAccountActionData.chargeOptions;
|
||||
});
|
||||
this.currentAccountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Current Account Charge form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createCurrentAccountChargeForm();
|
||||
this.buildDependencies();
|
||||
}
|
||||
|
||||
buildDependencies() {
|
||||
this.currentAccountChargeForm.controls.chargeId.valueChanges.subscribe((chargeId) => {
|
||||
this.currentAccountsService.getChargeTemplate(chargeId).subscribe((data: any) => {
|
||||
this.chargeDetails = data;
|
||||
const chargeTimeType = data.chargeTimeType.id;
|
||||
if (
|
||||
data.chargeTimeType.value === 'Withdrawal Fee' ||
|
||||
data.chargeTimeType.value === 'Current Account No Activity Fee'
|
||||
) {
|
||||
this.chargeDetails.dueDateNotRequired = true;
|
||||
}
|
||||
if (data.chargeTimeType.value === 'Annual Fee' || data.chargeTimeType.value === 'Monthly Fee') {
|
||||
this.chargeDetails.chargeTimeTypeAnnualOrMonth = true;
|
||||
}
|
||||
if (!this.chargeDetails.dueDateNotRequired && !this.chargeDetails.chargeTimeTypeAnnualOrMonth) {
|
||||
this.currentAccountChargeForm.addControl('dueDate', new UntypedFormControl('', Validators.required));
|
||||
} else {
|
||||
this.currentAccountChargeForm.removeControl('dueDate');
|
||||
}
|
||||
if (!this.chargeDetails.dueDateNotRequired && this.chargeDetails.chargeTimeTypeAnnualOrMonth) {
|
||||
this.currentAccountChargeForm.addControl('feeOnMonthDay', new UntypedFormControl('', Validators.required));
|
||||
} else {
|
||||
this.currentAccountChargeForm.removeControl('feeOnMonthDay');
|
||||
}
|
||||
if (chargeTimeType.value === 'Monthly Fee') {
|
||||
this.currentAccountChargeForm.addControl(
|
||||
'feeInterval',
|
||||
new UntypedFormControl(data.feeInterval, Validators.required)
|
||||
);
|
||||
} else {
|
||||
this.currentAccountChargeForm.removeControl('feeInterval');
|
||||
}
|
||||
this.currentAccountChargeForm.patchValue({
|
||||
amount: data.amount,
|
||||
chargeCalculationType: data.chargeCalculationType.id,
|
||||
chargeTimeType: data.chargeTimeType.id
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Current Account Charge form.
|
||||
*/
|
||||
createCurrentAccountChargeForm() {
|
||||
this.currentAccountChargeForm = this.formBuilder.group({
|
||||
chargeId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
amount: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
chargeCalculationType: [{ value: '', disabled: true }],
|
||||
chargeTimeType: [{ value: '', disabled: true }]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits current account charge.
|
||||
*/
|
||||
submit() {
|
||||
const currentAccountCharge = this.currentAccountChargeForm.value;
|
||||
currentAccountCharge.locale = this.settingsService.language.code;
|
||||
if (!currentAccountCharge.feeInterval) {
|
||||
currentAccountCharge.feeInterval = this.chargeDetails.feeInterval;
|
||||
}
|
||||
if (this.chargeDetails.dueDateNotRequired !== true) {
|
||||
if (this.chargeDetails.chargeTimeTypeAnnualOrMonth) {
|
||||
const monthDayFormat = 'MMMM-dd'; // TODO: Update once language and date settings are setup
|
||||
currentAccountCharge.monthDayFormat = monthDayFormat;
|
||||
if (currentAccountCharge.feeOnMonthDay) {
|
||||
const prevDate = this.currentAccountChargeForm.value.feeOnMonthDay;
|
||||
currentAccountCharge.feeOnMonthDay = this.dateUtils.formatDate(prevDate, monthDayFormat);
|
||||
}
|
||||
} else {
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
currentAccountCharge.dateFormat = dateFormat;
|
||||
if (currentAccountCharge.dueDate) {
|
||||
const prevDate = this.currentAccountChargeForm.value.dueDate;
|
||||
currentAccountCharge.dueDate = this.dateUtils.formatDate(prevDate, dateFormat);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.currentAccountsService
|
||||
.createCurrentAccountCharge(this.currentAccountId, 'charges', currentAccountCharge)
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="applyAnnualFeesForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="dueDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Annual Fees Transaction Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="dueDatePicker"
|
||||
required
|
||||
formControlName="dueDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
@if (applyAnnualFeesForm.controls.dueDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Due Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Amount' | translate }}</mat-label>
|
||||
<input type="number" formControlName="amount" required matInput />
|
||||
@if (applyAnnualFeesForm.controls.amount.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Amount' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!applyAnnualFeesForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Apply Annual Fees Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-apply-annual-fees-current-account',
|
||||
templateUrl: './apply-annual-fees-current-account.component.html',
|
||||
styleUrls: ['./apply-annual-fees-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
]
|
||||
})
|
||||
export class ApplyAnnualFeesCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Apply annual fees form. */
|
||||
applyAnnualFeesForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
/** Annual Fees charge Id */
|
||||
chargeId: any;
|
||||
/** Current Account Data */
|
||||
currentAccountData: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
this.route.data.subscribe((data: { currentAccountActionData: any }) => {
|
||||
this.currentAccountData = data.currentAccountActionData;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the apply annual fees form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createApplyAnnualFeesForm();
|
||||
this.applyCharge();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the apply annual fees form.
|
||||
*/
|
||||
createApplyAnnualFeesForm() {
|
||||
this.applyAnnualFeesForm = this.formBuilder.group({
|
||||
dueDate: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
amount: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retireves apply annual fees charge for ID and amount.
|
||||
*/
|
||||
applyCharge() {
|
||||
const charges: any[] = this.currentAccountData.charges;
|
||||
charges.forEach((charge: any) => {
|
||||
if (charge.name === 'Annual fee - INR') {
|
||||
this.chargeId = charge.id;
|
||||
this.applyAnnualFeesForm.get('amount').patchValue(charge.amount);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and applies the annual fees,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const applyAnnualFeesFormData = this.applyAnnualFeesForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevApprovedOnDate: Date = this.applyAnnualFeesForm.value.dueDate;
|
||||
if (applyAnnualFeesFormData.dueDate instanceof Date) {
|
||||
applyAnnualFeesFormData.dueDate = this.dateUtils.formatDate(prevApprovedOnDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...applyAnnualFeesFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountChargesCommand(this.accountId, 'paycharge', data, this.chargeId)
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['../../'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="approveCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="approvedOnDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Approved On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="approvedOnDatePicker"
|
||||
required
|
||||
formControlName="approvedOnDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="approvedOnDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #approvedOnDatePicker></mat-datepicker>
|
||||
@if (approveCurrentAccountForm.controls.approvedOnDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Approved On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!approveCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Approve Current Account Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-approve-current-account',
|
||||
templateUrl: './approve-current-account.component.html',
|
||||
styleUrls: ['./approve-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
})
|
||||
export class ApproveCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Approve Current Account form. */
|
||||
approveCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the approve current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createApproveCurrentAccountForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the approve current account form.
|
||||
*/
|
||||
createApproveCurrentAccountForm() {
|
||||
this.approveCurrentAccountForm = this.formBuilder.group({
|
||||
approvedOnDate: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
note: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and approves the current account,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const approveCurrentAccountFormData = this.approveCurrentAccountForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevApprovedOnDate: Date = this.approveCurrentAccountForm.value.approvedOnDate;
|
||||
if (approveCurrentAccountFormData.approvedOnDate instanceof Date) {
|
||||
approveCurrentAccountFormData.approvedOnDate = this.dateUtils.formatDate(prevApprovedOnDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...approveCurrentAccountFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService.executeCurrentAccountCommand(this.accountId, 'approve', data).subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="closeCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="closedOnDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Closed On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="closedOnDatePicker"
|
||||
required
|
||||
formControlName="closedOnDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="closedOnDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #closedOnDatePicker></mat-datepicker>
|
||||
@if (closeCurrentAccountForm.controls.closedOnDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Closed On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-checkbox class="m-b-25 m-t-15" formControlName="withdrawBalance">
|
||||
{{ 'labels.inputs.Withdraw Balance' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<mat-checkbox formControlName="postInterestValidationOnClosure">
|
||||
{{ 'labels.inputs.Is Interest Posting required on closure date' | translate }}?
|
||||
</mat-checkbox>
|
||||
|
||||
@if (closeCurrentAccountForm.controls['withdrawBalance'].value) {
|
||||
<div class="layout-column">
|
||||
@if (closeCurrentAccountForm.controls['amount']) {
|
||||
<mat-form-field class="m-t-20">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Amount' | translate }}</mat-label>
|
||||
<input type="number" required matInput formControlName="amount" />
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (closeCurrentAccountForm.controls['paymentTypeId']) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Payment Type' | translate }}</mat-label>
|
||||
<mat-select formControlName="paymentTypeId">
|
||||
@for (paymentType of paymentTypeOptions; track paymentType) {
|
||||
<mat-option [value]="paymentType.id">
|
||||
{{ paymentType.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
}
|
||||
<div class="flex-fill">
|
||||
<span class="expandcollapsebutton m-l-10 m-t-40 flex-75" (click)="addPaymentDetails()">
|
||||
<mat-slide-toggle>
|
||||
<div [className]="showPaymentDetails ? 'enabled' : 'disabled'">
|
||||
<span class="m-l-10">{{ 'labels.inputs.Show Payment Details' | translate }}</span>
|
||||
</div>
|
||||
</mat-slide-toggle>
|
||||
</span>
|
||||
</div>
|
||||
@if (closeCurrentAccountForm.controls['accountNumber']) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Account Number' | translate }}</mat-label>
|
||||
<input type="number" formControlName="accountNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (closeCurrentAccountForm.controls['checkNumber']) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Cheque' | translate }}</mat-label>
|
||||
<input type="number" formControlName="checkNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (closeCurrentAccountForm.controls['routingCode']) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Routing Code' | translate }}</mat-label>
|
||||
<input formControlName="routingCode" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (closeCurrentAccountForm.controls['receiptNumber']) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Receipt Number' | translate }}</mat-label>
|
||||
<input formControlName="receiptNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
@if (closeCurrentAccountForm.controls['bankNumber']) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Bank' | translate }}</mat-label>
|
||||
<input formControlName="bankNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="warn" [disabled]="!closeCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* 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 {
|
||||
UntypedFormGroup,
|
||||
UntypedFormBuilder,
|
||||
Validators,
|
||||
UntypedFormControl,
|
||||
ReactiveFormsModule
|
||||
} from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatSlideToggle } from '@angular/material/slide-toggle';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Close Current Account Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-close-current-account',
|
||||
templateUrl: './close-current-account.component.html',
|
||||
styleUrls: ['./close-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatCheckbox,
|
||||
MatSlideToggle,
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
})
|
||||
export class CloseCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Close Current Account form. */
|
||||
closeCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
/** Flag to enable payment details fields. */
|
||||
addPaymentDetailsFlag = false;
|
||||
/** Payment Type Options */
|
||||
paymentTypeOptions: any;
|
||||
/** Transaction Amount */
|
||||
transactionAmount: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.route.data.subscribe((data: { currentAccountActionData: any }) => {
|
||||
this.paymentTypeOptions = data.currentAccountActionData[0].paymentTypeOptions;
|
||||
this.transactionAmount = data.currentAccountActionData[1].summary.accountBalance;
|
||||
});
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the close current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createCloseCurrentAccountForm();
|
||||
this.buildDependencies();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the close current account form.
|
||||
*/
|
||||
createCloseCurrentAccountForm() {
|
||||
this.closeCurrentAccountForm = this.formBuilder.group({
|
||||
closedOnDate: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
withdrawBalance: [false],
|
||||
postInterestValidationOnClosure: [false],
|
||||
note: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to value changes of withdraw balance checkbox.
|
||||
*/
|
||||
buildDependencies() {
|
||||
this.closeCurrentAccountForm.get('withdrawBalance').valueChanges.subscribe((value: boolean) => {
|
||||
if (value) {
|
||||
this.closeCurrentAccountForm.addControl(
|
||||
'amount',
|
||||
new UntypedFormControl({ value: this.transactionAmount, disabled: true })
|
||||
);
|
||||
this.closeCurrentAccountForm.addControl('paymentTypeId', new UntypedFormControl(''));
|
||||
} else {
|
||||
this.closeCurrentAccountForm.removeControl('amount');
|
||||
this.closeCurrentAccountForm.removeControl('paymentTypeId');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add payment detail fields to the UI.
|
||||
*/
|
||||
addPaymentDetails() {
|
||||
this.addPaymentDetailsFlag = !this.addPaymentDetailsFlag;
|
||||
if (this.addPaymentDetailsFlag) {
|
||||
this.closeCurrentAccountForm.addControl('accountNumber', new UntypedFormControl(''));
|
||||
this.closeCurrentAccountForm.addControl('checkNumber', new UntypedFormControl(''));
|
||||
this.closeCurrentAccountForm.addControl('routingCode', new UntypedFormControl(''));
|
||||
this.closeCurrentAccountForm.addControl('receiptNumber', new UntypedFormControl(''));
|
||||
this.closeCurrentAccountForm.addControl('bankNumber', new UntypedFormControl(''));
|
||||
} else {
|
||||
this.closeCurrentAccountForm.removeControl('accountNumber');
|
||||
this.closeCurrentAccountForm.removeControl('checkNumber');
|
||||
this.closeCurrentAccountForm.removeControl('routingCode');
|
||||
this.closeCurrentAccountForm.removeControl('receiptNumber');
|
||||
this.closeCurrentAccountForm.removeControl('bankNumber');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and closes the current account,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const closeCurrentAccountFormData = this.closeCurrentAccountForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevClosedOnDate: Date = this.closeCurrentAccountForm.value.closedOnDate;
|
||||
if (closeCurrentAccountFormData.closedOnDate instanceof Date) {
|
||||
closeCurrentAccountFormData.closedOnDate = this.dateUtils.formatDate(prevClosedOnDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...closeCurrentAccountFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService.executeCurrentAccountCommand(this.accountId, 'close', data).subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
@if (actions['Approve']) {
|
||||
<mifosx-approve-current-account></mifosx-approve-current-account>
|
||||
}
|
||||
@if (actions['Reject']) {
|
||||
<mifosx-reject-current-account></mifosx-reject-current-account>
|
||||
}
|
||||
@if (actions['Activate']) {
|
||||
<mifosx-activate-current-account></mifosx-activate-current-account>
|
||||
}
|
||||
@if (actions['Undo Approval']) {
|
||||
<mifosx-undo-approval-current-account></mifosx-undo-approval-current-account>
|
||||
}
|
||||
@if (actions['Post Interest As On']) {
|
||||
<mifosx-post-interest-as-on-current-account></mifosx-post-interest-as-on-current-account>
|
||||
}
|
||||
@if (actions['Assign Staff']) {
|
||||
<mifosx-current-account-assign-staff></mifosx-current-account-assign-staff>
|
||||
}
|
||||
@if (actions['Unassign Staff']) {
|
||||
<mifosx-current-account-unassign-staff></mifosx-current-account-unassign-staff>
|
||||
}
|
||||
@if (actions['Withdrawn by Client']) {
|
||||
<mifosx-withdraw-by-client-current-account></mifosx-withdraw-by-client-current-account>
|
||||
}
|
||||
@if (actions['Add Charge']) {
|
||||
<mifosx-add-charge-current-account></mifosx-add-charge-current-account>
|
||||
}
|
||||
@if (actions['Withdrawal'] || actions['Deposit']) {
|
||||
<mifosx-current-account-transactions></mifosx-current-account-transactions>
|
||||
}
|
||||
@if (actions['Close']) {
|
||||
<mifosx-close-current-account></mifosx-close-current-account>
|
||||
}
|
||||
@if (actions['Apply Annual Fees']) {
|
||||
<mifosx-apply-annual-fees-current-account></mifosx-apply-annual-fees-current-account>
|
||||
}
|
||||
@if (actions['Hold Amount'] || actions['Block Account'] || actions['Block Deposit'] || actions['Block Withdrawal']) {
|
||||
<mifosx-manage-current-account [currency]="currency"> </mifosx-manage-current-account>
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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, inject } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Currency } from 'app/shared/models/general.model';
|
||||
import { ApproveCurrentAccountComponent } from './approve-current-account/approve-current-account.component';
|
||||
import { RejectCurrentAccountComponent } from './reject-current-account/reject-current-account.component';
|
||||
import { ActivateCurrentAccountComponent } from './activate-current-account/activate-current-account.component';
|
||||
import { UndoApprovalCurrentAccountComponent } from './undo-approval-current-account/undo-approval-current-account.component';
|
||||
import { PostInterestAsOnCurrentAccountComponent } from './post-interest-as-on-current-account/post-interest-as-on-current-account.component';
|
||||
import { CurrentAccountAssignStaffComponent } from './current-account-assign-staff/current-account-assign-staff.component';
|
||||
import { CurrentAccountUnassignStaffComponent } from './current-account-unassign-staff/current-account-unassign-staff.component';
|
||||
import { WithdrawByClientCurrentAccountComponent } from './withdraw-by-client-current-account/withdraw-by-client-current-account.component';
|
||||
import { AddChargeCurrentAccountComponent } from './add-charge-current-account/add-charge-current-account.component';
|
||||
import { CurrentAccountTransactionsComponent } from './current-account-transactions/current-account-transactions.component';
|
||||
import { CloseCurrentAccountComponent } from './close-current-account/close-current-account.component';
|
||||
import { ApplyAnnualFeesCurrentAccountComponent } from './apply-annual-fees-current-account/apply-annual-fees-current-account.component';
|
||||
import { ManageCurrentAccountComponent } from './manage-current-account/manage-current-account.component';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Current account actions component.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-current-account-account-actions',
|
||||
templateUrl: './current-account-actions.component.html',
|
||||
styleUrls: ['./current-account-actions.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
ApproveCurrentAccountComponent,
|
||||
RejectCurrentAccountComponent,
|
||||
ActivateCurrentAccountComponent,
|
||||
UndoApprovalCurrentAccountComponent,
|
||||
PostInterestAsOnCurrentAccountComponent,
|
||||
CurrentAccountAssignStaffComponent,
|
||||
CurrentAccountUnassignStaffComponent,
|
||||
WithdrawByClientCurrentAccountComponent,
|
||||
AddChargeCurrentAccountComponent,
|
||||
CurrentAccountTransactionsComponent,
|
||||
CloseCurrentAccountComponent,
|
||||
ApplyAnnualFeesCurrentAccountComponent,
|
||||
ManageCurrentAccountComponent
|
||||
]
|
||||
})
|
||||
export class CurrentAccountActionsComponent {
|
||||
private route = inject(ActivatedRoute);
|
||||
|
||||
/** Flag object to store possible actions and render appropriate UI to the user */
|
||||
actions: {
|
||||
Approve: boolean;
|
||||
Reject: boolean;
|
||||
Withdrawal: boolean;
|
||||
Deposit: boolean;
|
||||
Activate: boolean;
|
||||
Close: boolean;
|
||||
'Undo Approval': boolean;
|
||||
'Post Interest As On': boolean;
|
||||
'Assign Staff': boolean;
|
||||
'Add Charge': boolean;
|
||||
'Unassign Staff': boolean;
|
||||
'Withdrawn by Client': boolean;
|
||||
'Apply Annual Fees': boolean;
|
||||
'Hold Amount': boolean;
|
||||
'Block Account': boolean;
|
||||
'Unblock Account': boolean;
|
||||
'Block Deposit': boolean;
|
||||
'Unblock Deposit': boolean;
|
||||
'Block Withdrawal': boolean;
|
||||
'Unblock Withdrawal': boolean;
|
||||
} = {
|
||||
Approve: false,
|
||||
Reject: false,
|
||||
Withdrawal: false,
|
||||
Deposit: false,
|
||||
Activate: false,
|
||||
Close: false,
|
||||
'Undo Approval': false,
|
||||
'Post Interest As On': false,
|
||||
'Assign Staff': false,
|
||||
'Add Charge': false,
|
||||
'Unassign Staff': false,
|
||||
'Withdrawn by Client': false,
|
||||
'Apply Annual Fees': false,
|
||||
'Hold Amount': false,
|
||||
'Block Account': false,
|
||||
'Unblock Account': false,
|
||||
'Block Deposit': false,
|
||||
'Unblock Deposit': false,
|
||||
'Block Withdrawal': false,
|
||||
'Unblock Withdrawal': false
|
||||
};
|
||||
|
||||
currency: Currency;
|
||||
|
||||
/**
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
*/
|
||||
constructor() {
|
||||
this.route.data.subscribe((data: { currentAccountActionData: any }) => {
|
||||
if (data.currentAccountActionData) {
|
||||
this.currency = data.currentAccountActionData.currency;
|
||||
}
|
||||
});
|
||||
const name = this.route.snapshot.params['name'] as string;
|
||||
if (name in this.actions) {
|
||||
this.actions[name as keyof typeof this.actions] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="currentAccountAssignStaffForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field class="flex-48">
|
||||
<mat-label>{{ 'labels.inputs.To Current Account Officer' | translate }}</mat-label>
|
||||
<mat-select formControlName="toCurrentAccountOfficerId">
|
||||
@for (officer of fieldOfficerData; track officer) {
|
||||
<mat-option [value]="officer.id">
|
||||
{{ officer.displayName }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (currentAccountAssignStaffForm.controls.toCurrentAccountOfficerId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.To Current Account Officer' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field (click)="assignmentDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Assignment Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="assignmentDatePicker"
|
||||
required
|
||||
formControlName="assignmentDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="assignmentDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #assignmentDatePicker></mat-datepicker>
|
||||
@if (currentAccountAssignStaffForm.controls.assignmentDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Assignment Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!currentAccountAssignStaffForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, Validators } from '@angular/forms';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Current Account Assign Staff Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-current-account-account-assign-staff',
|
||||
templateUrl: './current-account-assign-staff.component.html',
|
||||
styleUrls: ['./current-account-assign-staff.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
]
|
||||
})
|
||||
export class CurrentAccountAssignStaffComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Current Account Assign Staff form. */
|
||||
currentAccountAssignStaffForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
/** Field Officer Data */
|
||||
fieldOfficerData: any;
|
||||
/** Current Account Data */
|
||||
currentAccountData: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
this.route.data.subscribe((data: { currentAccountActionData: any }) => {
|
||||
this.currentAccountData = data.currentAccountActionData;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the current account assign staff form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.fieldOfficerData = this.currentAccountData.fieldOfficerOptions;
|
||||
this.createCurrentAccountAssignStaffForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the current account assign staff form.
|
||||
*/
|
||||
createCurrentAccountAssignStaffForm() {
|
||||
this.currentAccountAssignStaffForm = this.formBuilder.group({
|
||||
toCurrentAccountOfficerId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
assignmentDate: [
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and assigns staff the current account,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const formValue = this.currentAccountAssignStaffForm.value;
|
||||
const assignmentDate =
|
||||
formValue.assignmentDate instanceof Date
|
||||
? this.dateUtils.formatDate(formValue.assignmentDate, dateFormat)
|
||||
: formValue.assignmentDate;
|
||||
const data = {
|
||||
toCurrentAccountOfficerId: formValue.toCurrentAccountOfficerId,
|
||||
assignmentDate,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountCommand(this.accountId, 'assignCurrentAccountOfficer', data)
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
@if (transactionType.withdrawal) {
|
||||
<mat-card-title class="form-heading">
|
||||
{{ 'labels.heading.Withdraw Money From Current Account' | translate }}
|
||||
</mat-card-title>
|
||||
}
|
||||
@if (transactionType.deposit) {
|
||||
<mat-card-title class="form-heading">
|
||||
{{ 'labels.heading.Deposit Money To Current Account' | translate }}
|
||||
</mat-card-title>
|
||||
}
|
||||
|
||||
<form [formGroup]="currentAccountTransactionForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="dueDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="dueDatePicker"
|
||||
formControlName="transactionDate"
|
||||
required
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #dueDatePicker></mat-datepicker>
|
||||
@if (currentAccountTransactionForm.controls.transactionDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transaction Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mifosx-input-amount
|
||||
[currency]="currency"
|
||||
[isRequired]="true"
|
||||
[inputFormControl]="currentAccountTransactionForm.controls.transactionAmount"
|
||||
[inputLabel]="'Transaction Amount'"
|
||||
>
|
||||
</mifosx-input-amount>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Payment Type' | translate }}</mat-label>
|
||||
<mat-select required formControlName="paymentTypeId">
|
||||
@for (paymentType of paymentTypeOptions; track paymentType) {
|
||||
<mat-option [value]="paymentType.id">
|
||||
{{ paymentType.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (currentAccountTransactionForm.controls.paymentTypeId.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Payment Type' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<div class="flex-fill">
|
||||
<span class="expandcollapsebutton m-l-10 m-t-40 flex-75" (click)="addPaymentDetails()">
|
||||
<mat-slide-toggle>
|
||||
<div [className]="addPaymentDetailsFlag ? 'enabled' : 'disabled'">
|
||||
<span class="m-l-10">{{ 'labels.inputs.Show Payment Details' | translate }}</span>
|
||||
</div>
|
||||
</mat-slide-toggle>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@if (addPaymentDetailsFlag) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Account Number' | translate }}</mat-label>
|
||||
<input type="number" formControlName="accountNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (addPaymentDetailsFlag) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Cheque' | translate }}</mat-label>
|
||||
<input type="number" formControlName="checkNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (addPaymentDetailsFlag) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Routing Code' | translate }}</mat-label>
|
||||
<input formControlName="routingCode" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (addPaymentDetailsFlag) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Receipt Number' | translate }}</mat-label>
|
||||
<input formControlName="receiptNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (addPaymentDetailsFlag) {
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Bank' | translate }}</mat-label>
|
||||
<input formControlName="bankNumber" matInput />
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Notes' | translate }}</mat-label>
|
||||
<textarea formControlName="note" matInput cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-card-actions class="layout-row layout-xs-column layout-align-center gap-5px">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../transactions']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!currentAccountTransactionForm.valid">
|
||||
{{ 'labels.buttons.Submit' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.expandcollapsebutton {
|
||||
margin-top: -7px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
|
||||
.right-input {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.right-label {
|
||||
padding-right: 25px !important;
|
||||
}
|
||||
|
||||
.form-heading {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* 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 {
|
||||
UntypedFormGroup,
|
||||
UntypedFormBuilder,
|
||||
Validators,
|
||||
UntypedFormControl,
|
||||
ReactiveFormsModule
|
||||
} from '@angular/forms';
|
||||
import { Router, ActivatedRoute, RouterLink } from '@angular/router';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from '../../current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { Currency } from 'app/shared/models/general.model';
|
||||
import { InputAmountComponent } from '../../../shared/input-amount/input-amount.component';
|
||||
import { MatSlideToggle } from '@angular/material/slide-toggle';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Create current account transactions component.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-current-account-transactions',
|
||||
templateUrl: './current-account-transactions.component.html',
|
||||
styleUrls: ['./current-account-transactions.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
InputAmountComponent,
|
||||
MatSlideToggle,
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
})
|
||||
export class CurrentAccountTransactionsComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private dateUtils = inject(Dates);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum Due Date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum Due Date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Current account transaction form. */
|
||||
currentAccountTransactionForm: UntypedFormGroup;
|
||||
/** current account transaction payment options. */
|
||||
paymentTypeOptions: {
|
||||
id: number;
|
||||
name: string;
|
||||
description: string;
|
||||
isCashPayment: boolean;
|
||||
position: number;
|
||||
}[];
|
||||
/** Flag to enable payment details fields. */
|
||||
addPaymentDetailsFlag: Boolean = false;
|
||||
/** transaction type flag to render required UI */
|
||||
transactionType: { deposit: boolean; withdrawal: boolean } = { deposit: false, withdrawal: false };
|
||||
/** transaction command for submit request */
|
||||
transactionCommand: string;
|
||||
/** current account's Id */
|
||||
currentAccountId: string;
|
||||
currency: Currency | null = null;
|
||||
|
||||
/**
|
||||
* Retrieves the Current Account transaction template data from `resolve`.
|
||||
* @param {FormBuilder} formBuilder Form Builder.
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service.
|
||||
* @param {ActivatedRoute} route Activated Route.
|
||||
* @param {Dates} dateUtils Date Utils.
|
||||
* @param {Router} router Router for navigation.
|
||||
* @param {SettingsService} settingsService Settings Service
|
||||
*/
|
||||
constructor() {
|
||||
this.route.data.subscribe((data: { currentAccountActionData: any }) => {
|
||||
this.paymentTypeOptions = data.currentAccountActionData.paymentTypeOptions;
|
||||
if (data.currentAccountActionData.currency) {
|
||||
this.currency = data.currentAccountActionData.currency;
|
||||
}
|
||||
});
|
||||
this.transactionCommand = this.route.snapshot.params['name'].toLowerCase();
|
||||
this.transactionType[this.transactionCommand as 'deposit' | 'withdrawal'] = true;
|
||||
this.currentAccountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Current Account account transaction form when component loads.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createCurrentAccountTransactionForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to create the Current Account Transaction Form.
|
||||
*/
|
||||
createCurrentAccountTransactionForm() {
|
||||
this.currentAccountTransactionForm = this.formBuilder.group({
|
||||
transactionDate: [
|
||||
this.settingsService.businessDate,
|
||||
Validators.required
|
||||
],
|
||||
transactionAmount: [
|
||||
0,
|
||||
Validators.required
|
||||
],
|
||||
paymentTypeId: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
note: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to add payment detail fields to the UI.
|
||||
*/
|
||||
addPaymentDetails() {
|
||||
this.addPaymentDetailsFlag = !this.addPaymentDetailsFlag;
|
||||
if (this.addPaymentDetailsFlag) {
|
||||
this.currentAccountTransactionForm.addControl('accountNumber', new UntypedFormControl(''));
|
||||
this.currentAccountTransactionForm.addControl('checkNumber', new UntypedFormControl(''));
|
||||
this.currentAccountTransactionForm.addControl('routingCode', new UntypedFormControl(''));
|
||||
this.currentAccountTransactionForm.addControl('receiptNumber', new UntypedFormControl(''));
|
||||
this.currentAccountTransactionForm.addControl('bankNumber', new UntypedFormControl(''));
|
||||
} else {
|
||||
this.currentAccountTransactionForm.removeControl('accountNumber');
|
||||
this.currentAccountTransactionForm.removeControl('checkNumber');
|
||||
this.currentAccountTransactionForm.removeControl('routingCode');
|
||||
this.currentAccountTransactionForm.removeControl('receiptNumber');
|
||||
this.currentAccountTransactionForm.removeControl('bankNumber');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to submit the transaction details.
|
||||
*/
|
||||
submit() {
|
||||
const currentAccountTransactionFormData = this.currentAccountTransactionForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevTransactionDate: Date = this.currentAccountTransactionForm.value.transactionDate;
|
||||
if (currentAccountTransactionFormData.transactionDate instanceof Date) {
|
||||
currentAccountTransactionFormData.transactionDate = this.dateUtils.formatDate(prevTransactionDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...currentAccountTransactionFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
data['transactionAmount'] = data['transactionAmount'] * 1;
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountTransactionsCommand(this.currentAccountId, this.transactionCommand, data)
|
||||
.subscribe((res) => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="currentAccountUnassignStaffForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<mat-form-field class="flex-fill" (click)="unassignedDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Unassignment Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="unassignedDatePicker"
|
||||
required
|
||||
formControlName="unassignedDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="unassignedDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #unassignedDatePicker></mat-datepicker>
|
||||
@if (currentAccountUnassignStaffForm.controls.unassignedDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Unassignment Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!currentAccountUnassignStaffForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* 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, Input, 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';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Current Account Unassign Staff Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-current-account-account-unassign-staff',
|
||||
templateUrl: './current-account-unassign-staff.component.html',
|
||||
styleUrls: ['./current-account-unassign-staff.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
]
|
||||
})
|
||||
export class CurrentAccountUnassignStaffComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Current Account Unassign Staff form. */
|
||||
currentAccountUnassignStaffForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the current account unassign staff form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createCurrentAccountUnassignStaffForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the current account unassign staff form.
|
||||
*/
|
||||
createCurrentAccountUnassignStaffForm() {
|
||||
this.currentAccountUnassignStaffForm = this.formBuilder.group({
|
||||
unassignedDate: [
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and unassigns staff of the current account,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const currentAccountUnassignStaffFormData = this.currentAccountUnassignStaffForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevUnassignmentDate: Date = this.currentAccountUnassignStaffForm.value.unassignedDate;
|
||||
if (currentAccountUnassignStaffFormData.unassignedDate instanceof Date) {
|
||||
currentAccountUnassignStaffFormData.unassignedDate = this.dateUtils.formatDate(prevUnassignmentDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...currentAccountUnassignStaffFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountCommand(this.accountId, 'unassignCurrentAccountOfficer', data)
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
@if (transactionType.holdamount) {
|
||||
<mat-card-title>{{ 'labels.heading.Hold Amount' | translate }}</mat-card-title>
|
||||
}
|
||||
@if (transactionType.blockaccount) {
|
||||
<mat-card-title>{{ 'labels.heading.Block Current Account' | translate }}</mat-card-title>
|
||||
}
|
||||
|
||||
<form [formGroup]="manageCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content class="layout-row">
|
||||
<mat-form-field class="flex-100">
|
||||
<mat-label>{{ 'labels.inputs.Reason' | translate }}</mat-label>
|
||||
<mat-select required formControlName="reasonForBlock">
|
||||
@for (codeValue of reasonOptions; track codeValue) {
|
||||
<mat-option [value]="codeValue.id">
|
||||
{{ codeValue.name }}
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
@if (manageCurrentAccountForm.controls.reasonForBlock.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Reason' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (transactionType.holdamount) {
|
||||
<mat-form-field class="flex-100" (click)="transactionDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="transactionDatePicker"
|
||||
required
|
||||
formControlName="transactionDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="transactionDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #transactionDatePicker></mat-datepicker>
|
||||
@if (manageCurrentAccountForm.controls.transactionDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transaction Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
@if (transactionType.holdamount) {
|
||||
<mifosx-input-amount
|
||||
class="flex-100"
|
||||
[currency]="currency"
|
||||
[isRequired]="true"
|
||||
[inputFormControl]="manageCurrentAccountForm.controls.transactionAmount"
|
||||
[inputLabel]="'Transaction Amount'"
|
||||
>
|
||||
</mifosx-input-amount>
|
||||
}
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../transactions']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!manageCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
width: 37rem;
|
||||
}
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
import { Component, Input, OnInit, inject } from '@angular/core';
|
||||
import { UntypedFormBuilder, UntypedFormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { Currency } from 'app/shared/models/general.model';
|
||||
import { SystemService } from 'app/system/system.service';
|
||||
import { MatCard, MatCardTitle, MatCardContent, MatCardActions } from '@angular/material/card';
|
||||
import { InputAmountComponent } from '../../../shared/input-amount/input-amount.component';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
type TransactionCommandType = 'holdamount' | 'blockaccount' | 'blockdeposit' | 'blockwithdrawal';
|
||||
|
||||
interface TransactionType {
|
||||
holdamount: boolean;
|
||||
blockaccount: boolean;
|
||||
blockdeposit: boolean;
|
||||
blockwithdrawal: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-manage-current-account',
|
||||
templateUrl: './manage-current-account.component.html',
|
||||
styleUrls: ['./manage-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
MatCardTitle,
|
||||
InputAmountComponent
|
||||
]
|
||||
})
|
||||
export class ManageCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private systemService = inject(SystemService);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
@Input() currency: Currency;
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Manage Current Account form. */
|
||||
manageCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
currentAccountId: string;
|
||||
transactionCommand: TransactionCommandType;
|
||||
|
||||
reasonOptions: any = [];
|
||||
|
||||
transactionType: TransactionType = {
|
||||
holdamount: false,
|
||||
blockaccount: false,
|
||||
blockdeposit: false,
|
||||
blockwithdrawal: false
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.transactionCommand = this.route.snapshot.params['name'].toLowerCase().replaceAll(' ', '');
|
||||
this.transactionType[this.transactionCommand] = true;
|
||||
this.currentAccountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the post interest current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createManageCurrentAccountForm();
|
||||
if (
|
||||
this.transactionType.holdamount ||
|
||||
this.transactionType.blockaccount ||
|
||||
this.transactionType.blockdeposit ||
|
||||
this.transactionType.blockwithdrawal
|
||||
) {
|
||||
this.getCodeValues();
|
||||
}
|
||||
}
|
||||
|
||||
getCodeValues() {
|
||||
let codeName = 'CurrentAccountTransactionFreezeReasons'; // Default Hold Amount
|
||||
if (this.transactionType.blockaccount) {
|
||||
codeName = 'CurrentAccountBlockReasons';
|
||||
} else if (this.transactionType.blockdeposit) {
|
||||
codeName = 'CreditTransactionFreezeReasons';
|
||||
} else if (this.transactionType.blockwithdrawal) {
|
||||
codeName = 'DebitTransactionFreezeReasons';
|
||||
}
|
||||
|
||||
this.systemService.getCodes().subscribe((codes: any) => {
|
||||
codes.some((code: any) => {
|
||||
if (code.name === codeName) {
|
||||
this.systemService.getCodeValues(code.id).subscribe((codeValues: any) => {
|
||||
this.reasonOptions = codeValues;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the manage current account form.
|
||||
*/
|
||||
createManageCurrentAccountForm() {
|
||||
if (this.transactionType.holdamount) {
|
||||
this.manageCurrentAccountForm = this.formBuilder.group({
|
||||
reasonForBlock: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
transactionDate: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
transactionAmount: [
|
||||
0.0,
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
} else {
|
||||
this.manageCurrentAccountForm = this.formBuilder.group({
|
||||
reasonForBlock: [
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
submit() {
|
||||
let command = '';
|
||||
let payload: { transactionAmount?: number; [key: string]: any } = {};
|
||||
|
||||
if (this.transactionType.holdamount) {
|
||||
const manageCurrentAccountFormData = this.manageCurrentAccountForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevTransactionDate: Date = this.manageCurrentAccountForm.value.transactionDate;
|
||||
if (manageCurrentAccountFormData.transactionDate instanceof Date) {
|
||||
manageCurrentAccountFormData.transactionDate = this.dateUtils.formatDate(prevTransactionDate, dateFormat);
|
||||
}
|
||||
payload = {
|
||||
...manageCurrentAccountFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
command = 'holdAmount';
|
||||
payload['transactionAmount'] = payload['transactionAmount'] * 1;
|
||||
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountTransactionsCommand(this.currentAccountId, command, payload)
|
||||
.subscribe((response: any) => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
} else {
|
||||
payload = {
|
||||
...this.manageCurrentAccountForm.value
|
||||
};
|
||||
command = 'block';
|
||||
if (this.transactionType.blockdeposit) {
|
||||
command = 'blockCredit';
|
||||
} else if (this.transactionType.blockwithdrawal) {
|
||||
command = 'blockDebit';
|
||||
}
|
||||
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountCommand(this.currentAccountId, command, payload)
|
||||
.subscribe((response: any) => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="postInterestCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<mat-form-field class="flex-100" (click)="transactionDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Transaction Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="transactionDatePicker"
|
||||
required
|
||||
formControlName="transactionDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="transactionDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #transactionDatePicker></mat-datepicker>
|
||||
@if (postInterestCurrentAccountForm.controls.transactionDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Transaction Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!postInterestCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Post Interest Current Account Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-post-interest-as-on-current-account',
|
||||
templateUrl: './post-interest-as-on-current-account.component.html',
|
||||
styleUrls: ['./post-interest-as-on-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS
|
||||
]
|
||||
})
|
||||
export class PostInterestAsOnCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Post Interest Current Account form. */
|
||||
postInterestCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the post interest current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createPostInterestCurrentAccountForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the post interest current account form.
|
||||
*/
|
||||
createPostInterestCurrentAccountForm() {
|
||||
this.postInterestCurrentAccountForm = this.formBuilder.group({
|
||||
transactionDate: [
|
||||
'',
|
||||
Validators.required
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and post interests of the current account,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const postInterestCurrentAccountFormData = this.postInterestCurrentAccountForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevTransactionDate: Date = this.postInterestCurrentAccountForm.value.transactionDate;
|
||||
if (postInterestCurrentAccountFormData.transactionDate instanceof Date) {
|
||||
postInterestCurrentAccountFormData.transactionDate = this.dateUtils.formatDate(prevTransactionDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...postInterestCurrentAccountFormData,
|
||||
IsPostInterestAsOn: true,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountTransactionsCommand(this.accountId, 'postInterestAsOn', data)
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="rejectCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="rejectedOnDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Rejected On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="rejectedOnDatePicker"
|
||||
required
|
||||
formControlName="rejectedOnDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="rejectedOnDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #rejectedOnDatePicker></mat-datepicker>
|
||||
@if (rejectCurrentAccountForm.controls.rejectedOnDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Rejected On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="warn" [disabled]="!rejectCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Reject Current Account Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-reject-current-account',
|
||||
templateUrl: './reject-current-account.component.html',
|
||||
styleUrls: ['./reject-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
})
|
||||
export class RejectCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Reject Current Account form. */
|
||||
rejectCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the reject current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createRejectCurrentAccountForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the reject current account form.
|
||||
*/
|
||||
createRejectCurrentAccountForm() {
|
||||
this.rejectCurrentAccountForm = this.formBuilder.group({
|
||||
rejectedOnDate: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
note: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and rejects the current account,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const rejectCurrentAccountFormData = this.rejectCurrentAccountForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevRejectedOnDate: Date = this.rejectCurrentAccountForm.value.rejectedOnDate;
|
||||
if (rejectCurrentAccountFormData.rejectedOnDate instanceof Date) {
|
||||
rejectCurrentAccountFormData.rejectedOnDate = this.dateUtils.formatDate(prevRejectedOnDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...rejectCurrentAccountFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService.executeCurrentAccountCommand(this.accountId, 'reject', data).subscribe(() => {
|
||||
this.router.navigate(['../../'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="undoApprovalCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<mat-form-field class="flex-fill">
|
||||
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
|
||||
</mat-form-field>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="warn" [disabled]="!undoApprovalCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Undo Approval Current Account Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-undo-approval-current-account',
|
||||
templateUrl: './undo-approval-current-account.component.html',
|
||||
styleUrls: ['./undo-approval-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
})
|
||||
export class UndoApprovalCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
|
||||
/** Undo Approval Current Account form. */
|
||||
undoApprovalCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the undo-approval current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.createUndoApprovalCurrentAccountForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the undo-approval current account form.
|
||||
*/
|
||||
createUndoApprovalCurrentAccountForm() {
|
||||
this.undoApprovalCurrentAccountForm = this.formBuilder.group({
|
||||
note: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and undo the approval of share account,
|
||||
* if successful redirects to the share account.
|
||||
*/
|
||||
submit() {
|
||||
const data = {
|
||||
...this.undoApprovalCurrentAccountForm.value
|
||||
};
|
||||
this.currentAccountsService.executeCurrentAccountCommand(this.accountId, 'undoapproval', data).subscribe(() => {
|
||||
this.router.navigate(['../../transactions'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="container mat-elevation-z8">
|
||||
<mat-card>
|
||||
<form [formGroup]="withdrawCurrentAccountForm" (ngSubmit)="submit()">
|
||||
<mat-card-content>
|
||||
<div class="layout-column">
|
||||
<mat-form-field (click)="withdrawnOnDatePicker.open()">
|
||||
<mat-label>{{ 'labels.inputs.Withdrawn On Date' | translate }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[matDatepicker]="withdrawnOnDatePicker"
|
||||
required
|
||||
formControlName="withdrawnOnDate"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="withdrawnOnDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #withdrawnOnDatePicker></mat-datepicker>
|
||||
@if (withdrawCurrentAccountForm.controls.withdrawnOnDate.hasError('required')) {
|
||||
<mat-error>
|
||||
{{ 'labels.inputs.Withdrawn On Date' | translate }} {{ 'labels.commons.is' | translate }}
|
||||
<strong>{{ 'labels.commons.required' | translate }}</strong>
|
||||
</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>{{ 'labels.inputs.Note' | translate }}</mat-label>
|
||||
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
|
||||
<mat-card-actions class="layout-row align-center gap-5px responsive-column">
|
||||
<button type="button" mat-raised-button [routerLink]="['../../']">
|
||||
{{ 'labels.buttons.Cancel' | translate }}
|
||||
</button>
|
||||
<button mat-raised-button color="primary" [disabled]="!withdrawCurrentAccountForm.valid">
|
||||
{{ 'labels.buttons.Confirm' | translate }}
|
||||
</button>
|
||||
</mat-card-actions>
|
||||
</form>
|
||||
</mat-card>
|
||||
</div>
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
.container {
|
||||
max-width: 37rem;
|
||||
}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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 { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
import { CurrentAccountsService } from 'app/current-accounts/current-accounts.service';
|
||||
import { SettingsService } from 'app/settings/settings.service';
|
||||
import { CdkTextareaAutosize } from '@angular/cdk/text-field';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
|
||||
/**
|
||||
* Withdrawn by Client Current Account Component
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-withdraw-by-client-current-account',
|
||||
templateUrl: './withdraw-by-client-current-account.component.html',
|
||||
styleUrls: ['./withdraw-by-client-current-account.component.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
CdkTextareaAutosize
|
||||
]
|
||||
})
|
||||
export class WithdrawByClientCurrentAccountComponent implements OnInit {
|
||||
private formBuilder = inject(UntypedFormBuilder);
|
||||
private currentAccountsService = inject(CurrentAccountsService);
|
||||
private dateUtils = inject(Dates);
|
||||
private route = inject(ActivatedRoute);
|
||||
private router = inject(Router);
|
||||
private settingsService = inject(SettingsService);
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Withdraw Current Account form. */
|
||||
withdrawCurrentAccountForm: UntypedFormGroup;
|
||||
/** Current Account Id */
|
||||
accountId: any;
|
||||
|
||||
/**
|
||||
* @param {FormBuilder} formBuilder Form Builder
|
||||
* @param {CurrentAccountsService} currentAccountsService Current Accounts Service
|
||||
* @param {Dates} dateUtils Date Utils
|
||||
* @param {ActivatedRoute} route Activated Route
|
||||
* @param {Router} router Router
|
||||
* @param {SettingsService} settingsService Setting service
|
||||
*/
|
||||
constructor() {
|
||||
this.accountId = this.route.snapshot.params['currentAccountId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the withdraw current account form.
|
||||
*/
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.createWithdrawCurrentAccountForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the withdraw current account form.
|
||||
*/
|
||||
createWithdrawCurrentAccountForm() {
|
||||
this.withdrawCurrentAccountForm = this.formBuilder.group({
|
||||
withdrawnOnDate: [
|
||||
'',
|
||||
Validators.required
|
||||
],
|
||||
note: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits the form and withdraws the current account by client,
|
||||
* if successful redirects to the current account.
|
||||
*/
|
||||
submit() {
|
||||
const withdrawCurrentAccountFormData = this.withdrawCurrentAccountForm.value;
|
||||
const locale = this.settingsService.language.code;
|
||||
const dateFormat = this.settingsService.dateFormat;
|
||||
const prevWithdrawnOnDate: Date = this.withdrawCurrentAccountForm.value.withdrawnOnDate;
|
||||
if (withdrawCurrentAccountFormData.withdrawnOnDate instanceof Date) {
|
||||
withdrawCurrentAccountFormData.withdrawnOnDate = this.dateUtils.formatDate(prevWithdrawnOnDate, dateFormat);
|
||||
}
|
||||
const data = {
|
||||
...withdrawCurrentAccountFormData,
|
||||
dateFormat,
|
||||
locale
|
||||
};
|
||||
this.currentAccountsService
|
||||
.executeCurrentAccountCommand(this.accountId, 'withdrawnByApplicant', data)
|
||||
.subscribe(() => {
|
||||
this.router.navigate(['../../'], { relativeTo: this.route });
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user