feat: add view savings account page (#862)

- Transactions Tab
- Charges Tab
- Standing Instructions Tab

Fixes: #221
This commit is contained in:
Karan Takalkar
2020-06-11 16:03:00 +05:30
committed by GitHub
parent fb52d3cf21
commit 3123f37155
32 changed files with 1353 additions and 54 deletions
+5 -6
View File
@@ -49,11 +49,6 @@ const routes: Routes = [
path: '',
component: ClientsComponent,
},
{
path: ':clientId/savingsaccounts',
data: { routeParamBreadcrumb: 'clientId'},
loadChildren: '../savings/savings.module#SavingsModule'
},
{
path: ':clientId',
component: ClientsViewComponent,
@@ -177,7 +172,11 @@ const routes: Routes = [
path: 'loans',
data: { title: extract('Loans'), breadcrumb: 'loans', routeParamBreadcrumb: false },
loadChildren: '../loans/loans.module#LoansModule'
}
},
{
path: 'savingsaccounts',
loadChildren: '../savings/savings.module#SavingsModule'
},
]
}
]
@@ -243,7 +243,7 @@
</ng-container>
<tr mat-header-row *matHeaderRowDef="openSavingsColumns"></tr>
<tr mat-row *matRowDef="let row; columns: openSavingsColumns;"></tr>
<tr mat-row *matRowDef="let row; columns: openSavingsColumns;" [routerLink]="['../', 'savingsaccounts', row.id, 'transactions']"></tr>
</table>
<!-- Closed Saving Accounts -->
+41 -32
View File
@@ -47,48 +47,57 @@ const routes: Routes = [
},
{
path: ':groupId',
component: GroupsViewComponent,
data: { title: extract('View Group'), routeParamBreadcrumb: 'groupId' },
resolve: {
groupViewData: GroupViewResolver,
groupDatatables: GroupDatatablesResolver
},
children: [
{
path: 'general',
component: GeneralTabComponent,
data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false },
path: '',
component: GroupsViewComponent,
resolve: {
groupAccountsData: GroupAccountsResolver,
groupSummary: GroupSummaryResolver
}
},
{
path: 'notes',
component: NotesTabComponent,
data: { title: extract('Notes'), breadcrumb: 'Notes', routeParamBreadcrumb: false },
resolve: {
groupNotes: GroupNotesResolver
}
},
{
path: 'committee',
component: CommitteeTabComponent,
data: { title: extract('Committee'), breadcrumb: 'Committee', routeParamBreadcrumb: false }
},
{
path: 'datatables',
groupViewData: GroupViewResolver,
groupDatatables: GroupDatatablesResolver
},
children: [
{
path: ':datatableName',
component: DatatableTabsComponent,
data: { title: extract('View Data Table'), routeParamBreadcrumb: 'datatableName' },
path: 'general',
component: GeneralTabComponent,
data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false },
resolve: {
groupDatatable: GroupDatatableResolver
groupAccountsData: GroupAccountsResolver,
groupSummary: GroupSummaryResolver
}
},
{
path: 'notes',
component: NotesTabComponent,
data: { title: extract('Notes'), breadcrumb: 'Notes', routeParamBreadcrumb: false },
resolve: {
groupNotes: GroupNotesResolver
}
},
{
path: 'committee',
component: CommitteeTabComponent,
data: { title: extract('Committee'), breadcrumb: 'Committee', routeParamBreadcrumb: false }
},
{
path: 'datatables',
children: [
{
path: ':datatableName',
component: DatatableTabsComponent,
data: { title: extract('View Data Table'), routeParamBreadcrumb: 'datatableName' },
resolve: {
groupDatatable: GroupDatatableResolver
}
}
]
}
]
}
},
{
path: 'savingsaccounts',
loadChildren: '../savings/savings.module#SavingsModule'
},
]
}
]
@@ -255,7 +255,7 @@
</ng-container>
<tr mat-header-row *matHeaderRowDef="openSavingsColumns"></tr>
<tr mat-row *matRowDef="let row; columns: openSavingsColumns;"></tr>
<tr mat-row *matRowDef="let row; columns: openSavingsColumns;" [routerLink]="['../', 'savingsaccounts', row.id, 'transactions']"></tr>
</table>
@@ -7,7 +7,7 @@
<div class="profile-image-container">
<div>
<img mat-card-md-image class="profile-image"
src="../../../assets/images/group_placeholder.png">
src="assets/images/group_placeholder.png">
</div>
</div>
@@ -29,7 +29,7 @@
background-color: #0a6aac;
p {
color: white;
padding-inline: 10px;
padding: 0 10px;
}
}
}
@@ -7,7 +7,6 @@
}
}
#timescale {
margin-block: 2%;
margin-inline: 35%;
margin: 2% 35%;
}
}
@@ -0,0 +1,32 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { SavingsService } from '../savings.service';
/**
* Savings Account data resolver.
*/
@Injectable()
export class SavingsAccountViewResolver implements Resolve<Object> {
/**
* @param {SavingsService} SavingsService Savings service.
*/
constructor(private savingsService: SavingsService) { }
/**
* Returns the Savings Account data.
* @param {ActivatedRouteSnapshot} route Route Snapshot
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const savingAccountId = route.paramMap.get('savingAccountId');
return this.savingsService.getSavingsAccountData(savingAccountId);
}
}
@@ -0,0 +1,106 @@
<div class="tab-container mat-typography">
<div fxLayout="row" fxLayoutAlign="start">
<div class="m-b-10">
<h3>All Charges</h3>
</div>
<div class="action-button m-b-20" *ngIf="this.chargesData">
<button mat-raised-button color="primary" (click)="toggleCharges()">
{{showInactiveCharges?'View Active Charges':'View Inactive Charges'}}</button>
</div>
</div>
<div class="mat-elevation-z1 m-b-25">
<table mat-table #chargesTable [dataSource]="dataSource" >
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let charge"> {{ charge.name }} </td>
</ng-container>
<ng-container matColumnDef="feeOrPenalty">
<th mat-header-cell *matHeaderCellDef> Fee/Penalty </th>
<td mat-cell *matCellDef="let charge"> {{ charge.penalty === true ? 'Penalty' : 'Fee' }} </td>
</ng-container>
<ng-container matColumnDef="paymentDueAt">
<th mat-header-cell *matHeaderCellDef> Payment Due At </th>
<td mat-cell *matCellDef="let charge"> {{ charge.chargeTimeType.value }} </td>
</ng-container>
<ng-container matColumnDef="dueAsOf">
<th mat-header-cell *matHeaderCellDef> Due As Of </th>
<td mat-cell *matCellDef="let charge"> {{ charge.dueDate | date }} </td>
</ng-container>
<ng-container matColumnDef="repeatsOn">
<th mat-header-cell *matHeaderCellDef> Repeats On (M/d) </th>
<td mat-cell *matCellDef="let charge"> {{ charge.feeOnMonthDay ? charge.feeOnMonthDay.join('/') : '' }} </td>
</ng-container>
<ng-container matColumnDef="calculationType">
<th mat-header-cell *matHeaderCellDef> Calculation Type </th>
<td mat-cell *matCellDef="let charge"> {{charge.chargeCalculationType.value}} </td>
</ng-container>
<ng-container matColumnDef="due">
<th mat-header-cell *matHeaderCellDef> Due </th>
<td mat-cell *matCellDef="let charge"> {{charge.currency.displaySymbol}}&nbsp;{{charge.amount}} </td>
</ng-container>
<ng-container matColumnDef="paid">
<th mat-header-cell *matHeaderCellDef> Paid </th>
<td mat-cell *matCellDef="let charge"> {{charge.currency.displaySymbol}}&nbsp;{{charge.amountPaid}} </td>
</ng-container>
<ng-container matColumnDef="waived">
<th mat-header-cell *matHeaderCellDef> Waived </th>
<td mat-cell *matCellDef="let charge"> {{charge.currency.displaySymbol}}&nbsp;{{charge.amountWaived}} </td>
</ng-container>
<ng-container matColumnDef="outstanding">
<th mat-header-cell *matHeaderCellDef> Outstanding </th>
<td mat-cell *matCellDef="let charge"> {{charge.currency.displaySymbol}}&nbsp;{{charge.amountOutstanding}} </td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </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="Edit Charge"
*mifosxHasPermission="'UPDATE_SAVINGSACCOUNTCHARGE'">
<i class="fa fa-pencil"></i>
</button>
<button class="account-action-button" mat-raised-button color="warn" matTooltip="Delete Charge"
*mifosxHasPermission="'DELETE_SAVINGSACCOUNTCHARGE'">
<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="Pay Charge"
*mifosxHasPermission="'PAY_SAVINGSACCOUNTCHARGE'">
<i class="fa fa-dollar"></i>
</button>
<button class="account-action-button" mat-raised-button color="primary" matTooltip="Waive Charge"
*mifosxHasPermission="'WAIVE_SAVINGSACCOUNTCHARGE'">
<i class="fa fa-flag"></i>
</button>
<ng-container *ngIf="isRecurringCharge(charge)">
<button class="account-action-button" mat-raised-button color="primary" matTooltip="Inactivate Charge"
*mifosxHasPermission="'INACTIVATE_SAVINGSACCOUNTCHARGE'">
<i class="fa fa-ban"></i>
</button>
</ng-container>
</span>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</div>
@@ -0,0 +1,19 @@
.tab-container {
padding: 1%;
margin: 1%;
h3 {
margin:1% auto;
}
.action-button {
margin-left: auto;
}
table {
width: 100%;
.account-action-button{
min-width: 26px;
padding: 0 6px;
margin: 4px;
line-height: 25px;
}
}
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ChargesTabComponent } from './charges-tab.component';
describe('ChargesTabComponent', () => {
let component: ChargesTabComponent;
let fixture: ComponentFixture<ChargesTabComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ChargesTabComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ChargesTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,81 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource, MatTable } from '@angular/material';
import { ActivatedRoute } from '@angular/router';
/**
* Charges Tab Component
*/
@Component({
selector: 'mifosx-charges-tab',
templateUrl: './charges-tab.component.html',
styleUrls: ['./charges-tab.component.scss']
})
export class ChargesTabComponent implements OnInit {
/** Savings Account Data */
savingsAccountData: any;
/** Charges Data */
chargesData: any[];
/** Data source for charges table. */
dataSource: MatTableDataSource<any>;
/** Toggles Charges Table */
showInactiveCharges = false;
/** Columns to be displayed in charges table. */
displayedColumns: string[] = [
'name',
'feeOrPenalty',
'paymentDueAt',
'dueAsOf',
'repeatsOn',
'calculationType',
'due',
'paid',
'waived',
'outstanding',
'actions'
];
/** Charges Table Reference */
@ViewChild('chargesTable') chargesTableRef: MatTable<Element>;
/**
* Retrieves Savings Account Data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
this.route.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.savingsAccountData = data.savingsAccountData;
this.chargesData = this.savingsAccountData.charges;
});
}
ngOnInit() {
const activeCharges = this.chargesData ? this.chargesData.filter(charge => charge.isActive) : [];
this.dataSource = new MatTableDataSource(activeCharges);
}
/**
* Toggles datasource for active/inactive charges.
*/
toggleCharges() {
this.showInactiveCharges = !this.showInactiveCharges;
if (!this.showInactiveCharges) {
const activeCharges = this.chargesData.filter(charge => charge.isActive);
this.dataSource.data = activeCharges;
} else {
const inActiveCharges = this.chargesData.filter(charge => !charge.isActive);
this.dataSource.data = inActiveCharges;
}
this.chargesTableRef.renderRows();
}
/**
* Checks if charge is recurring.
* @param {any} charge Charge
*/
isRecurringCharge(charge: any) {
return charge.chargeTimeType.value === 'Monthly Fee' || charge.chargeTimeType.value === 'Annual Fee' || charge.chargeTimeType.value === 'Weekly Fee';
}
}
@@ -0,0 +1,16 @@
@import "~@angular/material/theming";
@mixin savings-account-view-component-theme($theme) {
$primary: map-get($theme, primary);
mifosx-savings-account-view {
.savings-account-card {
.header {
background-color: mat-color($primary, 500);
}
.table-headers {
background-color: mat-color($primary, 500);
color: mat-contrast($primary, 500);
}
}
}
}
@@ -0,0 +1,289 @@
<mat-card class="savings-account-card">
<mat-card-header fxLayout="column" class="header">
<mat-card-title-group class="header-title-group">
<div class="profile-image-container">
<div>
<img mat-card-md-image class="profile-image"
matTooltip="Savings Account"
src="assets/images/savings_account_placeholder.png">
</div>
</div>
<div class="mat-typography account-card-title">
<mat-card-title>
<h3>
<i class="fa fa-stop" [ngClass]="savingsAccountData.status.code | statusLookup" [matTooltip]="savingsAccountData.status.value"></i>
Account Name : {{savingsAccountData.savingsProductName}}
</h3>
</mat-card-title>
<mat-card-subtitle>
<p>
Account #: {{savingsAccountData.accountNo}} | Client Name: {{savingsAccountData.clientName}}<br/>
<span *ngIf="!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval">
Current Balance: {{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.accountBalance}}<br/>
Available Balance: {{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.availableBalance}}<br/>
</span>
</p>
</mat-card-subtitle>
</div>
</mat-card-title-group>
<mat-card-actions class="account-actions">
<ng-container *ngFor="let button of buttonConfig.singleButtons">
<button mat-raised-button *mifosxHasPermission="button.taskPermissionName">
<i class="{{button.icon}}"></i> {{button.name}}</button>
</ng-container>
<ng-container *ngIf="buttonConfig.options">
<button mat-raised-button [matMenuTriggerFor]="More">More</button>
<mat-menu #More="matMenu">
<span *ngFor="let button of buttonConfig.options">
<button mat-menu-item *mifosxHasPermission="button.taskPermissionName">{{button.name}}</button>
</span>
</mat-menu>
</ng-container>
</mat-card-actions>
</mat-card-header>
<mat-card-content class="content">
<div class="savings-account-tables" fxLayout="row" fxLayoutGap="2%">
<div fxFlex="49%" *ngIf="!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval; else alternateSummary">
<h4 class="table-headers">Account Summary</h4>
<table>
<tbody>
<tr *ngIf="savingsAccountData.summary.totalWithdrawals">
<td>Total Withdrawls</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalWithdrawals}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalWithdrawalFees">
<td>Withdrawals Fees</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalWithdrawalFees}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalAnnualFees">
<td>Annual Fees</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalAnnualFees}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalInterestEarned >= 0">
<td>Interest Earned</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalInterestEarned}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalInterestPosted">
<td>Interest Posted</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalInterestPosted}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.interestNotPosted >= 0">
<td>Interest Earned Not Posted</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.interestNotPosted}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalOverdraftInterestDerived">
<td>Interest On Overdraft</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalOverdraftInterestDerived}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.interestNotPosted < 0">
<td>Overdraft Interest Not Posted</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.interestNotPosted}}</td>
</tr>
<tr>
<td>Nominal Interest Rate</td>
<td>{{savingsAccountData.nominalAnnualInterestRate}}%</td>
</tr>
<tr>
<td>Interest Compounding Period</td>
<td>{{savingsAccountData.interestCompoundingPeriodType.value}}</td>
</tr>
<tr>
<td>Interest Posting Period</td>
<td>{{savingsAccountData.interestPostingPeriodType.value}}</td>
</tr>
<tr>
<td>Interest Calculated Using</td>
<td>{{savingsAccountData.interestCalculationType.value}}</td>
</tr>
<tr>
<td># Days in Year</td>
<td>{{savingsAccountData.interestCalculationDaysInYearType.value}}</td>
</tr>
<tr *ngIf="savingsAccountData.withdrawalFee">
<td>Withdrawal Fee</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.withdrawalFee.amount}}</td>
</tr>
<tr *ngIf="savingsAccountData.lastActiveTransactionDate">
<td>Last Active Transaction Date</td>
<td>{{savingsAccountData.lastActiveTransactionDate | date}}</td>
</tr>
<tr *ngIf="!(savingsAccountData.subStatus.id === 0)">
<td>Substatus</td>
<td>{{savingsAccountData.subStatus.value}}</td>
</tr>
<tr *ngIf="savingsAccountData.daysToInactive">
<td>Days to Inactive</td>
<td>{{savingsAccountData.daysToInactive}}</td>
</tr>
<tr *ngIf="savingsAccountData.daysToDormancy">
<td>Days to Dormancy</td>
<td>{{savingsAccountData.daysToDormancy}}</td>
</tr>
<tr *ngIf="savingsAccountData.daysToEscheat">
<td>Days to Escheat</td>
<td>{{savingsAccountData.daysToEscheat}}</td>
</tr>
<tr *ngIf="savingsAccountData.annualFee">
<td>Annual Fee</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.annualFee.amount}}</td>
</tr>
<tr *ngIf="savingsAccountData.allowOverdraft">
<td>Over Draft Limit</td>
<td>{{savingsAccountData.overdraftLimit}}</td>
</tr>
<tr *ngIf="savingsAccountData.allowOverdraft">
<td>Min Overdraft Required for Interest Calculation</td>
<td>{{savingsAccountData.minOverdraftForInterestCalculation}}</td>
</tr>
<tr *ngIf="savingsAccountData.minBalanceForInterestCalculation">
<td>Min Balance Required for Interest Calculation</td>
<td>{{savingsAccountData.minBalanceForInterestCalculation}}</td>
</tr>
<tr *ngIf="savingsAccountData.minRequiredBalance">
<td>Minimum Required Balance</td>
<td>{{savingsAccountData.minRequiredBalance}}</td>
</tr>
<tr *ngIf="savingsAccountData.enforceMinRequiredBalance">
<td>Enforce Minimum Required Balance</td>
<td>{{savingsAccountData.enforceMinRequiredBalance}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.lastInterestCalculationDate">
<td>Interest Recalculation Date</td>
<td>{{savingsAccountData.summary.lastInterestCalculationDate | date}}</td>
</tr>
<tr *ngIf="savingsAccountData.onHoldFunds">
<td>On Hold Funds</td>
<td><a *mifosxHasPermission="'READ_SAVINGSACCOUNT'">{{savingsAccountData.onHoldFunds}}</a></td>
</tr>
<tr *ngIf="savingsAccountData.withHoldTax">
<td>Withhold Tax Group</td>
<td>{{savingsAccountData.taxGroup.name}}</td>
</tr>
</tbody>
</table>
</div>
<ng-template #alternateSummary>
<div fxFlex="49%" >
<h4 class="table-headers">Account Summary</h4>
<table>
<tbody>
<tr>
<td>Activated On</td>
<td>{{savingsAccountData.timeline.activatedOnDate ? (savingsAccountData.timeline.activatedOnDate | date) : 'Not Activated'}}</td>
</tr>
<tr>
<td>Currency</td>
<td>{{savingsAccountData.currency.name}} [{{savingsAccountData.currency.code}}]</td>
</tr>
<tr>
<td>External Id</td>
<td>{{savingsAccountData.externalId ? savingsAccountData.externalId : 'Not Provided'}}</td>
</tr>
</tbody>
</table>
</div>
</ng-template>
<div fxFlex="49%" fxLayout="column" fxLayoutGap="4%">
<div *ngIf="!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval; else alternateDetails">
<h4 class="table-headers">Savings Details</h4>
<table>
<tbody>
<tr>
<td>Activated On</td>
<td>{{savingsAccountData.timeline.activatedOnDate ? (savingsAccountData.timeline.activatedOnDate | date) : 'Not Activated'}}</td>
</tr>
<tr>
<td>Field Officer</td>
<td>{{savingsAccountData.fieldOfficerName ? savingsAccountData.fieldOfficerName : 'Unassigned'}}</td>
</tr>
<tr>
<td>External Id</td>
<td>{{savingsAccountData.externalId ? savingsAccountData.externalId : 'Not Provided'}}</td>
</tr>
<tr>
<td>Currency</td>
<td>{{savingsAccountData.currency.name}} [{{savingsAccountData.currency.code}}]</td>
</tr>
<tr>
<td>Nominal Interest Rate</td>
<td>{{savingsAccountData.nominalAnnualInterestRate}}%</td>
</tr>
</tbody>
</table>
</div>
<ng-template #alternateDetails>
<div>
<h4 class="table-headers">Savings Details</h4>
<table>
<tbody>
<tr>
<td>Field Officer</td>
<td>{{savingsAccountData.fieldOfficerName ? savingsAccountData.fieldOfficerName : 'Unassigned'}}</td>
</tr>
<tr>
<td>Balance</td>
<td>{{savingsAccountData.summary.accountBalance}}</td>
</tr>
</tbody>
</table>
</div>
</ng-template>
<div *ngIf="!savingsAccountData.status.rejected && !savingsAccountData.status.submittedAndPendingApproval">
<h4 class="table-headers">Performance History</h4>
<table>
<tbody>
<tr *ngIf="savingsAccountData.summary.totalDeposits">
<td>Total Deposits</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalDeposits}}</td>
</tr>
<tr *ngIf="savingsAccountData.summary.totalInterestEarned >= 0">
<td>Total Interest Earned</td>
<td>{{savingsAccountData.currency.displaySymbol}}&nbsp;{{savingsAccountData.summary.totalInterestEarned}}</td>
</tr>
</table>
</div>
</div>
</div>
<nav mat-tab-nav-bar class="navigation-tabs">
<a mat-tab-link [routerLink]="['./transactions']" routerLinkActive #transactions="routerLinkActive"
[active]="transactions.isActive">
Transactions
</a>
<a mat-tab-link [routerLink]="['./charges']" routerLinkActive #charges="routerLinkActive"
[active]="charges.isActive">
Charges
</a>
<ng-container *mifosxHasPermission="'READ_SAVINGSACCOUNTCHARGE'">
<a mat-tab-link [routerLink]="['./standing-instructions']" routerLinkActive #standingInstructions="routerLinkActive"
[active]="standingInstructions.isActive" *ngIf="savingsAccountData.clientId">
Standing Instructions
</a>
</ng-container>
</nav>
<router-outlet></router-outlet>
</mat-card-content>
</mat-card>
@@ -0,0 +1,53 @@
.savings-account-card {
margin: 0 auto;
max-width: 80rem;
width: 90%;
padding: 0;
.header {
padding: 1%;
.header-title-group {
.account-card-title {
color: white;
width: 90%;
p {
color: white;
}
}
}
.profile-image-container {
margin: 1%;
.profile-image {
object-fit: cover;
border-radius: 20px;
}
}
.account-actions {
align-self: flex-end;
margin: 0 1%;
i {
margin-bottom: 2px;
margin-right: 4px;
}
}
}
.navigation-tabs {
background-color: #f2f2f2;
overflow: auto;
}
.content {
.savings-account-tables {
padding: 1%;
margin: 1%;
.table-headers {
margin: 0;
padding: 6px;
}
td {
padding: 3px;
}
}
}
i, img:hover {
cursor: pointer;
}
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SavingsAccountViewComponent } from './savings-account-view.component';
describe('SavingsAccountViewComponent', () => {
let component: SavingsAccountViewComponent;
let fixture: ComponentFixture<SavingsAccountViewComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SavingsAccountViewComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SavingsAccountViewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,84 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { SavingsButtonsConfiguration } from './savings-buttons.config';
/**
* Savings Account View Component
*/
@Component({
selector: 'mifosx-savings-account-view',
templateUrl: './savings-account-view.component.html',
styleUrls: ['./savings-account-view.component.scss']
})
export class SavingsAccountViewComponent implements OnInit {
/** Savings Account Data */
savingsAccountData: any;
/** Button Configurations */
buttonConfig: SavingsButtonsConfiguration;
/**
* Fetches savings account data from `resolve`
* @param {ActivatedRoute} route Activated Route
*/
constructor(private route: ActivatedRoute) {
this.route.data.subscribe((data: { savingsAccountData: any }) => {
this.savingsAccountData = data.savingsAccountData;
});
}
ngOnInit() {
this.setConditionalButtons();
}
/**
* Adds options to button config. conditionaly.
*/
setConditionalButtons() {
const status = this.savingsAccountData.status.value;
this.buttonConfig = new SavingsButtonsConfiguration(status);
if (this.savingsAccountData.clientId) {
this.buttonConfig.addOption({
name: 'Transfer Funds',
taskPermissionName: 'CREATE_ACCOUNTTRANSFER'
});
}
if (!this.savingsAccountData.fieldOfficerId) {
this.buttonConfig.addOption({
name: 'Assign Staff',
taskPermissionName: 'UPDATESAVINGSOFFICER_SAVINGSACCOUNT'
});
} else {
this.buttonConfig.addOption({
name: 'Unassign Staff',
taskPermissionName: 'REMOVESAVINGSOFFICER_SAVINGSACCOUNT'
});
}
if (this.savingsAccountData.charges) {
const charges: any[] = this.savingsAccountData.charges;
charges.forEach((charge: any) => {
if (charge.name === 'Annual fee - INR') {
this.buttonConfig.addOption({
name: 'Apply Anuual Fees',
taskPermissionName: 'APPLYANNUALFEE_SAVINGSACCOUNT'
});
}
});
}
if (this.savingsAccountData.taxGroup) {
if (this.savingsAccountData.withHoldTax) {
this.buttonConfig.addOption({
name: 'Disable Withhold Tax',
taskPermissionName: 'UPDATEWITHHOLDTAX_SAVINGSACCOUNT'
});
} else {
this.buttonConfig.addOption({
name: 'Enable Withhold Tax',
taskPermissionName: 'UPDATEWITHHOLDTAX_SAVINGSACCOUNT'
});
}
}
}
}
@@ -0,0 +1,142 @@
/** Savings Account Buttons Configuration */
export class SavingsButtonsConfiguration {
optionArray: {
name: string,
taskPermissionName: string,
action?: Function
}[];
buttonsArray: {
name: string,
icon: string,
taskPermissionName: string,
action?: Function
}[];
constructor(status: string) {
this.setOptions(status);
this.setButtons(status);
}
get singleButtons() {
return this.buttonsArray;
}
get options() {
return this.optionArray;
}
setButtons(status: string) {
switch (status) {
case 'Active':
this.buttonsArray = [
{
name: 'Post Interest As On',
icon: 'fa fa-arrow-right',
taskPermissionName: 'POSTINTEREST_SAVINGSACCOUNT',
},
{
name: 'Deposit',
icon: 'fa fa-arrow-up',
taskPermissionName: 'DEPOSIT_SAVINGSACCOUNT'
},
{
name: 'Withdraw',
icon: 'fa fa-arrow-down',
taskPermissionName: 'WITHDRAW_SAVINGSACCOUNT'
},
{
name: 'Calculate Interest',
icon: 'fa fa-table',
taskPermissionName: 'CALCULATEINTEREST_SAVINGSACCOUNT'
}
];
break;
case 'Submitted and pending approval':
this.buttonsArray = [
{
name: 'Modify Application',
icon: 'fa fa-pencil ',
taskPermissionName: 'UPDATE_SAVINGSACCOUNT'
},
{
name: 'Approve',
icon: 'fa fa-check',
taskPermissionName: 'APPROVE_SAVINGSACCOUNT'
}
];
break;
case 'Approved':
this.buttonsArray = [
{
name: 'Undo Approval',
icon: 'fa fa-undo',
taskPermissionName: 'APPROVALUNDO_SAVINGSACCOUNT'
},
{
name: 'Activate',
icon: 'fa fa-check',
taskPermissionName: 'ACTIVATE_SAVINGSACCOUNT'
},
{
name: 'Add Charge',
icon: 'fa fa-plus',
taskPermissionName: 'CREATE_SAVINGSACCOUNTCHARGE'
}
];
break;
default:
this.buttonsArray = [];
}
}
setOptions(status: string) {
switch (status) {
case 'Active':
this.optionArray = [
{
name: 'Post Interest',
taskPermissionName: 'POSTINTEREST_SAVINGSACCOUNT'
},
{
name: 'Add Charge',
taskPermissionName: 'CREATE_SAVINGSACCOUNTCHARGE'
},
{
name: 'Close',
taskPermissionName: 'CLOSE_SAVINGSACCOUNT'
}
];
break;
case 'Submitted and pending approval':
this.optionArray = [
{
name: 'Reject',
taskPermissionName: 'REJECT_SAVINGSACCOUNT'
},
{
name: 'Withdraw',
taskPermissionName: 'WITHDRAW_SAVINGSACCOUNT'
},
{
name: 'Add Charge',
taskPermissionName: 'CREATE_SAVINGSACCOUNTCHARGE'
},
{
name: 'Delete',
taskPermissionName: 'DELETE_SAVINGSACCOUNT'
}
];
break;
case 'Approved':
default:
this.optionArray = [];
}
}
addOption(option: {name: string, taskPermissionName: string}) {
this.optionArray.push(option);
}
}
@@ -0,0 +1,70 @@
<div class="tab-container mat-typography">
<div class="m-b-10">
<h3>All Standing Instructions</h3>
</div>
<div class="mat-elevation-z1 m-b-25">
<table mat-table #instructionsTable [dataSource]="dataSource">
<ng-container matColumnDef="client">
<th mat-header-cell *matHeaderCellDef> Client </th>
<td mat-cell *matCellDef="let instruction">{{instruction.fromClient.displayName}}-{{instruction.fromClient.id}}</td>
</ng-container>
<ng-container matColumnDef="fromAccount">
<th mat-header-cell *matHeaderCellDef> From Account </th>
<td mat-cell *matCellDef="let instruction">{{instruction.fromAccount.accountNo}} ({{instruction.fromAccountType.value}})</td>
</ng-container>
<ng-container matColumnDef="beneficiary">
<th mat-header-cell *matHeaderCellDef> Beneficiary </th>
<td mat-cell *matCellDef="let instruction">{{instruction.toClient.displayName}}</td>
</ng-container>
<ng-container matColumnDef="toAccount">
<th mat-header-cell *matHeaderCellDef> To Account </th>
<td mat-cell *matCellDef="let instruction">{{instruction.toAccount.accountNo}} ({{instruction.toAccountType.value}})</td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef> Amount </th>
<td mat-cell *matCellDef="let instruction">{{instruction.instructionType.value}}/{{instruction.amount}}</td>
</ng-container>
<ng-container matColumnDef="validity">
<th mat-header-cell *matHeaderCellDef> Validity </th>
<td mat-cell *matCellDef="let instruction">{{instruction.validFrom | date}} to {{instruction.validTill | date}}</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let instruction">
<span *ngIf="instruction.status.value!=='Deleted'">
<button class="account-action-button" mat-raised-button color="primary" matTooltip="Edit Standing Instruction"
*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="Delete Standing Instruction"
*mifosxHasPermission="'DELETE_STANDINGINSTRUCTION'">
<i class="fa fa-times"></i>
</button>
</span>
<button class="account-action-button" mat-raised-button color="primary" matTooltip="View Standing Instruction"
*mifosxHasPermission="'READ_STANDINGINSTRUCTION'">
<i class="fa fa-eye"></i>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</div>
@@ -0,0 +1,19 @@
.tab-container {
padding: 1%;
margin: 1%;
h3 {
margin:1% auto;
}
.action-button {
margin-left: auto;
}
table {
width: 100%;
.account-action-button{
min-width: 26px;
padding: 0 6px;
margin: 4px;
line-height: 25px;
}
}
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { StandingInstructionsTabComponent } from './standing-instructions-tab.component';
describe('StandingInstructionsTabComponent', () => {
let component: StandingInstructionsTabComponent;
let fixture: ComponentFixture<StandingInstructionsTabComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ StandingInstructionsTabComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(StandingInstructionsTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,70 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatTableDataSource, MatTable } from '@angular/material';
import { ActivatedRoute } from '@angular/router';
/** Custom Services */
import { SavingsService } from 'app/savings/savings.service';
/**
* Savings Standing Instructions Tab
*/
@Component({
selector: 'mifosx-standing-instructions-tab',
templateUrl: './standing-instructions-tab.component.html',
styleUrls: ['./standing-instructions-tab.component.scss']
})
export class StandingInstructionsTabComponent implements OnInit {
/** Savings Data */
savingsData: any;
/** Instructions Data */
instructionsData: any[];
/** Data source for instructions table. */
dataSource = new MatTableDataSource();
/** Columns to be displayed in instructions table. */
displayedColumns: string[] = [
'client',
'fromAccount',
'beneficiary',
'toAccount',
'amount',
'validity',
'actions'
];
/** Instruction Table Reference */
@ViewChild('instructionsTable') instructionTableRef: MatTable<Element>;
/**
* Retrieves Savings Account Data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute,
private savingsService: SavingsService) {
this.route.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.savingsData = data.savingsAccountData;
});
}
ngOnInit() {
this.getStandingInstructions();
}
/**
* Retrieves standing instructions and initializes instructions table.
*/
getStandingInstructions() {
const clientId = this.savingsData.clientId;
const clientName = this.savingsData.clientName;
const accountId = this.savingsData.id;
const locale = 'en';
const dateFormat = 'dd MMMM yyyy';
this.savingsService.getStandingInstructions(clientId, clientName, accountId, locale, dateFormat).subscribe((response: any) => {
this.instructionsData = response.pageItems;
this.dataSource.data = this.instructionsData;
this.instructionTableRef.renderRows();
});
}
}
@@ -0,0 +1,63 @@
<div class="tab-container mat-typography">
<div fxLayout="row" fxLayoutAlign="start">
<div class="m-b-10">
<h3>All Transactions</h3>
</div>
<div class="action-button m-b-20" fxLayout="row" fxLayoutGap="20px" *ngIf="checkStatus()">
<button mat-raised-button color="primary">View Journal Entries</button>
<button mat-raised-button color="primary">Export</button>
</div>
</div>
<div class="mat-elevation-z1 m-b-25">
<table mat-table [dataSource]="dataSource" >
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> ID </th>
<td mat-cell *matCellDef="let transaction"> {{ transaction.id }} </td>
</ng-container>
<ng-container matColumnDef="transactionDate">
<th mat-header-cell *matHeaderCellDef> Transaction Date </th>
<td mat-cell *matCellDef="let transaction"> {{ transaction.date | date }} </td>
</ng-container>
<ng-container matColumnDef="transactionType">
<th mat-header-cell *matHeaderCellDef> Transaction Type </th>
<td mat-cell *matCellDef="let transaction"> {{ transaction.transactionType.value }} </td>
</ng-container>
<ng-container matColumnDef="debit">
<th mat-header-cell *matHeaderCellDef> Debit </th>
<td mat-cell *matCellDef="let transaction"> {{ isDebit(transaction.transactionType) ? transaction.amount : 'N/A'}} </td>
</ng-container>
<ng-container matColumnDef="credit">
<th mat-header-cell *matHeaderCellDef> Credit </th>
<td mat-cell *matCellDef="let transaction"> {{ !isDebit(transaction.transactionType) ? transaction.amount : 'N/A' }} </td>
</ng-container>
<ng-container matColumnDef="balance">
<th mat-header-cell *matHeaderCellDef> Balance </th>
<td mat-cell *matCellDef="let transaction"> {{ transaction.runningBalance }} </td>
</ng-container>
<ng-container matColumnDef="viewReciept">
<th mat-header-cell *matHeaderCellDef> View Reciept </th>
<td mat-cell *matCellDef="let transaction">
<button class="account-action-button" mat-raised-button color="primary">
<i class="fa fa-file" matTooltip="View Reciept"></i>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
</div>
</div>
@@ -0,0 +1,19 @@
.tab-container {
padding: 1%;
margin: 1%;
h3 {
margin:1% auto;
}
.action-button {
margin-left: auto;
}
table {
width: 100%;
.account-action-button{
min-width: 26px;
padding: 0 0 3px 0;
margin: 0 10%;
line-height: 25px;
}
}
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TransactionsTabComponent } from './transactions-tab.component';
describe('TransactionsTabComponent', () => {
let component: TransactionsTabComponent;
let fixture: ComponentFixture<TransactionsTabComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TransactionsTabComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TransactionsTabComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,60 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { MatTableDataSource } from '@angular/material';
import { ActivatedRoute } from '@angular/router';
/**
* Transactions Tab Component.
*/
@Component({
selector: 'mifosx-transactions-tab',
templateUrl: './transactions-tab.component.html',
styleUrls: ['./transactions-tab.component.scss']
})
export class TransactionsTabComponent implements OnInit {
/** Savings Account Status */
status: any;
/** Transactions Data */
transactionsData: any;
/** Columns to be displayed in transactions table. */
displayedColumns: string[] = ['id', 'transactionDate', 'transactionType', 'debit', 'credit', 'balance', 'viewReciept'];
/** Data source for transactions table. */
dataSource: MatTableDataSource<any>;
/**
* Retrieves savings account data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute) {
this.route.parent.data.subscribe((data: { savingsAccountData: any }) => {
this.transactionsData = data.savingsAccountData.transactions;
this.status = data.savingsAccountData.status.value;
});
}
ngOnInit() {
this.dataSource = new MatTableDataSource(this.transactionsData);
}
/**
* Checks if transaction is debit.
* @param {any} transactionType Transaction Type
*/
isDebit(transactionType: any) {
return transactionType.withdrawal === true || transactionType.feeDeduction === true
|| transactionType.overdraftInterest === true || transactionType.withholdTax === true;
}
/**
* Checks transaction status.
*/
checkStatus() {
if (this.status === 'Active' || this.status === 'Closed' || this.status === 'Transfer in progress' ||
this.status === 'Transfer on hold' || this.status === 'Premature Closed' || this.status === 'Matured') {
return true;
}
return false;
}
}
+28 -8
View File
@@ -6,32 +6,50 @@ import { Routes, RouterModule } from '@angular/router';
import { extract } from '../core/i18n/i18n.service';
/** Custom Components */
import { SavingsAccountViewComponent } from './savings-account-view/savings-account-view.component';
import { TransactionsTabComponent } from './savings-account-view/transactions-tab/transactions-tab.component';
import { SavingAccountActionsComponent } from './saving-account-actions/saving-account-actions.component';
import { AddSavingsChargeComponent } from './add-savings-charge/add-savings-charge.component';
import { ChargesTabComponent } from './savings-account-view/charges-tab/charges-tab.component';
import { StandingInstructionsTabComponent } from './savings-account-view/standing-instructions-tab/standing-instructions-tab.component';
/** Custom Resolvers */
import { SavingAccountTransactionTemplateResolver } from './common-resolvers/saving-transaction-template.resolver';
import { SavingsChargeTemplateResolver } from './common-resolvers/savings-charge-template.resolver';
import { SavingsAccountViewResolver } from './common-resolvers/savings-account-view.resolver';
const routes: Routes = [
{
path: '',
data: { title: extract('All Savings'), breadcrumb: 'Savings', routeParamBreadcrumb: false },
// Component to view all saving accounts Comes Here
children: [
{
path: ':savingAccountId',
data: { title: extract('Saving Account View'), routeParamBreadcrumb: 'savingAccountId' },
// Component For Saving Account View Comes Here
component: SavingsAccountViewComponent,
resolve: {
savingsAccountData: SavingsAccountViewResolver
},
children: [
{
path: 'transactions',
component: TransactionsTabComponent,
data: { title: extract('Savings Account Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false }
},
{
path: 'charges',
component: ChargesTabComponent,
data: { title: extract('Savings Account Charges'), breadcrumb: 'Charges', routeParamBreadcrumb: false }
},
{
path: 'standing-instructions',
component: StandingInstructionsTabComponent,
data: { title: extract('Savings Account SIH'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false }
},
{
path: 'add-savings-charge',
component: AddSavingsChargeComponent,
data: {
title: extract('Add Savings Charge'),
breadcrumb: 'Add Savings Charge',
routeParamBreadcrumb: false
},
data: { title: extract('Add Savings Charge'), breadcrumb: 'Add Savings Charge', routeParamBreadcrumb: false },
resolve: {
savingsChargeTemplate: SavingsChargeTemplateResolver
}
@@ -53,6 +71,8 @@ const routes: Routes = [
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
declarations: [],
providers: [SavingAccountTransactionTemplateResolver, SavingsChargeTemplateResolver]
providers: [SavingAccountTransactionTemplateResolver,
SavingsChargeTemplateResolver,
SavingsAccountViewResolver]
})
export class SavingsRoutingModule {}
+13 -1
View File
@@ -5,11 +5,17 @@ import { DatePipe } from '@angular/common';
/** Custom Modules */
import { SavingsRoutingModule } from './savings-routing.module';
import { SharedModule } from 'app/shared/shared.module';
import { PipesModule } from '../pipes/pipes.module';
import { DirectivesModule } from '../directives/directives.module';
/** Custom Components */
import { SavingAccountActionsComponent } from './saving-account-actions/saving-account-actions.component';
import { SavingsAccountTransactionsComponent } from './saving-account-actions/savings-account-transactions/savings-account-transactions.component';
import { AddSavingsChargeComponent } from './add-savings-charge/add-savings-charge.component';
import { TransactionsTabComponent } from './savings-account-view/transactions-tab/transactions-tab.component';
import { SavingsAccountViewComponent } from './savings-account-view/savings-account-view.component';
import { ChargesTabComponent } from './savings-account-view/charges-tab/charges-tab.component';
import { StandingInstructionsTabComponent } from './savings-account-view/standing-instructions-tab/standing-instructions-tab.component';
/**
* Savings Module
@@ -19,12 +25,18 @@ import { AddSavingsChargeComponent } from './add-savings-charge/add-savings-char
@NgModule({
imports: [
SharedModule,
PipesModule,
DirectivesModule,
SavingsRoutingModule
],
declarations: [
SavingAccountActionsComponent,
SavingsAccountTransactionsComponent,
AddSavingsChargeComponent
AddSavingsChargeComponent,
TransactionsTabComponent,
SavingsAccountViewComponent,
ChargesTabComponent,
StandingInstructionsTabComponent
],
providers: [DatePipe]
})
+34 -1
View File
@@ -1,6 +1,6 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { HttpClient, HttpParams } from '@angular/common/http';
/** rxjs Imports */
import { Observable } from 'rxjs';
@@ -12,7 +12,9 @@ import { Observable } from 'rxjs';
providedIn: 'root'
})
export class SavingsService {
constructor(private http: HttpClient) {}
/**
* @param {string} savingAccountId is saving account's Id.
* @returns {Observable<any>}
@@ -55,4 +57,35 @@ export class SavingsService {
const params = { template: 'true' };
return this.http.get(`/charges/${chargeId}`, { params: params });
}
/**
* @param groupId Group Id of group to get data for.
* @returns {Observable<any>} Group data.
*/
getSavingsAccountData(accountId: string): Observable<any> {
const httpParams = new HttpParams().set('associations', 'all');
return this.http.get(`/savingsaccounts/${accountId}`, { params: httpParams });
}
/**
* @param clientId Client Id
* @param clientName Client Name
* @param fromAccountId Account Id
* @param locale Locale
* @param dateFormat Date Format
* @returns {Observable<any>} Standing Instructions
*/
getStandingInstructions(
clientId: string, clientName: string, fromAccountId: string,
locale: string, dateFormat: string): Observable<any> {
const httpParams = new HttpParams()
.set('clientId', clientId)
.set('clientName', clientName)
.set('fromAccountId', fromAccountId)
.set('fromAccountType', '2')
.set('locale', locale)
.set('dateFormat', dateFormat);
return this.http.get(`/standinginstructions`, { params: httpParams });
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

+2
View File
@@ -5,6 +5,7 @@
@import '../../app/centers/centers-view/centers-view.component-theme.scss';
@import '../../app/home/dashboard/dashboard.component-theme.scss';
@import '../../app/loans/loans-view/loans-view.component-theme.scss';
@import '../../app/savings/savings-account-view/savings-account-view.component-theme.scss';
// Custom material palette
$mat-denim: (
@@ -55,3 +56,4 @@ $mifosx-app-theme: mat-light-theme($mifosx-app-primary, $mifosx-app-accent, $mif
@include centers-view-component-theme($mifosx-app-theme);
@include dashboard-component-theme($mifosx-app-theme);
@include loans-view-component-theme($mifosx-app-theme);
@include savings-account-view-component-theme($mifosx-app-theme);
@@ -5,6 +5,7 @@
@import '../../app/centers/centers-view/centers-view.component-theme.scss';
@import '../../app/home/dashboard/dashboard.component-theme.scss';
@import '../../app/loans/loans-view/loans-view.component-theme.scss';
@import '../../app/savings/savings-account-view/savings-account-view.component-theme.scss';
// Custom material palette
$mat-picton-blue: (
@@ -55,3 +56,4 @@ $mifosx-app-theme: mat-light-theme($mifosx-app-primary, $mifosx-app-accent, $mif
@include centers-view-component-theme($mifosx-app-theme);
@include dashboard-component-theme($mifosx-app-theme);
@include loans-view-component-theme($mifosx-app-theme);
@include savings-account-view-component-theme($mifosx-app-theme);