- 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>
270 lines
11 KiB
HTML
270 lines
11 KiB
HTML
<!--
|
|
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="responsive-column">
|
|
<h3 class="mat-h3 flex-fill">{{ 'labels.heading.Details' | translate }}</h3>
|
|
|
|
<mat-divider class="flex-fill"></mat-divider>
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Product' | translate }}</span>
|
|
<span class="flex-60">{{
|
|
currentAccount.productId | find: currentAccountTemplate.productOptions : 'id' : 'name'
|
|
}}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Submitted On' | translate }}</span>
|
|
<span class="flex-60">{{ currentAccount.submittedOnDate | dateFormat }}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.External Id' | translate }}</span>
|
|
@if (currentAccount.externalId) {
|
|
<span class="flex-60">
|
|
<mifosx-external-identifier externalId="{{ currentAccount.externalId }}"></mifosx-external-identifier>
|
|
</span>
|
|
}
|
|
@if (!currentAccount.externalId) {
|
|
<span class="flex-60">
|
|
{{ 'labels.inputs.Unassigned' | translate }}
|
|
</span>
|
|
}
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Field Officer' | translate }}</span>
|
|
<span class="flex-60">{{
|
|
currentAccount.fieldOfficerId | find: currentAccountProductTemplate.fieldOfficerOptions : 'id' : 'displayName'
|
|
}}</span>
|
|
</div>
|
|
|
|
@if (activeClientMembers) {
|
|
<h3 class="mat-h3 margin-t flex-fill">{{ 'labels.heading.Client Members' | translate }}</h3>
|
|
<mat-divider class="flex-fill"></mat-divider>
|
|
<div class="flex-60">
|
|
<table mat-table #membersTable [dataSource]="dataSource">
|
|
<!-- ID Column -->
|
|
<ng-container matColumnDef="id">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Client ID' | translate }}</th>
|
|
<td mat-cell *matCellDef="let element">{{ element.id }}</td>
|
|
</ng-container>
|
|
<!-- Name Column -->
|
|
<ng-container matColumnDef="name">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Client Name' | translate }}</th>
|
|
<td mat-cell *matCellDef="let element">{{ element.displayName }}</td>
|
|
</ng-container>
|
|
<tr mat-header-row *matHeaderRowDef="membersDisplayedColumns"></tr>
|
|
<tr mat-row *matRowDef="let row; columns: membersDisplayedColumns"></tr>
|
|
</table>
|
|
</div>
|
|
}
|
|
|
|
<h3 class="mat-h3 margin-t flex-fill">{{ 'labels.heading.Terms' | translate }}</h3>
|
|
|
|
<mat-divider class="flex-fill"></mat-divider>
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Currency' | translate }}</span>
|
|
<span class="flex-60">{{ currentAccountTermsForm.get('currencyCode').value }}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Decimal Places' | translate }}</span>
|
|
<span class="flex-60">{{ currentAccountTermsForm.get('decimal').value }}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Nominal Annual Interest' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.nominalAnnualInterestRate | formatNumber }} %</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Interest Compounding Period' | translate }}:</span>
|
|
<span class="flex-60">{{
|
|
getCatalogTranslation(
|
|
currentAccount.interestCompoundingPeriodType
|
|
| find: currentAccountProductTemplate.interestCompoundingPeriodTypeOptions : 'id' : 'value'
|
|
)
|
|
}}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Interest Posting Period' | translate }}:</span>
|
|
<span class="flex-60">{{
|
|
getCatalogTranslation(
|
|
currentAccount.interestPostingPeriodType
|
|
| find: currentAccountProductTemplate.interestPostingPeriodTypeOptions : 'id' : 'value'
|
|
)
|
|
}}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Interest Calculated using' | translate }}:</span>
|
|
<span class="flex-60">{{
|
|
getCatalogTranslation(
|
|
currentAccount.interestCalculationType
|
|
| find: currentAccountProductTemplate.interestCalculationTypeOptions : 'id' : 'value'
|
|
)
|
|
}}</span>
|
|
</div>
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Days in Year' | translate }}:</span>
|
|
<span class="flex-60">{{
|
|
getCatalogTranslation(
|
|
currentAccount.interestCalculationDaysInYearType
|
|
| find: currentAccountProductTemplate.interestCalculationDaysInYearTypeOptions : 'id' : 'value'
|
|
)
|
|
}}</span>
|
|
</div>
|
|
|
|
@if (currentAccount.minRequiredOpeningBalance) {
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Minimum Opening Balance' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.minRequiredOpeningBalance | formatNumber }}</span>
|
|
</div>
|
|
}
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Apply Withdrawal Fee for Transfers' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.withdrawalFeeForTransfers | yesNo }}</span>
|
|
</div>
|
|
|
|
@if (currentAccount.lockinPeriodFrequency) {
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Lock-in Period' | translate }}:</span>
|
|
<span class="flex-60">{{
|
|
getCatalogTranslation(
|
|
currentAccount.lockinPeriodFrequency +
|
|
' ' +
|
|
(currentAccount.lockinPeriodFrequencyType
|
|
| find: currentAccountProductTemplate.lockinPeriodFrequencyTypeOptions : 'id' : 'value')
|
|
)
|
|
}}</span>
|
|
</div>
|
|
}
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Is Overdraft Allowed' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.allowOverdraft | yesNo }}</span>
|
|
</div>
|
|
|
|
@if (currentAccount.minOverdraftForInterestCalculation) {
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40"
|
|
>{{ 'labels.inputs.Minimum Overdraft Required for Interest Calculation' | translate }}:</span
|
|
>
|
|
<span class="flex-60">{{ currentAccount.minOverdraftForInterestCalculation | formatNumber }}</span>
|
|
</div>
|
|
}
|
|
|
|
@if (currentAccount.nominalAnnualInterestRateOverdraft) {
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Nominal Annual Interest for Overdraft' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.nominalAnnualInterestRateOverdraft | formatNumber }} %</span>
|
|
</div>
|
|
}
|
|
|
|
@if (currentAccount.overdraftLimit) {
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Maximum Overdraft Amount Limit' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.overdraftLimit | formatNumber }}</span>
|
|
</div>
|
|
}
|
|
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Enforce Minimum Balance' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.enforceMinRequiredBalance | yesNo }}</span>
|
|
</div>
|
|
|
|
@if (currentAccount.minRequiredBalance) {
|
|
<div class="flex-fill layout-row">
|
|
<span class="flex-40">{{ 'labels.inputs.Minimum Balance' | translate }}:</span>
|
|
<span class="flex-60">{{ currentAccount.minRequiredBalance }}</span>
|
|
</div>
|
|
}
|
|
|
|
@if (currentAccount.charges.length) {
|
|
<div class="layout-row-wrap responsive-column flex-fill">
|
|
<h3 class="mat-h3 flex-fill">{{ 'labels.inputs.Charges' | translate }}</h3>
|
|
<mat-divider class="flex-fill"></mat-divider>
|
|
<table class="flex-fill mat-elevation-z1" mat-table [dataSource]="currentAccount.charges">
|
|
<ng-container matColumnDef="name">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Name' | translate }}</th>
|
|
<td mat-cell *matCellDef="let charge">
|
|
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
|
</td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="chargeCalculationType">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Type' | translate }}</th>
|
|
<td mat-cell *matCellDef="let charge">
|
|
{{ charge.chargeCalculationType.value | translateKey: 'catalogs' }}
|
|
</td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="amount">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Amount' | translate }}</th>
|
|
<td mat-cell *matCellDef="let charge">
|
|
{{ charge.amount | formatNumber }}
|
|
</td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="date">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Date' | translate }}</th>
|
|
<td mat-cell *matCellDef="let charge">
|
|
@if (charge.chargeTimeType.value === 'Specified due date' || charge.chargeTimeType.value === 'Weekly Fee') {
|
|
<span>
|
|
{{ (charge.dueDate | dateFormat) || 'Unassigned' }}
|
|
</span>
|
|
}
|
|
@if (charge.chargeTimeType.value === 'Monthly Fee' || charge.chargeTimeType.value === 'Annual Fee') {
|
|
<span>
|
|
{{ (charge.feeOnMonthDay | dateFormat) || 'Unassigned' }}
|
|
</span>
|
|
}
|
|
@if (
|
|
!(
|
|
charge.chargeTimeType.value === 'Monthly Fee' ||
|
|
charge.chargeTimeType.value === 'Annual Fee' ||
|
|
charge.chargeTimeType.value === 'Specified due date' ||
|
|
charge.chargeTimeType.value === 'Weekly Fee'
|
|
)
|
|
) {
|
|
<span> N/A </span>
|
|
}
|
|
</td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="repaymentsEvery">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Repayments Every' | translate }}</th>
|
|
<td mat-cell *matCellDef="let charge">
|
|
{{ charge.feeInterval || 'Not Provided' }}
|
|
</td>
|
|
</ng-container>
|
|
<ng-container matColumnDef="chargeTimeType">
|
|
<th mat-header-cell *matHeaderCellDef>{{ 'labels.inputs.Collected On' | translate }}</th>
|
|
<td mat-cell *matCellDef="let charge">
|
|
{{ charge.chargeTimeType.value }}
|
|
</td>
|
|
</ng-container>
|
|
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
|
|
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns"></tr>
|
|
</table>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
<div class="layout-row responsive-column align-center gap-2px margin-t">
|
|
<button mat-raised-button matStepperPrevious>
|
|
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
|
|
{{ 'labels.buttons.Previous' | translate }}
|
|
</button>
|
|
<button mat-raised-button [routerLink]="['../..']">
|
|
{{ 'labels.buttons.Cancel' | translate }}
|
|
</button>
|
|
<button mat-raised-button color="primary" (click)="submitEvent.emit()">
|
|
{{ 'labels.buttons.Submit' | translate }}
|
|
</button>
|
|
</div>
|