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:
Aditya
2026-03-17 18:23:37 +05:30
co-authored by Claude Opus 4.6
parent 73aa69ee02
commit 0a32d7135e
210 changed files with 15048 additions and 155 deletions
+51
View File
@@ -27,6 +27,57 @@
<mat-sidenav-content class="sidenav">
<!-- Toolbar -->
<mifosx-toolbar [sidenav]="sidenav" (collapse)="toggleCollapse($event)"></mifosx-toolbar>
<!-- Sub Menu Bar -->
<div class="sub-menu-bar">
<a class="sub-menu-link" tabindex="0">
<fa-icon icon="money-bill" class="sub-menu-icon" size="lg"></fa-icon>Cashier
</a>
<a class="sub-menu-link" tabindex="0">
<fa-icon icon="user-tie" class="sub-menu-icon" size="lg"></fa-icon>Officer
</a>
<a class="sub-menu-link" tabindex="0" [matMenuTriggerFor]="depositsMenu">
<fa-icon icon="piggy-bank" class="sub-menu-icon" size="lg"></fa-icon>Deposits
<fa-icon icon="caret-down" class="sub-menu-caret"></fa-icon>
</a>
<a class="sub-menu-link" tabindex="0">
<fa-icon icon="exchange" class="sub-menu-icon" size="lg"></fa-icon>Clearing
</a>
<a class="sub-menu-link" tabindex="0">
<fa-icon icon="money-check" class="sub-menu-icon" size="lg"></fa-icon>HRM
</a>
<a class="sub-menu-link" tabindex="0" [matMenuTriggerFor]="shareMenu">
<fa-icon icon="coins" class="sub-menu-icon" size="lg"></fa-icon>Share
<fa-icon icon="caret-down" class="sub-menu-caret"></fa-icon>
</a>
<a class="sub-menu-link" tabindex="0" [matMenuTriggerFor]="othersMenu">
<fa-icon icon="folder-open" class="sub-menu-icon" size="lg"></fa-icon>Others
<fa-icon icon="caret-down" class="sub-menu-caret"></fa-icon>
</a>
<a class="sub-menu-link" tabindex="0">
<fa-icon icon="exclamation-triangle" class="sub-menu-icon" size="lg"></fa-icon>NPA Module
</a>
<a class="sub-menu-link" tabindex="0">
<fa-icon icon="fingerprint" class="sub-menu-icon" size="lg"></fa-icon>CKYC Management
</a>
</div>
<!-- Sub Menu Dropdowns -->
<mat-menu #depositsMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item tabindex="0">Saving</button>
<button mat-menu-item tabindex="0">Current</button>
<button mat-menu-item tabindex="0">Fixed Deposit</button>
<button mat-menu-item tabindex="0">Recurring</button>
<button mat-menu-item tabindex="0">DDS</button>
</mat-menu>
<mat-menu #shareMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item tabindex="0">Nominal</button>
</mat-menu>
<mat-menu #othersMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item tabindex="0">Locker</button>
<button mat-menu-item tabindex="0">Investment</button>
</mat-menu>
<!-- Progress Bar -->
@if (progressBarMode !== 'none') {
<div>
+45
View File
@@ -36,6 +36,51 @@ $color: #e2e4ec;
overflow-x: hidden;
}
.sub-menu-bar {
display: flex;
flex-wrap: nowrap;
align-items: center;
background-color: #1074b9;
padding: 2px 0.5rem 2px calc(48px + 2rem);
width: 100%;
z-index: 1;
position: relative;
font-family: Roboto, 'Helvetica Neue', sans-serif;
font-size: 14px;
font-weight: 500;
letter-spacing: normal;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.sub-menu-link {
display: inline-flex;
align-items: center;
padding: 6px 0.5rem;
text-decoration: none;
font-weight: 500;
font-size: 14px;
color: rgb(255 255 255 / 70%);
white-space: nowrap;
cursor: pointer;
flex-shrink: 0;
line-height: 1;
&:hover {
color: #fff;
}
}
.sub-menu-icon {
margin-right: 0.35rem;
}
.sub-menu-caret {
margin-left: 0.35rem;
font-size: 12px;
}
@keyframes move {
0% {
left: 0;
+5 -1
View File
@@ -23,6 +23,8 @@ import { ToolbarComponent } from './toolbar/toolbar.component';
import { BreadcrumbComponent } from './breadcrumb/breadcrumb.component';
import { ContentComponent } from './content/content.component';
import { FooterComponent } from '../../shared/footer/footer.component';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { MatMenuModule } from '@angular/material/menu';
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
/**
@@ -43,7 +45,9 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
BreadcrumbComponent,
ContentComponent,
FooterComponent,
AsyncPipe
AsyncPipe,
FaIconComponent,
MatMenuModule
]
})
export class ShellComponent implements OnInit, OnDestroy {
@@ -46,6 +46,7 @@
>
<fa-icon class="mr-05" icon="university" size="lg"></fa-icon>
{{ 'labels.menus.Institution' | translate }}
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
<span class="hide-lt-md">
@@ -79,6 +80,7 @@
>
<fa-icon class="mr-05" icon="chart-bar" size="lg"></fa-icon>
{{ 'labels.menus.Reports' | translate }}
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
<a
#admin
@@ -90,35 +92,22 @@
>
<fa-icon class="mr-05" icon="shield-alt" size="lg"></fa-icon>
{{ 'labels.menus.Admin' | translate }}
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
<a #configWizard class="tab-link" (click)="openDialog()" tabindex="0" *mifosxHasPermission="'READ_CONFIG_WIZARD'">
<fa-icon class="mr-05" icon="info" size="lg"></fa-icon>
{{ 'labels.menus.Configuration Wizard' | translate }}
</a>
<a class="tab-link" [matMenuTriggerFor]="ledgerMenu" tabindex="0">
<fa-icon class="mr-05" icon="book" size="lg"></fa-icon>
Ledger
<fa-icon icon="caret-down" class="ml-05"></fa-icon>
</a>
</span>
</div>
<span class="toolbar-spacer"></span>
<div #globalSearch class="white-text-search">
<mifosx-search-tool tabindex="0"></mifosx-search-tool>
</div>
<div #languageSelector class="white-text-language">
<mifosx-language-selector class="ml-1 language hide-lt-md" tabindex="0"></mifosx-language-selector>
</div>
<button
mat-icon-button
[matMenuTriggerFor]="languageMenu"
class="show-lt-md"
tabindex="0"
[attr.aria-label]="'labels.menus.Language Selector' | translate"
matTooltip="{{ 'labels.menus.Language Selector' | translate }}"
>
<mat-icon>language</mat-icon>
</button>
<div #notifications>
<mifosx-notifications-tray #notificationsTray class="hide-lt-md" tabindex="0"></mifosx-notifications-tray>
</div>
@@ -134,11 +123,6 @@
</div>
</mat-toolbar>
<!-- Language selector menu for small screen view -->
<mat-menu #languageMenu="matMenu">
<mifosx-language-selector class="ml-1 language"></mifosx-language-selector>
</mat-menu>
<mat-menu #institutionMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item routerLink="/clients" tabindex="0" *mifosxHasPermission="'READ_CLIENT'">
{{ 'labels.menus.Clients' | translate }}
@@ -160,6 +144,12 @@
</span>
</mat-menu>
<!-- Ledger Menu -->
<mat-menu #ledgerMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item tabindex="0">Sub Ledger</button>
<button mat-menu-item tabindex="0">General Ledger</button>
</mat-menu>
<!-- Toolbar Menus -->
<mat-menu #reportsMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item [routerLink]="['/reports']" tabindex="0" *mifosxHasPermission="'READ_REPORT'">
@@ -317,54 +307,6 @@
<button mat-raised-button color="primary" (click)="popover.close(); showPopover(templateSelfService, selfService)">
{{ 'labels.buttons.Back' | translate }}
</button>
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(templateGlobalSearch, globalSearch)"
>
{{ 'labels.buttons.Next' | translate }}
</button>
</div>
</ng-template>
<ng-template #templateGlobalSearch let-popover="popover">
<h2>{{ 'labels.menus.Global Search' | translate }}</h2>
<p class="mw300">{{ 'labels.text.Navigate system selecting entity' | translate }}</p>
<div class="layout-row align-end gap-2px responsive-column">
<button mat-raised-button color="warn" (click)="popover.close(); configurationWizardService.closeConfigWizard()">
{{ 'labels.buttons.Close' | translate }}
</button>
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(templateConfigWizard, configWizard)"
>
{{ 'labels.buttons.Back' | translate }}
</button>
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(templateLanguageSelector, languageSelector)"
>
{{ 'labels.buttons.Next' | translate }}
</button>
</div>
</ng-template>
<ng-template #templateLanguageSelector let-popover="popover">
<h2>{{ 'labels.menus.Language Selector' | translate }}</h2>
<p class="mw300">{{ 'labels.text.Organization available languages' | translate }}</p>
<div class="layout-row align-end gap-2px responsive-column">
<button mat-raised-button color="warn" (click)="popover.close(); configurationWizardService.closeConfigWizard()">
{{ 'labels.buttons.Close' | translate }}
</button>
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(templateGlobalSearch, globalSearch)"
>
{{ 'labels.buttons.Back' | translate }}
</button>
<button
mat-raised-button
color="primary"
@@ -385,7 +327,7 @@
<button
mat-raised-button
color="primary"
(click)="popover.close(); showPopover(templateLanguageSelector, languageSelector)"
(click)="popover.close(); showPopover(templateConfigWizard, configWizard)"
>
{{ 'labels.buttons.Back' | translate }}
</button>
@@ -8,10 +8,7 @@
#mifosx-toolbar {
position: relative;
box-shadow:
0 3px 1px -2px rgb(0 0 0 / 20%),
0 2px 2px 0 rgb(0 0 0 / 14%),
0 1px 5px 0 rgb(0 0 0 / 12%);
box-shadow: none;
.tab-nav-bar {
display: flex;
@@ -21,7 +18,7 @@
.tab-link {
min-width: auto;
padding: 15px 1rem;
padding: 15px 0.5rem;
text-decoration: none;
font-weight: 500;
font-size: 14px;
@@ -34,21 +31,6 @@
cursor: pointer;
}
.search-bar {
.search {
max-width: 400px;
width: 100%;
font-size: 1rem;
}
}
.language {
min-width: 80px;
width: 80px;
font-size: 0.875rem;
margin-top: 0.375rem;
}
.img-button {
img {
width: 32px;
@@ -57,6 +39,11 @@
}
}
.ml-05 {
margin-left: 0.35rem;
font-size: 12px;
}
.ml-1 {
margin-left: 1rem;
}
@@ -66,40 +53,6 @@
}
}
// Show language icon button only on small screens (when full selector is hidden)
.show-lt-md {
display: none;
}
@media (width <= 768px) {
.show-lt-md {
display: inline-flex;
}
}
.toolbar-spacer {
flex: 1 1 auto;
}
.white-text-language ::ng-deep mifosx-language-selector {
color: white !important;
/* stylelint-disable-next-line selector-max-universal */
* {
background-color: transparent !important;
color: white !important;
}
}
.white-text-search ::ng-deep mifosx-search-tool {
color: white !important;
/* stylelint-disable-next-line selector-max-universal */
* {
background-color: transparent !important;
color: white !important;
margin-bottom: 0;
}
}
.white-text-language {
margin-top: 27px;
}