Upgrading to Angular 20:

Replaced checked in package-lock.json by regenerated one.
Ran ng update @angular/core@20 @angular/cli@20
Ran npm install @angular-builders/jest@^20.0.0 @fortawesome/angular-fontawesome@^3.0.0 @swimlane/ngx-graph@^11
Ran npm install ngx-mat-select-search@^8.0.2.
Ran ng update @angular/material@20.
Updated all eslint and typescript to the latest versions.
Removed @angular-devkit/schematics.
Updated fontawesome.
Updated rxjs and tslib.
Moved required node version from 16 to 20.
Updated jest-preset-angular.
Set preserveWhitespaces to false.
Corrected two type declarations in two typescript files to make ng serve run without errors.
Removed unused angular-devkit/schematics from view-user.component.ts .
Updated list of supported browsers.
Upgraded prettier.
Ran prettier . --write the first time.
Ran prettier . --write the second time.
Ran ng generate @angular/core:inject with defaults, excepted a handful of files.
Fixed remaining eslint problems.
Added dist directory to ignores in eslint.config.js.
Let prettier fix formatting, almost everything is just line breaks.
Made htmlhint ignore @if and @for Angular constructs.
Updated node version in Github workflow to 22.12.0 (build.yml).
Updated .env.ts.
Updated Angular datetime format strings from YYYY-MM-DD to yyyy-MM-dd.
Merged changes from dev into angular20 branch.
This commit is contained in:
Felix van Hove
2025-12-08 11:01:01 +01:00
parent f1b4ec2cf2
commit 7fd1486c08
1516 changed files with 39367 additions and 36037 deletions
@@ -3,15 +3,17 @@
<div class="m-b-10">
<h3>{{ 'labels.inputs.Charges' | translate }}</h3>
</div>
<div class="action-button m-b-20" *ngIf="this.chargesData">
<button mat-raised-button color="primary" (click)="toggleCharges()">
{{
showInactiveCharges
? viewAllChargeButtons('View Active Charges')
: viewAllChargeButtons('View Inactive Charges')
}}
</button>
</div>
@if (this.chargesData) {
<div class="action-button m-b-20">
<button mat-raised-button color="primary" (click)="toggleCharges()">
{{
showInactiveCharges
? viewAllChargeButtons('View Active Charges')
: viewAllChargeButtons('View Inactive Charges')
}}
</button>
</div>
}
</div>
<div class="mat-elevation-z1 m-b-25">
@@ -77,62 +79,66 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let charge">
<span *ngIf="savingsAccountData.status.value === 'Submitted and pending approval'">
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Edit Charge' | translate }}"
*mifosxHasPermission="'UPDATE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); editCharge(charge)"
>
<i class="fa fa-pencil"></i>
</button>
<button
class="account-action-button"
mat-raised-button
color="warn"
matTooltip="{{ 'tooltips.Delete Charge' | translate }}"
*mifosxHasPermission="'DELETE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); deleteCharge(charge.id)"
>
<i class="fa fa-trash"></i>
</button>
</span>
<span *ngIf="savingsAccountData.status.value === 'Active' && charge.amountOutstanding !== 0">
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Pay Charge' | translate }}"
*mifosxHasPermission="'PAY_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); payCharge(charge.id)"
>
<i class="fa fa-dollar"></i>
</button>
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Waive Charge' | translate }}"
*mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); waiveCharge(charge.id)"
>
<i class="fa fa-flag"></i>
</button>
<ng-container *ngIf="isRecurringCharge(charge)">
@if (savingsAccountData.status.value === 'Submitted and pending approval') {
<span>
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Inactivate Charge' | translate }}"
*mifosxHasPermission="'INACTIVATE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); inactivateCharge(charge.id)"
matTooltip="{{ 'tooltips.Edit Charge' | translate }}"
*mifosxHasPermission="'UPDATE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); editCharge(charge)"
>
<i class="fa fa-ban"></i>
<i class="fa fa-pencil"></i>
</button>
</ng-container>
</span>
<button
class="account-action-button"
mat-raised-button
color="warn"
matTooltip="{{ 'tooltips.Delete Charge' | translate }}"
*mifosxHasPermission="'DELETE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); deleteCharge(charge.id)"
>
<i class="fa fa-trash"></i>
</button>
</span>
}
@if (savingsAccountData.status.value === 'Active' && charge.amountOutstanding !== 0) {
<span>
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Pay Charge' | translate }}"
*mifosxHasPermission="'PAY_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); payCharge(charge.id)"
>
<i class="fa fa-dollar"></i>
</button>
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Waive Charge' | translate }}"
*mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); waiveCharge(charge.id)"
>
<i class="fa fa-flag"></i>
</button>
@if (isRecurringCharge(charge)) {
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Inactivate Charge' | translate }}"
*mifosxHasPermission="'INACTIVATE_SAVINGSACCOUNTCHARGE'"
(click)="routeEdit($event); inactivateCharge(charge.id)"
>
<i class="fa fa-ban"></i>
</button>
}
</span>
}
</td>
</ng-container>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import {
@@ -32,7 +32,7 @@ import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base';
import { Dates } from 'app/core/utils/dates';
import { TranslateService } from '@ngx-translate/core';
import { NgIf, CurrencyPipe } from '@angular/common';
import { CurrencyPipe } from '@angular/common';
import { MatTooltip } from '@angular/material/tooltip';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -62,6 +62,14 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ChargesTabComponent implements OnInit {
private savingsService = inject(SavingsService);
private route = inject(ActivatedRoute);
private dateUtils = inject(Dates);
private router = inject(Router);
private dialog = inject(MatDialog);
private settingsService = inject(SettingsService);
private translateService = inject(TranslateService);
/** Savings Account Data */
savingsAccountData: any;
/** Charges Data */
@@ -97,15 +105,7 @@ export class ChargesTabComponent implements OnInit {
* @param {Dates} dateUtils Date Utils.
* @param {SettingsService} settingsService Setting service
*/
constructor(
private savingsService: SavingsService,
private route: ActivatedRoute,
private dateUtils: Dates,
private router: Router,
private dialog: MatDialog,
private settingsService: SettingsService,
private translateService: TranslateService
) {
constructor() {
this.route.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.savingsAccountData = data.savingsAccountData;
this.chargesData = this.savingsAccountData.charges;
@@ -152,7 +152,6 @@ export class ChargesTabComponent implements OnInit {
type: 'date',
required: true
})
];
const data = {
title: `Pay Charge ${chargeId}`,
@@ -226,7 +225,6 @@ export class ChargesTabComponent implements OnInit {
type: 'number',
required: true
})
];
const data = {
title: `Edit Charge ${charge.id}`,
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import {
MatDialogRef,
MatDialogTitle,
@@ -27,8 +27,5 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class CalculateInterestDialogComponent {
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
*/
constructor(public dialogRef: MatDialogRef<CalculateInterestDialogComponent>) {}
dialogRef = inject<MatDialogRef<CalculateInterestDialogComponent>>(MatDialogRef);
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import {
MatDialogRef,
MAT_DIALOG_DATA,
@@ -28,12 +28,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class InactivateChargeDialogComponent {
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
* @param {any} data.
*/
constructor(
public dialogRef: MatDialogRef<InactivateChargeDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {}
dialogRef = inject<MatDialogRef<InactivateChargeDialogComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import {
MatDialogRef,
MatDialogTitle,
@@ -27,8 +27,5 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class PostInterestDialogComponent {
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
*/
constructor(public dialogRef: MatDialogRef<PostInterestDialogComponent>) {}
dialogRef = inject<MatDialogRef<PostInterestDialogComponent>>(MatDialogRef);
}
@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import {
MatDialogRef,
MatDialogTitle,
@@ -23,8 +23,5 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ReleaseAmountDialogComponent {
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
*/
constructor(public dialogRef: MatDialogRef<ReleaseAmountDialogComponent>) {}
dialogRef = inject<MatDialogRef<ReleaseAmountDialogComponent>>(MatDialogRef);
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import {
MatDialogRef,
MAT_DIALOG_DATA,
@@ -28,12 +28,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ToggleWithholdTaxDialogComponent {
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
* @param {any} data.
*/
constructor(
public dialogRef: MatDialogRef<ToggleWithholdTaxDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {}
dialogRef = inject<MatDialogRef<ToggleWithholdTaxDialogComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import {
MatDialogRef,
MatDialogTitle,
@@ -26,8 +26,5 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class UndoTransactionDialogComponent {
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
*/
constructor(public dialogRef: MatDialogRef<UndoTransactionDialogComponent>) {}
dialogRef = inject<MatDialogRef<UndoTransactionDialogComponent>>(MatDialogRef);
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, Inject } from '@angular/core';
import { Component, inject } from '@angular/core';
import {
MatDialogRef,
MAT_DIALOG_DATA,
@@ -28,12 +28,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class WaiveChargeDialogComponent {
/**
* @param {MatDialogRef} dialogRef Component reference to dialog.
* @param {any} data.
*/
constructor(
public dialogRef: MatDialogRef<WaiveChargeDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: any
) {}
dialogRef = inject<MatDialogRef<WaiveChargeDialogComponent>>(MatDialogRef);
data = inject(MAT_DIALOG_DATA);
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { EntityDatatableTabComponent } from '../../../shared/tabs/entity-datatable-tab/entity-datatable-tab.component';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -17,6 +17,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class DatatableTabsComponent {
private route = inject(ActivatedRoute);
entityId: string;
/** Savings Datatable */
entityDatatable: any;
@@ -27,7 +29,7 @@ export class DatatableTabsComponent {
* Fetches Savings and datatables data from `resolve`
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
constructor() {
this.entityId = this.route.parent.parent.snapshot.paramMap.get('savingAccountId');
this.route.data.subscribe((data: { savingsDatatable: any }) => {
@@ -1,279 +1,359 @@
<div *ngIf="isLoading" class="loader">
<div class="loading"></div>
</div>
@if (isLoading) {
<div class="loader">
<div class="loading"></div>
</div>
}
<div class="savings-account-tables layout-row gap-2percent" *ngIf="!isLoading">
<div class="flex-49 layout-column gap-4percent">
<div
*ngIf="
!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval;
else alternateDetails
"
>
<h4 class="table-headers">{{ 'labels.heading.Savings Details' | translate }}</h4>
<table>
<tbody>
<tr>
<td>{{ 'labels.inputs.External Id' | translate }}</td>
<td *ngIf="savingsAccountData.externalId">
<mifosx-external-identifier externalId="{{ savingsAccountData.externalId }}"></mifosx-external-identifier>
</td>
<td *ngIf="!savingsAccountData.externalId">{{ 'labels.inputs.Not Provided' | translate }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Activated On' | translate }}</td>
<td>
{{
savingsAccountData.timeline.activatedOnDate
? (savingsAccountData.timeline.activatedOnDate | dateFormat)
: 'Not Activated'
}}
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Field Officer' | translate }}</td>
<td>{{ savingsAccountData.fieldOfficerName ? savingsAccountData.fieldOfficerName : 'Unassigned' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Currency' | translate }}</td>
<td>{{ savingsAccountData.currency.name }} [{{ savingsAccountData.currency.code }}]</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Nominal Interest Rate' | translate }}</td>
<td class="r-amount">
<span *ngIf="savingsAccountData.nominalAnnualInterestRate"
>{{ savingsAccountData.nominalAnnualInterestRate | formatNumber }} %</span
>
<span *ngIf="!savingsAccountData.nominalAnnualInterestRate">0 %</span>
</td>
</tr>
</tbody>
</table>
@if (!isLoading) {
<div class="savings-account-tables layout-row gap-2percent">
<div class="flex-49 layout-column gap-4percent">
@if (!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval) {
<div>
<h4 class="table-headers">{{ 'labels.heading.Savings Details' | translate }}</h4>
<table>
<tbody>
<tr>
<td>{{ 'labels.inputs.External Id' | translate }}</td>
@if (savingsAccountData.externalId) {
<td>
<mifosx-external-identifier
externalId="{{ savingsAccountData.externalId }}"
></mifosx-external-identifier>
</td>
}
@if (!savingsAccountData.externalId) {
<td>{{ 'labels.inputs.Not Provided' | translate }}</td>
}
</tr>
<tr>
<td>{{ 'labels.inputs.Activated On' | translate }}</td>
<td>
{{
savingsAccountData.timeline.activatedOnDate
? (savingsAccountData.timeline.activatedOnDate | dateFormat)
: 'Not Activated'
}}
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Field Officer' | translate }}</td>
<td>{{ savingsAccountData.fieldOfficerName ? savingsAccountData.fieldOfficerName : 'Unassigned' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Currency' | translate }}</td>
<td>{{ savingsAccountData.currency.name }} [{{ savingsAccountData.currency.code }}]</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Nominal Interest Rate' | translate }}</td>
<td class="r-amount">
@if (savingsAccountData.nominalAnnualInterestRate) {
<span>{{ savingsAccountData.nominalAnnualInterestRate | formatNumber }} %</span>
}
@if (!savingsAccountData.nominalAnnualInterestRate) {
<span>0 %</span>
}
</td>
</tr>
</tbody>
</table>
</div>
} @else {
<div>
<h4 class="table-headers">{{ 'labels.heading.Savings Details' | translate }}</h4>
<table>
<tbody>
<tr>
<td>{{ 'labels.inputs.Field Officer' | translate }}</td>
<td>{{ savingsAccountData.fieldOfficerName ? savingsAccountData.fieldOfficerName : 'Unassigned' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Balance' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
</tbody>
</table>
</div>
}
@if (!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval) {
<div>
<h4 class="table-headers">{{ 'labels.heading.Performance History' | translate }}</h4>
<table>
<tbody>
@if (savingsAccountData.summary.totalDeposits) {
<tr>
<td>{{ 'labels.inputs.Total Deposits' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalDeposits | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
}
@if (savingsAccountData.summary.totalInterestEarned >= 0) {
<tr>
<td>{{ 'labels.inputs.Total Interest Earned' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.totalInterestEarned
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
<ng-template #alternateDetails>
<div>
<h4 class="table-headers">{{ 'labels.heading.Savings Details' | translate }}</h4>
@if (isActive) {
<div class="flex-49">
<h4 class="table-headers">{{ 'labels.heading.Account Summary' | translate }}</h4>
<table>
<tbody>
@if (savingsAccountData.summary.totalWithdrawals) {
<tr>
<td>{{ 'labels.inputs.Total Withdrawls' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.totalWithdrawals | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.summary.totalWithdrawalFees) {
<tr>
<td>{{ 'labels.inputs.Withdrawals Fees' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.totalWithdrawalFees | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.summary.totalAnnualFees) {
<tr>
<td>{{ 'labels.inputs.Annual Fees' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalAnnualFees | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
}
@if (savingsAccountData.summary.totalInterestEarned >= 0) {
<tr>
<td>{{ 'labels.inputs.Interest Earned' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.totalInterestEarned | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.summary.totalInterestPosted) {
<tr>
<td>{{ 'labels.inputs.Interest Posted' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.totalInterestPosted | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.summary.interestNotPosted >= 0) {
<tr>
<td>{{ 'labels.inputs.Interest Earned Not Posted' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.summary.totalOverdraftInterestDerived) {
<tr>
<td>{{ 'labels.inputs.Interest On Overdraft' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.totalOverdraftInterestDerived
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.summary.interestNotPosted < 0) {
<tr>
<td>{{ 'labels.inputs.Overdraft Interest Not Posted' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.nominalAnnualInterestRate) {
<tr>
<td>{{ 'labels.inputs.Nominal Interest Rate' | translate }}</td>
<td class="r-amount">{{ savingsAccountData.nominalAnnualInterestRate | formatNumber }} %</td>
</tr>
}
<tr>
<td>{{ 'labels.inputs.Interest Compounding Period' | translate }}</td>
<td>{{ savingsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Interest Posting Period' | translate }}</td>
<td>{{ savingsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Interest Calculated Using' | translate }}</td>
<td>{{ savingsAccountData.interestCalculationType.value | translateKey: 'catalogs' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Days in Year' | translate }}</td>
<td>{{ savingsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs' }}</td>
</tr>
@if (savingsAccountData.withdrawalFee) {
<tr>
<td>{{ 'labels.inputs.Withdrawal Fee' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.withdrawalFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
}
@if (savingsAccountData.lastActiveTransactionDate) {
<tr>
<td>{{ 'labels.inputs.Last Active Transaction Date' | translate }}</td>
<td>{{ savingsAccountData.lastActiveTransactionDate | dateFormat }}</td>
</tr>
}
@if (!(savingsAccountData.subStatus.id === 0)) {
<tr>
<td>{{ 'labels.inputs.Substatus' | translate }}</td>
<td>{{ savingsAccountData.subStatus.value }}</td>
</tr>
}
@if (savingsAccountData.daysToInactive) {
<tr>
<td>{{ 'labels.inputs.Days to Inactive' | translate }}</td>
<td>{{ savingsAccountData.daysToInactive }}</td>
</tr>
}
@if (savingsAccountData.daysToDormancy) {
<tr>
<td>{{ 'labels.inputs.Days to Dormancy' | translate }}</td>
<td>{{ savingsAccountData.daysToDormancy }}</td>
</tr>
}
@if (savingsAccountData.daysToEscheat) {
<tr>
<td>{{ 'labels.inputs.Days to Escheat' | translate }}</td>
<td>{{ savingsAccountData.daysToEscheat }}</td>
</tr>
}
@if (savingsAccountData.annualFee) {
<tr>
<td>{{ 'labels.inputs.Annual Fee' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.annualFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
}
@if (savingsAccountData.allowOverdraft) {
<tr>
<td>{{ 'labels.inputs.Overdraft Limit' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.overdraftLimit | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
}
@if (savingsAccountData.allowOverdraft) {
<tr>
<td>{{ 'labels.inputs.Minimum Overdraft Required for Interest Calculation' | translate }}</td>
<td>
{{
savingsAccountData.minOverdraftForInterestCalculation
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
}
@if (savingsAccountData.minBalanceForInterestCalculation) {
<tr>
<td>{{ 'labels.inputs.Min Balance Required for Interest Calculation' | translate }}</td>
<td>{{ savingsAccountData.minBalanceForInterestCalculation | formatNumber }}</td>
</tr>
}
@if (savingsAccountData.minRequiredBalance) {
<tr>
<td>{{ 'labels.inputs.Minimum Required Balance' | translate }}</td>
<td>{{ savingsAccountData.minRequiredBalance | formatNumber }}</td>
</tr>
}
@if (savingsAccountData.enforceMinRequiredBalance) {
<tr>
<td>{{ 'labels.inputs.Enforce Minimum Required Balance' | translate }}</td>
<td>{{ savingsAccountData.enforceMinRequiredBalance | yesNo }}</td>
</tr>
}
@if (savingsAccountData.summary.lastInterestCalculationDate) {
<tr>
<td>{{ 'labels.inputs.Interest Recalculation Date' | translate }}</td>
<td>{{ savingsAccountData.summary.lastInterestCalculationDate | dateFormat }}</td>
</tr>
}
@if (savingsAccountData.onHoldFunds) {
<tr>
<td>{{ 'labels.inputs.On Hold Funds' | translate }}</td>
<td>
<a *mifosxHasPermission="'READ_SAVINGSACCOUNT'">{{
savingsAccountData.onHoldFunds | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</a>
</td>
</tr>
}
@if (savingsAccountData.withHoldTax) {
<tr>
<td>{{ 'labels.inputs.Withhold Tax Group' | translate }}</td>
<td>{{ savingsAccountData.taxGroup.name }}</td>
</tr>
}
</tbody>
</table>
</div>
} @else {
<div class="flex-49">
<h4 class="table-headers">{{ 'labels.heading.Account Summary' | translate }}</h4>
<table>
<tbody>
<tr>
<td>{{ 'labels.inputs.Field Officer' | translate }}</td>
<td>{{ savingsAccountData.fieldOfficerName ? savingsAccountData.fieldOfficerName : 'Unassigned' }}</td>
<td>{{ 'labels.inputs.External Id' | translate }}</td>
@if (savingsAccountData.externalId) {
<td>
<mifosx-external-identifier
externalId="{{ savingsAccountData.externalId }}"
></mifosx-external-identifier>
</td>
}
@if (!savingsAccountData.externalId) {
<td>{{ 'labels.inputs.Not Provided' | translate }}</td>
}
</tr>
<tr>
<td>{{ 'labels.inputs.Balance' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
<td>{{ 'labels.inputs.Activated On' | translate }}</td>
<td>
{{
savingsAccountData.timeline.activatedOnDate
? (savingsAccountData.timeline.activatedOnDate | dateFormat)
: 'Not Activated'
}}
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Currency' | translate }}</td>
<td>{{ savingsAccountData.currency.name }} [{{ savingsAccountData.currency.code }}]</td>
</tr>
</tbody>
</table>
</div>
</ng-template>
<div *ngIf="!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval">
<h4 class="table-headers">{{ 'labels.heading.Performance History' | translate }}</h4>
<table>
<tbody>
<tr *ngIf="savingsAccountData.summary.totalDeposits">
<td>{{ 'labels.inputs.Total Deposits' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalDeposits | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalInterestEarned >= 0">
<td>{{ 'labels.inputs.Total Interest Earned' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalInterestEarned | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
</tbody>
</table>
</div>
}
</div>
<div class="flex-49" *ngIf="isActive; else alternateSummary">
<h4 class="table-headers">{{ 'labels.heading.Account Summary' | translate }}</h4>
<table>
<tbody>
<tr *ngIf="savingsAccountData.summary.totalWithdrawals">
<td>{{ 'labels.inputs.Total Withdrawls' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalWithdrawals | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalWithdrawalFees">
<td>{{ 'labels.inputs.Withdrawals Fees' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalWithdrawalFees | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalAnnualFees">
<td>{{ 'labels.inputs.Annual Fees' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalAnnualFees | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalInterestEarned >= 0">
<td>{{ 'labels.inputs.Interest Earned' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalInterestEarned | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalInterestPosted">
<td>{{ 'labels.inputs.Interest Posted' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.totalInterestPosted | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.interestNotPosted >= 0">
<td>{{ 'labels.inputs.Interest Earned Not Posted' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalOverdraftInterestDerived">
<td>{{ 'labels.inputs.Interest On Overdraft' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.totalOverdraftInterestDerived
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
<tr *ngIf="savingsAccountData.summary.interestNotPosted < 0">
<td>{{ 'labels.inputs.Overdraft Interest Not Posted' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.summary.interestNotPosted | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.nominalAnnualInterestRate">
<td>{{ 'labels.inputs.Nominal Interest Rate' | translate }}</td>
<td class="r-amount">{{ savingsAccountData.nominalAnnualInterestRate | formatNumber }} %</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Interest Compounding Period' | translate }}</td>
<td>{{ savingsAccountData.interestCompoundingPeriodType.value | translateKey: 'catalogs' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Interest Posting Period' | translate }}</td>
<td>{{ savingsAccountData.interestPostingPeriodType.value | translateKey: 'catalogs' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Interest Calculated Using' | translate }}</td>
<td>{{ savingsAccountData.interestCalculationType.value | translateKey: 'catalogs' }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Days in Year' | translate }}</td>
<td>{{ savingsAccountData.interestCalculationDaysInYearType.value | translateKey: 'catalogs' }}</td>
</tr>
<tr *ngIf="savingsAccountData.withdrawalFee">
<td>{{ 'labels.inputs.Withdrawal Fee' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.withdrawalFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.lastActiveTransactionDate">
<td>{{ 'labels.inputs.Last Active Transaction Date' | translate }}</td>
<td>{{ savingsAccountData.lastActiveTransactionDate | dateFormat }}</td>
</tr>
<tr *ngIf="!(savingsAccountData.subStatus.id === 0)">
<td>{{ 'labels.inputs.Substatus' | translate }}</td>
<td>{{ savingsAccountData.subStatus.value }}</td>
</tr>
<tr *ngIf="savingsAccountData.daysToInactive">
<td>{{ 'labels.inputs.Days to Inactive' | translate }}</td>
<td>{{ savingsAccountData.daysToInactive }}</td>
</tr>
<tr *ngIf="savingsAccountData.daysToDormancy">
<td>{{ 'labels.inputs.Days to Dormancy' | translate }}</td>
<td>{{ savingsAccountData.daysToDormancy }}</td>
</tr>
<tr *ngIf="savingsAccountData.daysToEscheat">
<td>{{ 'labels.inputs.Days to Escheat' | translate }}</td>
<td>{{ savingsAccountData.daysToEscheat }}</td>
</tr>
<tr *ngIf="savingsAccountData.annualFee">
<td>{{ 'labels.inputs.Annual Fee' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.annualFee.amount | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.allowOverdraft">
<td>{{ 'labels.inputs.Overdraft Limit' | translate }}</td>
<td class="r-amount">
{{ savingsAccountData.overdraftLimit | currency: currency.code : 'symbol-narrow' : '1.2-2' }}
</td>
</tr>
<tr *ngIf="savingsAccountData.allowOverdraft">
<td>{{ 'labels.inputs.Minimum Overdraft Required for Interest Calculation' | translate }}</td>
<td>
{{
savingsAccountData.minOverdraftForInterestCalculation
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
<tr *ngIf="savingsAccountData.minBalanceForInterestCalculation">
<td>{{ 'labels.inputs.Min Balance Required for Interest Calculation' | translate }}</td>
<td>{{ savingsAccountData.minBalanceForInterestCalculation | formatNumber }}</td>
</tr>
<tr *ngIf="savingsAccountData.minRequiredBalance">
<td>{{ 'labels.inputs.Minimum Required Balance' | translate }}</td>
<td>{{ savingsAccountData.minRequiredBalance | formatNumber }}</td>
</tr>
<tr *ngIf="savingsAccountData.enforceMinRequiredBalance">
<td>{{ 'labels.inputs.Enforce Minimum Required Balance' | translate }}</td>
<td>{{ savingsAccountData.enforceMinRequiredBalance | yesNo }}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.lastInterestCalculationDate">
<td>{{ 'labels.inputs.Interest Recalculation Date' | translate }}</td>
<td>{{ savingsAccountData.summary.lastInterestCalculationDate | dateFormat }}</td>
</tr>
<tr *ngIf="savingsAccountData.onHoldFunds">
<td>{{ 'labels.inputs.On Hold Funds' | translate }}</td>
<td>
<a *mifosxHasPermission="'READ_SAVINGSACCOUNT'">{{
savingsAccountData.onHoldFunds | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}</a>
</td>
</tr>
<tr *ngIf="savingsAccountData.withHoldTax">
<td>{{ 'labels.inputs.Withhold Tax Group' | translate }}</td>
<td>{{ savingsAccountData.taxGroup.name }}</td>
</tr>
</tbody>
</table>
</div>
<ng-template #alternateSummary>
<div class="flex-49">
<h4 class="table-headers">{{ 'labels.heading.Account Summary' | translate }}</h4>
<table>
<tbody>
<tr>
<td>{{ 'labels.inputs.External Id' | translate }}</td>
<td *ngIf="savingsAccountData.externalId">
<mifosx-external-identifier externalId="{{ savingsAccountData.externalId }}"></mifosx-external-identifier>
</td>
<td *ngIf="!savingsAccountData.externalId">{{ 'labels.inputs.Not Provided' | translate }}</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Activated On' | translate }}</td>
<td>
{{
savingsAccountData.timeline.activatedOnDate
? (savingsAccountData.timeline.activatedOnDate | dateFormat)
: 'Not Activated'
}}
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Currency' | translate }}</td>
<td>{{ savingsAccountData.currency.name }} [{{ savingsAccountData.currency.code }}]</td>
</tr>
</tbody>
</table>
</div>
</ng-template>
</div>
}
@@ -1,7 +1,7 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Currency } from 'app/shared/models/general.model';
import { NgIf, CurrencyPipe } from '@angular/common';
import { CurrencyPipe } from '@angular/common';
import { ExternalIdentifierComponent } from '../../../shared/external-identifier/external-identifier.component';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { FormatNumberPipe } from '../../../pipes/format-number.pipe';
@@ -22,6 +22,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class GeneralTabComponent {
private route = inject(ActivatedRoute);
private router = inject(Router);
isLoading = true;
isActive = false;
entityType: string;
@@ -29,10 +32,7 @@ export class GeneralTabComponent {
savingsAccountData: any;
currency: Currency;
constructor(
private route: ActivatedRoute,
private router: Router
) {
constructor() {
this.route.parent.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.savingsAccountData = data.savingsAccountData;
this.currency = this.savingsAccountData.currency;
@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { AuthenticationService } from 'app/core/authentication/authentication.service';
import { SavingsService } from 'app/savings/savings.service';
@@ -15,15 +15,15 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class NotesTabComponent {
private route = inject(ActivatedRoute);
private savingsService = inject(SavingsService);
private authenticationService = inject(AuthenticationService);
entityId: string;
username: string;
entityNotes: any;
constructor(
private route: ActivatedRoute,
private savingsService: SavingsService,
private authenticationService: AuthenticationService
) {
constructor() {
const savedCredentials = this.authenticationService.getCredentials();
this.username = savedCredentials.username;
this.entityId = this.route.parent.snapshot.params['savingAccountId'];
@@ -16,18 +16,20 @@
<mat-card-title class="layout-row layout-lt-md-column">
<div class="flex-60">
<h3>
<i
class="fa fa-stop"
[ngClass]="savingsAccountData.status.code | statusLookup"
[matTooltip]="savingsAccountData.status.value"
*ngIf="!savingsAccountData.subStatus.block"
></i>
<i
class="fa fa-stop"
[ngClass]="savingsAccountData.subStatus.value | statusLookup"
[matTooltip]="savingsAccountData.subStatus.value"
*ngIf="savingsAccountData.subStatus.block"
></i>
@if (!savingsAccountData.subStatus.block) {
<i
class="fa fa-stop"
[ngClass]="savingsAccountData.status.code | statusLookup"
[matTooltip]="savingsAccountData.status.value"
></i>
}
@if (savingsAccountData.subStatus.block) {
<i
class="fa fa-stop"
[ngClass]="savingsAccountData.subStatus.value | statusLookup"
[matTooltip]="savingsAccountData.subStatus.value"
></i>
}
<span class="m-r-5">{{ 'labels.inputs.Savings Product' | translate }} :</span>
<span class="m-r-5"
><mifosx-long-text textValue="{{ savingsAccountData.savingsProductName }}"></mifosx-long-text
@@ -40,38 +42,40 @@
<span class="account-overview">
{{ 'labels.text.' + entityType | translate }} {{ 'labels.inputs.name' | translate }}:
{{ savingsAccountData.clientName || savingsAccountData.groupName }}
<span class="m-l-10" *ngIf="savingsAccountData.clientAccountNo">
<mifosx-account-number accountNo="{{ savingsAccountData.clientAccountNo }}"></mifosx-account-number>
</span>
@if (savingsAccountData.clientAccountNo) {
<span class="m-l-10">
<mifosx-account-number accountNo="{{ savingsAccountData.clientAccountNo }}"></mifosx-account-number>
</span>
}
</span>
</div>
<div
class="flex-30"
*ngIf="!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval"
>
<h3>{{ 'labels.heading.Account Overview' | translate }}</h3>
<table class="account-overview">
<tbody>
<tr>
<td>{{ 'labels.inputs.Current Balance' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Available Balance' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.availableBalance | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
</tbody>
</table>
</div>
@if (!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval) {
<div class="flex-30">
<h3>{{ 'labels.heading.Account Overview' | translate }}</h3>
<table class="account-overview">
<tbody>
<tr>
<td>{{ 'labels.inputs.Current Balance' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.accountBalance | currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
<tr>
<td>{{ 'labels.inputs.Available Balance' | translate }}</td>
<td class="r-amount">
{{
savingsAccountData.summary.availableBalance
| currency: currency.code : 'symbol-narrow' : '1.2-2'
}}
</td>
</tr>
</tbody>
</table>
</div>
}
<div class="flex-5">
<button
@@ -89,102 +93,107 @@
</div>
<mat-menu #accountMenu="matMenu">
<ng-container *ngFor="let item of buttonConfig.singleButtons">
@for (item of buttonConfig.singleButtons; track item) {
<button mat-menu-item *mifosxHasPermission="item.taskPermissionName" (click)="doAction(item.name)">
<mat-icon matListIcon>
<fa-icon icon="{{ item.icon }}" size="sm"></fa-icon>
</mat-icon>
<span> {{ 'labels.menus.' + item.name | translate }} </span>
</button>
</ng-container>
}
<ng-container *ngIf="buttonConfig.options && !savingsAccountData.subStatus.block">
@if (buttonConfig.options && !savingsAccountData.subStatus.block) {
<button mat-menu-item [matMenuTriggerFor]="More">{{ 'labels.menus.More' | translate }}</button>
<mat-menu #More="matMenu">
<span *ngFor="let option of buttonConfig.options">
<button mat-menu-item *mifosxHasPermission="option.taskPermissionName" (click)="doAction(option.name)">
{{ 'labels.menus.' + option.name | translate }}
</button>
</span>
@for (option of buttonConfig.options; track option) {
<span>
<button mat-menu-item *mifosxHasPermission="option.taskPermissionName" (click)="doAction(option.name)">
{{ 'labels.menus.' + option.name | translate }}
</button>
</span>
}
</mat-menu>
</ng-container>
}
</mat-menu>
</mat-card-title-group>
</mat-card-header>
<mat-card-content class="content">
<nav mat-tab-nav-bar class="navigation-tabs" *ngIf="isActive" [tabPanel]="tabPanel">
<a
mat-tab-link
[routerLink]="['./general']"
routerLinkActive
#general="routerLinkActive"
[active]="general.isActive"
>
{{ 'labels.inputs.General' | translate }}
</a>
<a
mat-tab-link
[routerLink]="['./transactions']"
routerLinkActive
#transactions="routerLinkActive"
[active]="transactions.isActive"
>
{{ 'labels.inputs.Transactions' | translate }}
</a>
<a
mat-tab-link
[routerLink]="['./charges']"
routerLinkActive
#charges="routerLinkActive"
[active]="charges.isActive"
>
{{ 'labels.inputs.Charges' | translate }}
</a>
<a
mat-tab-link
[routerLink]="['./documents']"
routerLinkActive
#savingsDocuments="routerLinkActive"
[active]="savingsDocuments.isActive"
>
{{ 'labels.inputs.Documents' | translate }}
</a>
<a
mat-tab-link
*mifosxHasPermission="'READ_SAVINGSNOTE'"
[routerLink]="['./notes']"
routerLinkActive
#notes="routerLinkActive"
[active]="notes.isActive"
>
{{ 'labels.inputs.Notes' | translate }}
</a>
<ng-container *mifosxHasPermission="'READ_SAVINGSACCOUNTCHARGE'">
@if (isActive) {
<nav mat-tab-nav-bar class="navigation-tabs" [tabPanel]="tabPanel">
<a
mat-tab-link
[routerLink]="['./standing-instructions']"
[routerLink]="['./general']"
routerLinkActive
#standingInstructions="routerLinkActive"
[active]="standingInstructions.isActive"
*ngIf="savingsAccountData.clientId"
#general="routerLinkActive"
[active]="general.isActive"
>
{{ 'labels.inputs.Standing Instructions' | translate }}
{{ 'labels.inputs.General' | translate }}
</a>
</ng-container>
<ng-container *ngFor="let savingsDatatable of savingsDatatables">
<a
mat-tab-link
*mifosxHasPermission="'READ_' + savingsDatatable.registeredTableName"
[routerLink]="['./datatables', savingsDatatable.registeredTableName]"
[routerLink]="['./transactions']"
routerLinkActive
#datatable="routerLinkActive"
[active]="datatable.isActive"
#transactions="routerLinkActive"
[active]="transactions.isActive"
>
{{ savingsDatatable.registeredTableName }}
{{ 'labels.inputs.Transactions' | translate }}
</a>
</ng-container>
</nav>
<a
mat-tab-link
[routerLink]="['./charges']"
routerLinkActive
#charges="routerLinkActive"
[active]="charges.isActive"
>
{{ 'labels.inputs.Charges' | translate }}
</a>
<a
mat-tab-link
[routerLink]="['./documents']"
routerLinkActive
#savingsDocuments="routerLinkActive"
[active]="savingsDocuments.isActive"
>
{{ 'labels.inputs.Documents' | translate }}
</a>
<a
mat-tab-link
*mifosxHasPermission="'READ_SAVINGSNOTE'"
[routerLink]="['./notes']"
routerLinkActive
#notes="routerLinkActive"
[active]="notes.isActive"
>
{{ 'labels.inputs.Notes' | translate }}
</a>
<ng-container *mifosxHasPermission="'READ_SAVINGSACCOUNTCHARGE'">
@if (savingsAccountData.clientId) {
<a
mat-tab-link
[routerLink]="['./standing-instructions']"
routerLinkActive
#standingInstructions="routerLinkActive"
[active]="standingInstructions.isActive"
>
{{ 'labels.inputs.Standing Instructions' | translate }}
</a>
}
</ng-container>
@for (savingsDatatable of savingsDatatables; track savingsDatatable) {
<a
mat-tab-link
*mifosxHasPermission="'READ_' + savingsDatatable.registeredTableName"
[routerLink]="['./datatables', savingsDatatable.registeredTableName]"
routerLinkActive
#datatable="routerLinkActive"
[active]="datatable.isActive"
>
{{ savingsDatatable.registeredTableName }}
</a>
}
</nav>
}
<mat-tab-nav-panel #tabPanel>
<router-outlet></router-outlet>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { ActivatedRoute, Router, RouterLinkActive, RouterLink, RouterOutlet } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
@@ -27,7 +27,7 @@ import {
MatCardContent
} from '@angular/material/card';
import { MatTooltip } from '@angular/material/tooltip';
import { NgIf, NgClass, NgFor, CurrencyPipe } from '@angular/common';
import { NgClass, CurrencyPipe } from '@angular/common';
import { LongTextComponent } from '../../shared/long-text/long-text.component';
import { AccountNumberComponent } from '../../shared/account-number/account-number.component';
import { MatIconButton } from '@angular/material/button';
@@ -71,6 +71,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class SavingsAccountViewComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private savingsService = inject(SavingsService);
private translateService = inject(TranslateService);
dialog = inject(MatDialog);
/** Savings Account Data */
savingsAccountData: any;
/** Savings Data Tables */
@@ -89,13 +95,7 @@ export class SavingsAccountViewComponent implements OnInit {
* @param {Router} router Router
* @param {SavingsService} savingsService Savings Service
*/
constructor(
private route: ActivatedRoute,
private router: Router,
private savingsService: SavingsService,
private translateService: TranslateService,
public dialog: MatDialog
) {
constructor() {
this.route.data.subscribe((data: { savingsAccountData: any; savingsDatatables: any }) => {
this.savingsAccountData = data.savingsAccountData;
this.currency = this.savingsAccountData.currency;
@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute } from '@angular/router';
import { SavingsService } from 'app/savings/savings.service';
@@ -17,6 +17,11 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class SavingsDocumentsTabComponent {
private route = inject(ActivatedRoute);
private savingsService = inject(SavingsService);
private settingsService = inject(SettingsService);
dialog = inject(MatDialog);
/** Stores the resolved savings documents data */
entityDocuments: any;
/** Stores the saving Account Id */
@@ -27,12 +32,7 @@ export class SavingsDocumentsTabComponent {
* Retrieves the savings data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(
private route: ActivatedRoute,
private savingsService: SavingsService,
private settingsService: SettingsService,
public dialog: MatDialog
) {
constructor() {
this.route.data.subscribe((data: { savingsDocuments: any }) => {
this.setSavingsDocumentsData(data.savingsDocuments);
});
@@ -47,29 +47,33 @@
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Actions' | translate }}</th>
<td mat-cell *matCellDef="let instruction">
<span *ngIf="instruction.status.value !== 'Deleted'">
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Edit Standing Instruction' | translate }}"
*mifosxHasPermission="'UPDATE_STANDINGINSTRUCTION'"
>
<i class="fa fa-edit"></i>
</button>
</span>
<span *ngIf="instruction.status.value !== 'Deleted'">
<button
class="account-action-button"
mat-raised-button
color="warn"
matTooltip="{{ 'tooltips.Delete Standing Instruction' | translate }}"
*mifosxHasPermission="'DELETE_STANDINGINSTRUCTION'"
(click)="deleteStandingInstruction(instruction.id)"
>
<i class="fa fa-times"></i>
</button>
</span>
@if (instruction.status.value !== 'Deleted') {
<span>
<button
class="account-action-button"
mat-raised-button
color="primary"
matTooltip="{{ 'tooltips.Edit Standing Instruction' | translate }}"
*mifosxHasPermission="'UPDATE_STANDINGINSTRUCTION'"
>
<i class="fa fa-edit"></i>
</button>
</span>
}
@if (instruction.status.value !== 'Deleted') {
<span>
<button
class="account-action-button"
mat-raised-button
color="warn"
matTooltip="{{ 'tooltips.Delete Standing Instruction' | translate }}"
*mifosxHasPermission="'DELETE_STANDINGINSTRUCTION'"
(click)="deleteStandingInstruction(instruction.id)"
>
<i class="fa fa-times"></i>
</button>
</span>
}
<button
class="account-action-button"
mat-raised-button
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import {
MatTableDataSource,
@@ -51,6 +51,12 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class StandingInstructionsTabComponent implements OnInit {
private route = inject(ActivatedRoute);
private savingsService = inject(SavingsService);
private dialog = inject(MatDialog);
private accountTransfersService = inject(AccountTransfersService);
private settingsService = inject(SettingsService);
/** Savings Data */
savingsData: any;
/** Instructions Data */
@@ -76,13 +82,7 @@ export class StandingInstructionsTabComponent implements OnInit {
* @param {ActivatedRoute} route Activated Route.
* @param {SettingsService} settingsService Setting service
*/
constructor(
private route: ActivatedRoute,
private savingsService: SavingsService,
private dialog: MatDialog,
private accountTransfersService: AccountTransfersService,
private settingsService: SettingsService
) {
constructor() {
this.route.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.savingsData = data.savingsAccountData;
});
@@ -45,4 +45,6 @@
</div>
</form>
<iframe *ngIf="!hideOutput" [src]="pentahoUrl" frameborder="0" width="100%" height="750px;"></iframe>
@if (!hideOutput) {
<iframe [src]="pentahoUrl" frameborder="0" width="100%" height="750px;"></iframe>
}
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
import { ActivatedRoute, RouterLink } from '@angular/router';
@@ -24,6 +24,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ExportTransactionsComponent implements OnInit {
private sanitizer = inject(DomSanitizer);
private reportsService = inject(ReportsService);
private formBuilder = inject(UntypedFormBuilder);
private dateUtils = inject(Dates);
private route = inject(ActivatedRoute);
private settingsService = inject(SettingsService);
/** Minimum date allowed. */
minDate = new Date(2000, 0, 1);
/** Maximum date allowed. */
@@ -46,14 +53,7 @@ export class ExportTransactionsComponent implements OnInit {
* @param {ActivatedRoute} route Activated Route
* @param {SettingsService} settingsService Settings Service
*/
constructor(
private sanitizer: DomSanitizer,
private reportsService: ReportsService,
private formBuilder: UntypedFormBuilder,
private dateUtils: Dates,
private route: ActivatedRoute,
private settingsService: SettingsService
) {
constructor() {
this.route.parent.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.savingsAccountId = data.savingsAccountData.accountNo;
});
@@ -1,17 +1,19 @@
<div class="container">
<div class="mat-elevation-z1 m-b-25" [hidden]="!accountWithTransactions">
<div class="layout-row align-end">
<div class="action-button m-b-20 layout-row gap-20px" *ngIf="checkStatus()">
<mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="accruals">
{{ 'labels.inputs.Hide Reversed' | translate }}</mat-checkbox
>
<mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="accruals">
{{ 'labels.inputs.Hide Accruals' | translate }}</mat-checkbox
>
<button mat-raised-button color="primary" [routerLink]="['export']">
{{ 'labels.buttons.Export' | translate }}
</button>
</div>
@if (checkStatus()) {
<div class="action-button m-b-20 layout-row gap-20px">
<mat-checkbox [formControl]="hideReversedParam" (click)="hideReversed()" class="accruals">
{{ 'labels.inputs.Hide Reversed' | translate }}</mat-checkbox
>
<mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="accruals">
{{ 'labels.inputs.Hide Accruals' | translate }}</mat-checkbox
>
<button mat-raised-button color="primary" [routerLink]="['export']">
{{ 'labels.buttons.Export' | translate }}
</button>
</div>
}
</div>
<table mat-table [dataSource]="dataSource" matSort>
@@ -118,16 +120,18 @@
<mat-icon><fa-icon icon="eye" size="sm"></fa-icon></mat-icon>
<span>{{ 'labels.text.View Transaction' | translate }}</span>
</button>
<span *ngIf="!transaction.reversed">
<button
mat-menu-item
*mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction(transaction, $event)"
>
<mat-icon><fa-icon icon="undo" size="sm"></fa-icon></mat-icon>
<span>{{ 'tooltips.Undo Transaction' | translate }}</span>
</button>
</span>
@if (!transaction.reversed) {
<span>
<button
mat-menu-item
*mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction(transaction, $event)"
>
<mat-icon><fa-icon icon="undo" size="sm"></fa-icon></mat-icon>
<span>{{ 'tooltips.Undo Transaction' | translate }}</span>
</button>
</span>
}
<button
mat-menu-item
class="account-action-button"
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { Component, OnInit, ViewChild, inject } from '@angular/core';
import { UntypedFormControl, ReactiveFormsModule } from '@angular/forms';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort, MatSortHeader } from '@angular/material/sort';
@@ -26,7 +26,7 @@ import { SavingsService } from 'app/savings/savings.service';
import { SettingsService } from 'app/settings/settings.service';
import { UndoTransactionDialogComponent } from '../custom-dialogs/undo-transaction-dialog/undo-transaction-dialog.component';
import { MatDialog } from '@angular/material/dialog';
import { NgIf, NgClass } from '@angular/common';
import { NgClass } from '@angular/common';
import { MatCheckbox } from '@angular/material/checkbox';
import { MatButton, MatIconButton } from '@angular/material/button';
import { ExternalIdentifierComponent } from '../../../shared/external-identifier/external-identifier.component';
@@ -73,6 +73,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class TransactionsTabComponent implements OnInit {
private route = inject(ActivatedRoute);
private router = inject(Router);
private savingsService = inject(SavingsService);
private settingsService = inject(SettingsService);
private dialog = inject(MatDialog);
private dateUtils = inject(Dates);
/** Savings Account Status */
status: any;
/** Transactions Data */
@@ -105,14 +112,7 @@ export class TransactionsTabComponent implements OnInit {
* Retrieves savings account data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(
private route: ActivatedRoute,
private router: Router,
private savingsService: SavingsService,
private settingsService: SettingsService,
private dialog: MatDialog,
private dateUtils: Dates
) {
constructor() {
this.route.parent.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.transactionsData = data.savingsAccountData.transactions;
this.status = data.savingsAccountData.status.value;
@@ -14,10 +14,12 @@
/>
<mat-datepicker-toggle matSuffix [for]="dueDatePicker"></mat-datepicker-toggle>
<mat-datepicker #dueDatePicker></mat-datepicker>
<mat-error *ngIf="editTransactionForm.controls.transactionDate.hasError('required')">
{{ 'labels.inputs.Transaction Date' | translate }} {{ 'labels.commons.is' | translate }}
<strong>{{ 'labels.commons.required' | translate }}</strong>
</mat-error>
@if (editTransactionForm.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
@@ -31,9 +33,11 @@
<mat-form-field>
<mat-label>{{ 'labels.inputs.Payment Type' | translate }}</mat-label>
<mat-select formControlName="paymentTypeId">
<mat-option *ngFor="let paymentType of paymentTypeOptions" [value]="paymentType.id">
{{ paymentType.name }}
</mat-option>
@for (paymentType of paymentTypeOptions; track paymentType) {
<mat-option [value]="paymentType.id">
{{ paymentType.name }}
</mat-option>
}
</mat-select>
</mat-form-field>
@@ -47,30 +51,40 @@
</span>
</div>
<mat-form-field *ngIf="editTransactionForm.controls['accountNumber']">
<mat-label>{{ 'labels.inputs.Account Number' | translate }}</mat-label>
<input type="number" formControlName="accountNumber" matInput />
</mat-form-field>
@if (editTransactionForm.controls['accountNumber']) {
<mat-form-field>
<mat-label>{{ 'labels.inputs.Account Number' | translate }}</mat-label>
<input type="number" formControlName="accountNumber" matInput />
</mat-form-field>
}
<mat-form-field *ngIf="editTransactionForm.controls['checkNumber']">
<mat-label>{{ 'labels.inputs.Cheque' | translate }}</mat-label>
<input type="number" formControlName="checkNumber" matInput />
</mat-form-field>
@if (editTransactionForm.controls['checkNumber']) {
<mat-form-field>
<mat-label>{{ 'labels.inputs.Cheque' | translate }}</mat-label>
<input type="number" formControlName="checkNumber" matInput />
</mat-form-field>
}
<mat-form-field *ngIf="editTransactionForm.controls['routingCode']">
<mat-label>{{ 'labels.inputs.Routing Code' | translate }}</mat-label>
<input formControlName="routingCode" matInput />
</mat-form-field>
@if (editTransactionForm.controls['routingCode']) {
<mat-form-field>
<mat-label>{{ 'labels.inputs.Routing Code' | translate }}</mat-label>
<input formControlName="routingCode" matInput />
</mat-form-field>
}
<mat-form-field *ngIf="editTransactionForm.controls['receiptNumber']">
<mat-label>{{ 'labels.inputs.Receipt Number' | translate }}</mat-label>
<input formControlName="receiptNumber" matInput />
</mat-form-field>
@if (editTransactionForm.controls['receiptNumber']) {
<mat-form-field>
<mat-label>{{ 'labels.inputs.Receipt Number' | translate }}</mat-label>
<input formControlName="receiptNumber" matInput />
</mat-form-field>
}
<mat-form-field *ngIf="editTransactionForm.controls['bankNumber']">
<mat-label>{{ 'labels.inputs.Bank' | translate }}</mat-label>
<input formControlName="bankNumber" matInput />
</mat-form-field>
@if (editTransactionForm.controls['bankNumber']) {
<mat-form-field>
<mat-label>{{ 'labels.inputs.Bank' | translate }}</mat-label>
<input formControlName="bankNumber" matInput />
</mat-form-field>
}
<mat-card-actions class="layout-row layout-xs-column layout-align-center gap-5px">
<button type="button" mat-raised-button [routerLink]="['../']">
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import {
UntypedFormGroup,
UntypedFormBuilder,
@@ -32,6 +32,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class EditTransactionComponent implements OnInit {
private formBuilder = inject(UntypedFormBuilder);
private route = inject(ActivatedRoute);
private router = inject(Router);
private dateUtils = inject(Dates);
private savingsService = inject(SavingsService);
private settingsService = inject(SettingsService);
/** Minimum Due Date allowed. */
minDate = new Date(2000, 0, 1);
/** Maximum Due Date allowed. */
@@ -63,14 +70,7 @@ export class EditTransactionComponent implements OnInit {
* @param {Router} router Router for navigation.
* @param {SettingsService} settingsService Setting service
*/
constructor(
private formBuilder: UntypedFormBuilder,
private route: ActivatedRoute,
private router: Router,
private dateUtils: Dates,
private savingsService: SavingsService,
private settingsService: SettingsService
) {
constructor() {
this.route.data.subscribe((data: { savingsAccountTransactionTemplate: any }) => {
this.transactionTemplateData = data.savingsAccountTransactionTemplate;
if (data.savingsAccountTransactionTemplate.currency) {
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
@@ -18,6 +18,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ViewRecieptComponent implements OnInit {
private sanitizer = inject(DomSanitizer);
private route = inject(ActivatedRoute);
/** trusted resource url for pentaho output */
pentahoUrl: any;
/** Transaction Reciept Data */
@@ -28,10 +31,7 @@ export class ViewRecieptComponent implements OnInit {
* @param {DomSanitizer} sanitizer DOM Sanitizer
* @param {ActivatedRoute} route Activated Route
*/
constructor(
private sanitizer: DomSanitizer,
private route: ActivatedRoute
) {
constructor() {
this.route.data.subscribe((data: { savingsTransactionReciept: any }) => {
this.transactionRecieptData = data.savingsTransactionReciept;
});
@@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component, OnInit, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { EntityDatatableTabComponent } from '../../../../../shared/tabs/entity-datatable-tab/entity-datatable-tab.component';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
@@ -13,13 +13,15 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class DatatableTransactionTabComponent {
private route = inject(ActivatedRoute);
/** Transaction Id */
entityId: string;
/** Savings Datatable */
entityDatatable: any;
/** Multi Row Datatable Flag */
multiRowDatatableFlag: boolean;
constructor(private route: ActivatedRoute) {
constructor() {
this.entityId = this.route.parent.parent.snapshot.paramMap.get('id');
this.route.data.subscribe((data: { transactionDatatable: any }) => {
this.entityDatatable = data.transactionDatatable;
@@ -1,48 +1,49 @@
<div class="container transaction-buttons m-b-20 align-end-center gap-2percent" align="end">
<span
*ngIf="
!(
transactionData.interestedPostedAsOn === false &&
(transactionData.transactionType.id === 17 || transactionData.transactionType.id === 3)
)
"
>
<span *mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'">
<button
mat-raised-button
color="primary"
*ngIf="
@if (
!(
transactionData.interestedPostedAsOn === false &&
(transactionData.transactionType.id === 17 || transactionData.transactionType.id === 3)
)
) {
<span>
<span *mifosxHasPermission="'ADJUSTTRANSACTION_SAVINGSACCOUNT'">
@if (
transactionData.transactionType.value === 'Transfer' ||
transactionData.reversed === 'true' ||
transactionData.transactionType.id === 3 ||
transactionData.transactionType.id === 17
"
[routerLink]="'edit'"
) {
<button mat-raised-button color="primary" [routerLink]="'edit'">
<fa-icon icon="edit" class="m-r-10"></fa-icon>{{ 'labels.buttons.Edit' | translate }}
</button>
}
</span>
</span>
}
@if (!transactionData.reversed && transactionData.transactionType.amountHold) {
<span>
<button
mat-raised-button
color="primary"
*mifosxHasPermission="'RELEASEAMOUNT_SAVINGSACCOUNT'"
(click)="releaseAmount()"
>
<fa-icon icon="edit" class="m-r-10"></fa-icon>{{ 'labels.buttons.Edit' | translate }}
<fa-icon icon="lock-open" class="m-r-10"></fa-icon>{{ 'labels.buttons.Release Amount' | translate }}
</button>
</span>
</span>
<span *ngIf="!transactionData.reversed && transactionData.transactionType.amountHold">
<button
mat-raised-button
color="primary"
*mifosxHasPermission="'RELEASEAMOUNT_SAVINGSACCOUNT'"
(click)="releaseAmount()"
>
<fa-icon icon="lock-open" class="m-r-10"></fa-icon>{{ 'labels.buttons.Release Amount' | translate }}
</button>
</span>
<span *ngIf="allowUndo()">
<button
mat-raised-button
color="warn"
*mifosxHasPermission="'UNDOTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction()"
>
<fa-icon icon="undo" class="m-r-10"></fa-icon>{{ 'labels.buttons.Undo' | translate }}
</button>
</span>
}
@if (allowUndo()) {
<span>
<button
mat-raised-button
color="warn"
*mifosxHasPermission="'UNDOTRANSACTION_SAVINGSACCOUNT'"
(click)="undoTransaction()"
>
<fa-icon icon="undo" class="m-r-10"></fa-icon>{{ 'labels.buttons.Undo' | translate }}
</button>
</span>
}
</div>
<div class="container">
@@ -91,19 +92,22 @@
{{ transactionData.amount | currency: transactionData.currency.code : 'symbol-narrow' : '1.2-2' }}
</div>
<div class="flex-50 mat-body-strong" *ngIf="transactionData.note">
{{ 'labels.inputs.Note' | translate }}
</div>
@if (transactionData.note) {
<div class="flex-50 mat-body-strong">
{{ 'labels.inputs.Note' | translate }}
</div>
}
<div class="flex-50" *ngIf="transactionData.note">
{{ transactionData.note }}
</div>
@if (transactionData.note) {
<div class="flex-50">
{{ transactionData.note }}
</div>
}
<mifosx-transaction-payment-detail
*ngIf="transactionData.paymentDetailData"
[paymentDetailData]="transactionData.paymentDetailData"
>
</mifosx-transaction-payment-detail>
@if (transactionData.paymentDetailData) {
<mifosx-transaction-payment-detail [paymentDetailData]="transactionData.paymentDetailData">
</mifosx-transaction-payment-detail>
}
</div>
<div class="layout-row layout-align-center gap-2percent column-on-mobile">
@@ -1,4 +1,4 @@
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { Dates } from 'app/core/utils/dates';
@@ -6,7 +6,7 @@ import { ReleaseAmountDialogComponent } from 'app/savings/savings-account-view/c
import { UndoTransactionDialogComponent } from 'app/savings/savings-account-view/custom-dialogs/undo-transaction-dialog/undo-transaction-dialog.component';
import { SavingsService } from 'app/savings/savings.service';
import { SettingsService } from 'app/settings/settings.service';
import { NgIf, NgClass, CurrencyPipe } from '@angular/common';
import { NgClass, CurrencyPipe } from '@angular/common';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { TransactionPaymentDetailComponent } from '../../../../../shared/transaction-payment-detail/transaction-payment-detail.component';
import { DateFormatPipe } from '../../../../../pipes/date-format.pipe';
@@ -26,18 +26,18 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class SavingsTransactionGeneralTabComponent {
private savingsService = inject(SavingsService);
private route = inject(ActivatedRoute);
private dateUtils = inject(Dates);
private router = inject(Router);
dialog = inject(MatDialog);
private settingsService = inject(SettingsService);
accountId: string;
transactionId: string;
transactionData: any;
constructor(
private savingsService: SavingsService,
private route: ActivatedRoute,
private dateUtils: Dates,
private router: Router,
public dialog: MatDialog,
private settingsService: SettingsService
) {
constructor() {
this.route.data.subscribe((data: { savingsAccountTransaction: any }) => {
this.accountId = this.route.parent.snapshot.params['savingAccountId'];
this.transactionData = data.savingsAccountTransaction;
@@ -9,7 +9,7 @@
>
{{ 'labels.heading.General' | translate }}
</a>
<ng-container *ngFor="let entityDatatable of entityDatatables">
@for (entityDatatable of entityDatatables; track entityDatatable) {
<a
mat-tab-link
[routerLink]="['./datatables', entityDatatable.registeredTableName]"
@@ -20,7 +20,7 @@
>
{{ entityDatatable.registeredTableName }}
</a>
</ng-container>
}
</nav>
<mat-tab-nav-panel #tabPanel>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute, RouterLinkActive, RouterLink, RouterOutlet } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
import { MatTabNav, MatTabLink, MatTabNavPanel } from '@angular/material/tabs';
@@ -19,6 +19,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ViewTransactionComponent {
private route = inject(ActivatedRoute);
dialog = inject(MatDialog);
/** Transaction data. */
transactionData: any;
@@ -30,10 +33,7 @@ export class ViewTransactionComponent {
* @param {Router} router Router for navigation.
* @param {MatDialog} dialog Dialog reference.
*/
constructor(
private route: ActivatedRoute,
public dialog: MatDialog
) {
constructor() {
this.route.data.subscribe((data: { transactionDatatables: any }) => {
this.accountId = this.route.snapshot.params['savingAccountId'];
this.entityDatatables = data.transactionDatatables;
@@ -1,41 +1,56 @@
<div
*ngIf="savingsAccountData.status.value === 'Active' && chargeData.amountOutstanding !== 0"
class="layout-row align-end gap-2percent layout-xs-column container m-b-20"
>
<button mat-raised-button color="accent" *mifosxHasPermission="'PAY_SAVINGSACCOUNTCHARGE'" (click)="payCharge()">
<fa-icon icon="dollar-sign" class="m-r-10"></fa-icon>
Pay
</button>
<button mat-raised-button color="primary" *mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'" (click)="waiveCharge()">
<fa-icon icon="flag" class="m-r-10"></fa-icon>
Waive
</button>
<span *ngIf="isRecurringCharge()">
@if (savingsAccountData.status.value === 'Active' && chargeData.amountOutstanding !== 0) {
<div class="layout-row align-end gap-2percent layout-xs-column container m-b-20">
<button mat-raised-button color="accent" *mifosxHasPermission="'PAY_SAVINGSACCOUNTCHARGE'" (click)="payCharge()">
<fa-icon icon="dollar-sign" class="m-r-10"></fa-icon>
Pay
</button>
<button
mat-raised-button
color="primary"
*mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'"
(click)="waiveCharge()"
>
<fa-icon icon="flag" class="m-r-10"></fa-icon>
Waive
</button>
@if (isRecurringCharge()) {
<span>
<button
mat-raised-button
color="warn"
*mifosxHasPermission="'INACTIVATE_SAVINGSACCOUNTCHARGE'"
(click)="inactivateCharge()"
>
<fa-icon icon="trash" class="m-r-10"></fa-icon>
Inactivate
</button>
</span>
}
</div>
}
@if (savingsAccountData.status.value === 'Submitted and pending approval') {
<div class="layout-row align-end gap-2percent layout-xs-column container m-b-20">
<button
mat-raised-button
color="primary"
*mifosxHasPermission="'UPDATE_SAVINGSACCOUNTCHARGE'"
(click)="editCharge()"
>
<fa-icon icon="edit" class="m-r-10"></fa-icon>
Edit
</button>
<button
mat-raised-button
color="warn"
*mifosxHasPermission="'INACTIVATE_SAVINGSACCOUNTCHARGE'"
(click)="inactivateCharge()"
*mifosxHasPermission="'DELETE_SAVINGSACCOUNTCHARGE'"
(click)="deleteCharge()"
>
<fa-icon icon="trash" class="m-r-10"></fa-icon>
Inactivate
Delete
</button>
</span>
</div>
<div
*ngIf="savingsAccountData.status.value === 'Submitted and pending approval'"
class="layout-row align-end gap-2percent layout-xs-column container m-b-20"
>
<button mat-raised-button color="primary" *mifosxHasPermission="'UPDATE_SAVINGSACCOUNTCHARGE'" (click)="editCharge()">
<fa-icon icon="edit" class="m-r-10"></fa-icon>
Edit
</button>
<button mat-raised-button color="warn" *mifosxHasPermission="'DELETE_SAVINGSACCOUNTCHARGE'" (click)="deleteCharge()">
<fa-icon icon="trash" class="m-r-10"></fa-icon>
Delete
</button>
</div>
</div>
}
<div class="container">
<mat-card>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component } from '@angular/core';
import { Component, inject } from '@angular/core';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { MatDialog } from '@angular/material/dialog';
@@ -38,6 +38,13 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
]
})
export class ViewChargeComponent {
private savingsService = inject(SavingsService);
private route = inject(ActivatedRoute);
private dateUtils = inject(Dates);
private router = inject(Router);
dialog = inject(MatDialog);
private settingsService = inject(SettingsService);
/** Charge data. */
chargeData: any;
/** Savings Account Data */
@@ -52,14 +59,7 @@ export class ViewChargeComponent {
* @param {Dates} dateUtils Date Utils.
* @param {SettingsService} settingsService Setting service
*/
constructor(
private savingsService: SavingsService,
private route: ActivatedRoute,
private dateUtils: Dates,
private router: Router,
public dialog: MatDialog,
private settingsService: SettingsService
) {
constructor() {
this.route.data.subscribe((data: { savingsAccountCharge: any }) => {
this.chargeData = data.savingsAccountCharge;
});
@@ -87,7 +87,6 @@ export class ViewChargeComponent {
type: 'date',
required: true
})
];
const data = {
title: 'Pay Charge',
@@ -160,7 +159,6 @@ export class ViewChargeComponent {
type: 'number',
required: true
})
];
const data = {
title: 'Edit Charge',