feat: add create loan account (#1050)
Fixes: #220 Co-authored-by: Abhijeet Singh <abhijeet40308@gmail.com>
This commit is contained in:
co-authored by
Abhijeet Singh
parent
11d74bd665
commit
843e4ed981
+176
@@ -0,0 +1,176 @@
|
||||
<div fxLayout="row wrap" fxLayoutGap="2%" fxLayout.lt-md="column">
|
||||
|
||||
<mat-form-field fxFlex="48%">
|
||||
<mat-label>Charge</mat-label>
|
||||
<mat-select #charge>
|
||||
<mat-option *ngFor="let charge of chargeData" [value]="charge">
|
||||
{{ charge.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<div fxFlex="48%" fxFlexAlign="center">
|
||||
<button type="button" mat-raised-button color="primary" (click)="addCharge(charge)" [disabled]="!charge.value">
|
||||
<fa-icon icon="plus"></fa-icon>
|
||||
Add
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table fxFlex="98%" class="mat-elevation-z1" mat-table [dataSource]="chargesDataSource"
|
||||
[hidden]="chargesDataSource.length === 0">
|
||||
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.name + ', ' + charge.currency.displaySymbol }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeCalculationType">
|
||||
<th mat-header-cell *matHeaderCellDef> Type </th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeCalculationType.value }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef> Amount </th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.amount }}
|
||||
<button mat-icon-button color="primary" (click)="editChargeAmount(charge)">
|
||||
<fa-icon icon="pen"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="chargeTimeType">
|
||||
<th mat-header-cell *matHeaderCellDef> Collected On </th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
{{ charge.chargeTimeType.value }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="date">
|
||||
<th mat-header-cell *matHeaderCellDef> Date </th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
<span
|
||||
*ngIf="charge.chargeTimeType.value === 'Specified due date' || charge.chargeTimeType.value === 'Weekly Fee'">
|
||||
{{(charge.dueDate | date) || 'Unassigned'}}
|
||||
</span>
|
||||
<span *ngIf="charge.chargeTimeType.value === 'Monthly Fee' || charge.chargeTimeType.value === 'Annual Fee'">
|
||||
{{(charge.feeOnMonthDay | date) || 'Unassigned'}}
|
||||
</span>
|
||||
<span
|
||||
*ngIf="!(charge.chargeTimeType.value === 'Monthly Fee' || charge.chargeTimeType.value === 'Annual Fee'
|
||||
|| charge.chargeTimeType.value === 'Specified due date' || charge.chargeTimeType.value === 'Weekly Fee')">
|
||||
N/A
|
||||
</span>
|
||||
<button mat-icon-button color="primary" *ngIf="charge.chargeTimeType.value === 'Weekly Fee' || charge.chargeTimeType.value === 'Annual Fee'
|
||||
|| charge.chargeTimeType.value === 'Specified due date'" (click)="editChargeDate(charge)">
|
||||
<fa-icon icon="pen"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||
<td mat-cell *matCellDef="let charge">
|
||||
<button mat-icon-button color="warn" (click)="deleteCharge(charge)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="chargesDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: chargesDisplayedColumns;"></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<mat-divider fxFlex="98%"></mat-divider>
|
||||
|
||||
<h4 fxFlex="98%" class="mat-h4">Overdue Charges</h4>
|
||||
|
||||
<table mat-table class="mat-elevation-z1" [dataSource]="overDueChargesDataSource">
|
||||
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let charge"> {{ charge.name }},{{ charge.currency.displaySymbol }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef> Type </th>
|
||||
<td mat-cell *matCellDef="let charge"> {{ charge.chargeCalculationType.value }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="amount">
|
||||
<th mat-header-cell *matHeaderCellDef> Amount </th>
|
||||
<td mat-cell *matCellDef="let charge"> {{ charge.amount| number }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="collectedon">
|
||||
<th mat-header-cell *matHeaderCellDef> Collected On </th>
|
||||
<td mat-cell *matCellDef="let charge"> {{ charge.chargeTimeType.value }} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="overdueChargesDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: overdueChargesDisplayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-divider fxFlex="98%"></mat-divider>
|
||||
|
||||
<div fxFlex="50%">
|
||||
<div fxLayout="column" fxFlex="50%" class="tableName">
|
||||
<h4 fxFlex="98%" class="mat-h4">Collaterals Data</h4>
|
||||
</div>
|
||||
|
||||
<div fxLayout="column" fxFlex="50%">
|
||||
<div fxLayout="row" fxLayoutAlign="flex-end">
|
||||
<button mat-raised-button color="primary" (click)="addCollateral()">
|
||||
<fa-icon icon="plus"></fa-icon> Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table mat-table class="mat-elevation-z1" [dataSource]="collateralDataSource">
|
||||
|
||||
<ng-container matColumnDef="type">
|
||||
<th mat-header-cell *matHeaderCellDef> Type </th>
|
||||
<td mat-cell *matCellDef="let ele"> {{ ele.type.name }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="value">
|
||||
<th mat-header-cell *matHeaderCellDef> Value </th>
|
||||
<td mat-cell *matCellDef="let ele"> {{ ele.value }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="description">
|
||||
<th mat-header-cell *matHeaderCellDef> Description </th>
|
||||
<td mat-cell *matCellDef="let ele"> {{ ele.description }} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
||||
<td mat-cell *matCellDef="let ele; let collateralIndex = index">
|
||||
<button mat-icon-button color="warn" (click)="deleteCollateral(collateralIndex)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="loanCollateralDisplayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: loanCollateralDisplayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<div fxLayout="row" class="margin-t" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="2%">
|
||||
<button mat-raised-button matStepperPrevious>
|
||||
<fa-icon icon="arrow-left"></fa-icon>
|
||||
Previous
|
||||
</button>
|
||||
<button mat-raised-button matStepperNext [disabled]="!loansAccountFormValid">
|
||||
Next
|
||||
<fa-icon icon="arrow-right"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.mat-elevation-z1 {
|
||||
margin: 1em 0 1.5em 0;
|
||||
}
|
||||
|
||||
.margin-t {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
mat-divider {
|
||||
margin: 1em 0 1em 0;
|
||||
}
|
||||
|
||||
.margin-v {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.margin-b {
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
|
||||
.tableName {
|
||||
padding-left: 2%;
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoansAccountChargesStepComponent } from './loans-account-charges-step.component';
|
||||
|
||||
describe('LoansAccountChargesStepComponent', () => {
|
||||
let component: LoansAccountChargesStepComponent;
|
||||
let fixture: ComponentFixture<LoansAccountChargesStepComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ LoansAccountChargesStepComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoansAccountChargesStepComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
+249
@@ -0,0 +1,249 @@
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, Input, OnChanges } from '@angular/core';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material';
|
||||
|
||||
/** Dialog Components */
|
||||
import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component';
|
||||
import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component';
|
||||
import { LoansAccountAddCollateralDialogComponent } from 'app/loans/loans-account-add-collateral-dialog/loans-account-add-collateral-dialog.component';
|
||||
|
||||
/** Custom Services */
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base';
|
||||
import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base';
|
||||
import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base';
|
||||
|
||||
/**
|
||||
* Recurring Deposit Account Charges Step
|
||||
*/
|
||||
@Component({
|
||||
selector: 'mifosx-loans-account-charges-step',
|
||||
templateUrl: './loans-account-charges-step.component.html',
|
||||
styleUrls: ['./loans-account-charges-step.component.scss']
|
||||
})
|
||||
export class LoansAccountChargesStepComponent implements OnInit, OnChanges {
|
||||
|
||||
// @Input loansAccountProductTemplate: LoansAccountProductTemplate
|
||||
@Input() loansAccountProductTemplate: any;
|
||||
// @Imput loansAccountTemplate: LoansAccountTemplate
|
||||
@Input() loansAccountTemplate: any;
|
||||
// @Input() loansAccountFormValid: LoansAccountFormValid
|
||||
@Input() loansAccountFormValid: boolean;
|
||||
// @Input collateralOptionsL Collateral Options
|
||||
@Input() collateralOptions: any;
|
||||
|
||||
/** Charges Data */
|
||||
chargeData: any;
|
||||
/** Charges Data Source */
|
||||
chargesDataSource: {}[] = [];
|
||||
/** Overdue Charges Data Source */
|
||||
overDueChargesDataSource: {}[] = [];
|
||||
/** Collateral Data Source */
|
||||
collateralDataSource: {}[] = [];
|
||||
/** Charges table columns */
|
||||
chargesDisplayedColumns: string[] = ['name', 'chargeCalculationType', 'amount', 'chargeTimeType', 'date', 'action'];
|
||||
/** Columns to be displayed in overdue charges table. */
|
||||
overdueChargesDisplayedColumns: string[] = ['name', 'type', 'amount', 'collectedon'];
|
||||
/** Columns to be displayed in collateral table. */
|
||||
loanCollateralDisplayedColumns: string[] = ['type', 'value', 'description', 'action'];
|
||||
/** Component is pristine if there has been no changes by user interaction */
|
||||
pristine = true;
|
||||
|
||||
/**
|
||||
* Loans Account Charges Form Step
|
||||
* @param {dialog} MatDialog Mat Dialog
|
||||
* @param {datePipe} DatePipe DatePipe
|
||||
*/
|
||||
constructor(public dialog: MatDialog,
|
||||
private datePipe: DatePipe) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if ( this.loansAccountTemplate.charges) {
|
||||
this.chargesDataSource = this.loansAccountTemplate.charges.map((charge: any) => ({ ...charge, id: charge.chargeId })) || [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes on change of input values
|
||||
*/
|
||||
ngOnChanges() {
|
||||
if (this.loansAccountProductTemplate) {
|
||||
this.chargeData = this.loansAccountProductTemplate.chargeOptions;
|
||||
if (this.loansAccountProductTemplate.overdueCharges) {
|
||||
this.overDueChargesDataSource = this.loansAccountProductTemplate.overdueCharges;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a charge
|
||||
*/
|
||||
addCharge(charge: any) {
|
||||
this.chargesDataSource = this.chargesDataSource.concat([charge.value]);
|
||||
charge.value = '';
|
||||
this.pristine = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the Charge Amount
|
||||
* @param {any} charge Charge
|
||||
*/
|
||||
editChargeAmount(charge: any) {
|
||||
const formfields: FormfieldBase[] = [
|
||||
new InputBase({
|
||||
controlName: 'amount',
|
||||
label: 'Amount',
|
||||
value: charge.amount,
|
||||
type: 'number',
|
||||
required: false
|
||||
}),
|
||||
];
|
||||
const data = {
|
||||
title: 'Edit Charge Amount',
|
||||
layout: { addButtonText: 'Confirm' },
|
||||
formfields: formfields
|
||||
};
|
||||
const editNoteDialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||
editNoteDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
const newCharge = { ...charge, amount: response.data.value.amount };
|
||||
this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1, newCharge);
|
||||
this.chargesDataSource = this.chargesDataSource.concat([]);
|
||||
}
|
||||
});
|
||||
this.pristine = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the Charge Date
|
||||
* @param {any} charge Charge
|
||||
*/
|
||||
editChargeDate(charge: any) {
|
||||
const formfields: FormfieldBase[] = [
|
||||
new DatepickerBase({
|
||||
controlName: 'date',
|
||||
label: 'Date',
|
||||
value: charge.dueDate || charge.feeOnMonthDay || '',
|
||||
type: 'datetime-local',
|
||||
required: false
|
||||
}),
|
||||
];
|
||||
const data = {
|
||||
title: 'Edit Charge Date',
|
||||
layout: { addButtonText: 'Confirm' },
|
||||
formfields: formfields
|
||||
};
|
||||
const editNoteDialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||
editNoteDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
let newCharge: any;
|
||||
const dateFormat = 'dd MMMM yyyy';
|
||||
const date = this.datePipe.transform(response.data.value.date, dateFormat);
|
||||
switch (charge.chargeTimeType.value) {
|
||||
case 'Specified due date':
|
||||
case 'Weekly Fee':
|
||||
newCharge = { ...charge, dueDate: date };
|
||||
break;
|
||||
case 'Annual Fee':
|
||||
newCharge = { ...charge, feeOnMonthDay: date };
|
||||
break;
|
||||
}
|
||||
this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1, newCharge);
|
||||
this.chargesDataSource = this.chargesDataSource.concat([]);
|
||||
}
|
||||
});
|
||||
this.pristine = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the Charge Fee Interval
|
||||
* @param {any} charge Charge
|
||||
*/
|
||||
editChargeFeeInterval(charge: any) {
|
||||
const formfields: FormfieldBase[] = [
|
||||
new InputBase({
|
||||
controlName: 'feeInterval',
|
||||
label: 'Fee Interval',
|
||||
value: charge.feeInterval,
|
||||
type: 'text',
|
||||
required: false
|
||||
}),
|
||||
];
|
||||
const data = {
|
||||
title: 'Edit Charge Fee Interval',
|
||||
layout: { addButtonText: 'Confirm' },
|
||||
formfields: formfields
|
||||
};
|
||||
const editNoteDialogRef = this.dialog.open(FormDialogComponent, { data });
|
||||
editNoteDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.data) {
|
||||
const newCharge = { ...charge, feeInterval: response.data.value.feeInterval };
|
||||
this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1, newCharge);
|
||||
this.chargesDataSource = this.chargesDataSource.concat([]);
|
||||
}
|
||||
});
|
||||
this.pristine = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a particular charge
|
||||
* @param charge Charge
|
||||
*/
|
||||
deleteCharge(charge: any) {
|
||||
const deleteChargeDialogRef = this.dialog.open(DeleteDialogComponent, {
|
||||
data: { deleteContext: `charge ${charge.name}` }
|
||||
});
|
||||
deleteChargeDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.delete) {
|
||||
this.chargesDataSource.splice(this.chargesDataSource.indexOf(charge), 1);
|
||||
this.chargesDataSource = this.chargesDataSource.concat([]);
|
||||
this.pristine = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Needs to be completed
|
||||
addCollateral() {
|
||||
const addCollateralDialogRef = this.dialog.open(LoansAccountAddCollateralDialogComponent, {
|
||||
data: { collateralOptions: this.collateralOptions }
|
||||
});
|
||||
addCollateralDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.addCollateralForm) {
|
||||
console.log('formdata: ', response.addCollateralForm);
|
||||
const collateralData = {
|
||||
type: response.addCollateralForm.value.type,
|
||||
value: response.addCollateralForm.value.value,
|
||||
description: response.addCollateralForm.value.description
|
||||
};
|
||||
this.collateralDataSource = this.collateralDataSource.concat(collateralData);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
deleteCollateral(id: any) {
|
||||
const deleteCollateralDialogRef = this.dialog.open(DeleteDialogComponent, {
|
||||
data: { deleteContext: `collateral` }
|
||||
});
|
||||
deleteCollateralDialogRef.afterClosed().subscribe((response: any) => {
|
||||
if (response.delete) {
|
||||
this.collateralDataSource.splice(this.collateralDataSource.indexOf(id), 1);
|
||||
this.collateralDataSource = this.collateralDataSource.concat([]);
|
||||
this.pristine = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Loans Account Charges and Collateral Form
|
||||
*/
|
||||
get loansAccountCharges() {
|
||||
return {
|
||||
charges: this.chargesDataSource,
|
||||
collateral: this.collateralDataSource
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user