Support for Charge-off and Undo charge-off to Loan account (#1748)

Co-authored-by: Jose Alberto Hernandez <alberto@blue-daemon.local>
This commit is contained in:
José Alberto Hernández
2023-05-09 22:09:45 -06:00
committed by GitHub
co-authored by Jose Alberto Hernandez
parent d294885f00
commit b2aa39cb67
94 changed files with 863 additions and 481 deletions
@@ -43,8 +43,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -59,8 +59,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -217,8 +217,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -104,7 +104,7 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!fixedDepositAccountFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -25,8 +25,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -42,8 +42,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -143,7 +143,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -139,8 +139,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -94,8 +94,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -105,7 +105,7 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!recurringDepositAccountFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -21,8 +21,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -42,8 +42,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -148,7 +148,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -202,8 +202,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -62,8 +62,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -70,6 +70,8 @@ export class LoanActionButtonResolver implements Resolve<Object> {
return this.loansService.getLoanChargeTemplateResource(loanId);
} else if (loanActionButton === 'Foreclosure') {
return this.loansService.getLoanForeclosureActionTemplate(loanId);
} else if (loanActionButton === 'Charge-Off') {
return this.loansService.getLoanActionTemplate(loanId, 'charge-off');
} else {
return undefined;
}
@@ -163,7 +163,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -80,8 +80,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -121,8 +121,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -124,8 +124,8 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!loansAccountFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
<button mat-raised-button *ngIf="loanId" [routerLink]="['../', 'general']">
Cancel
@@ -43,8 +43,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -95,8 +95,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
<button mat-raised-button *ngIf="loanId" [routerLink]="['../', 'general']">
Cancel
@@ -2,8 +2,6 @@
<h3 class="mat-h3" fxFlexFill>Details</h3>
<mat-divider fxFlexFill></mat-divider>
<div fxFlexFill>
<span fxFlex="40%">Product:</span>
<span fxFlex="60%">{{ loansAccount.productId | find:loansAccountTemplate.productOptions:'id':'name' }}</span>
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Component, OnInit, Input, Output, EventEmitter, OnDestroy } from '@angular/core';
/**
* Create Loans Account Preview Step
@@ -9,10 +9,10 @@ import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
templateUrl: './loans-account-preview-step.component.html',
styleUrls: ['./loans-account-preview-step.component.scss']
})
export class LoansAccountPreviewStepComponent implements OnInit {
export class LoansAccountPreviewStepComponent implements OnInit, OnDestroy {
/** Loans Account Template */
@Input() loansAccountTemplate: any;
@Input() loansAccountTemplate: any = [];
/** Loans Account Product Template */
@Input() loansAccountProductTemplate: any;
/** Loans Account Data */
@@ -29,4 +29,6 @@ export class LoansAccountPreviewStepComponent implements OnInit {
ngOnInit() { }
ngOnDestroy(): void { }
}
@@ -4,8 +4,7 @@
Repayment Info
</a>
<mifosx-repayment-schedule-tab fxFlex="100%"
[repaymentScheduleDetails]="repaymentScheduleDetails"
<mifosx-repayment-schedule-tab fxFlex="100%" [repaymentScheduleDetails]="repaymentScheduleDetails"
[currencyCode]="currencyCode">
</mifosx-repayment-schedule-tab>
@@ -17,8 +16,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
<button mat-raised-button *ngIf="loanId" [routerLink]="['../', 'general']">
Cancel
@@ -426,8 +426,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
<button mat-raised-button *ngIf="loanId" [routerLink]="['../', 'general']">
Cancel
@@ -0,0 +1,58 @@
<div class="container mat-elevation-z8">
<mat-card>
<form [formGroup]="chargeoffLoanForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field (click)="transactionDatePicker.open()">
<mat-label>Transaction Date</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="transactionDatePicker" required
formControlName="transactionDate">
<mat-datepicker-toggle matSuffix [for]="transactionDatePicker"></mat-datepicker-toggle>
<mat-datepicker #transactionDatePicker></mat-datepicker>
<mat-error *ngIf="chargeoffLoanForm.controls.transactionDate.hasError('required')">
Transaction Date <strong>is required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Reason for Charge-Off</mat-label>
<mat-select formControlName="chargeOffReasonId">
<mat-option *ngFor="let chargeOffReason of chargeOffReasonOptions" [value]="chargeOffReason.id">
{{ chargeOffReason.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="chargeoffLoanForm.controls.chargeOffReasonId.hasError('required')">
Reason for Charge-Off <strong>is required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>External Id</mat-label>
<input matInput formControlName="externalId">
</mat-form-field>
<mat-form-field>
<mat-label>Note</mat-label>
<textarea matInput formControlName="note" cdkTextareaAutosize cdkAutosizeMinRows="2"></textarea>
</mat-form-field>
</div>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../../general']">Cancel</button>
<button mat-raised-button color="primary" [disabled]="!chargeoffLoanForm.valid"
*mifosxHasPermission="'CHARGEOFF_LOAN'">Submit</button>
</mat-card-actions>
</mat-card-content>
</form>
</mat-card>
</div>
@@ -0,0 +1,4 @@
.container {
max-width: 37rem;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ChargeOffComponent } from './charge-off.component';
describe('ChargeOffComponent', () => {
let component: ChargeOffComponent;
let fixture: ComponentFixture<ChargeOffComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ChargeOffComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ChargeOffComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,89 @@
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Dates } from 'app/core/utils/dates';
import { LoansService } from 'app/loans/loans.service';
import { SettingsService } from 'app/settings/settings.service';
@Component({
selector: 'mifosx-charge-off',
templateUrl: './charge-off.component.html',
styleUrls: ['./charge-off.component.scss']
})
export class ChargeOffComponent implements OnInit {
@Input() dataObject: any;
/** Loan Id */
loanId: string;
/** Payment Type Options */
paymentTypes: any;
/** Show payment details */
showPaymentDetails = false;
/** Minimum Date allowed. */
minDate = new Date(2000, 0, 1);
/** Maximum Date allowed. */
maxDate = new Date();
/** Repayment Loan Form */
chargeoffLoanForm: FormGroup;
chargeOffReasonOptions: any = [];
/**
* @param {FormBuilder} formBuilder Form Builder.
* @param {LoansService} loanService Loan Service.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
* @param {SettingsService} settingsService Settings Service
*/
constructor(private formBuilder: FormBuilder,
private loanService: LoansService,
private route: ActivatedRoute,
private router: Router,
private dateUtils: Dates,
private settingsService: SettingsService) {
this.loanId = this.route.snapshot.params['loanId'];
}
/**
* Creates the repayment loan form
* and initialize with the required values
*/
ngOnInit() {
this.maxDate = this.settingsService.businessDate;
this.chargeOffReasonOptions = this.dataObject.chargeOffReasonOptions;
this.createChargeoffLoanForm();
}
/**
* Creates the create close form.
*/
createChargeoffLoanForm() {
this.chargeoffLoanForm = this.formBuilder.group({
'transactionDate': [this.settingsService.businessDate, Validators.required],
'externalId': '',
'chargeOffReasonId': '',
'note': ''
});
}
submit() {
const chargeoffLoanFormData = this.chargeoffLoanForm.value;
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
const prevTransactionDate: Date = this.chargeoffLoanForm.value.transactionDate;
if (chargeoffLoanFormData.transactionDate instanceof Date) {
chargeoffLoanFormData.transactionDate = this.dateUtils.formatDate(prevTransactionDate, dateFormat);
}
const data = {
...chargeoffLoanFormData,
dateFormat,
locale
};
const command = 'charge-off';
this.loanService.submitLoanActionButton(this.loanId, data, command)
.subscribe((response: any) => {
this.router.navigate(['../../transactions'], { relativeTo: this.route });
});
}
}
@@ -25,3 +25,5 @@
<mifosx-approve-loan *ngIf="actions['Approve']" ></mifosx-approve-loan>
<mifosx-add-loan-charge *ngIf="actions['Add Loan Charge']"></mifosx-add-loan-charge>
<mifosx-edit-repayment-schedule *ngIf="actions['Edit Repayment Schedule']"></mifosx-edit-repayment-schedule>
<mifosx-charge-off [dataObject]="actionButtonData" *ngIf="actions['Charge-Off']"></mifosx-charge-off>
<mifosx-undo-command [actionName]="actionName" *ngIf="actions['Undo Charge-Off']"></mifosx-undo-command>
@@ -40,7 +40,9 @@ export class LoanAccountActionsComponent {
'Merchant Issued Refund': boolean,
'Payout Refund': boolean,
'Credit Balance Refund': boolean,
'Edit Repayment Schedule': boolean
'Edit Repayment Schedule': boolean,
'Charge-Off': boolean,
'Undo Charge-Off': boolean
} = {
'Close': false,
'Undo Approval': false,
@@ -69,7 +71,9 @@ export class LoanAccountActionsComponent {
'Merchant Issued Refund': false,
'Payout Refund': false,
'Credit Balance Refund': false,
'Edit Repayment Schedule': false
'Edit Repayment Schedule': false,
'Charge-Off': false,
'Undo Charge-Off': false
};
actionButtonData: any;
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
@@ -16,7 +16,7 @@ import { Dates } from 'app/core/utils/dates';
templateUrl: './make-repayment.component.html',
styleUrls: ['./make-repayment.component.scss']
})
export class MakeRepaymentComponent implements OnInit {
export class MakeRepaymentComponent implements OnInit, OnDestroy {
@Input() dataObject: any;
/** Loan Id */
@@ -58,6 +58,10 @@ export class MakeRepaymentComponent implements OnInit {
this.setRepaymentLoanDetails();
}
ngOnDestroy(): void {
}
/**
* Creates the create close form.
*/
@@ -1,5 +1,5 @@
/** Angular Imports */
import { Component, OnInit, Input } from '@angular/core';
import { Component, OnInit, Input, OnDestroy } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
@@ -17,7 +17,7 @@ import { Dates } from 'app/core/utils/dates';
templateUrl: './prepay-loan.component.html',
styleUrls: ['./prepay-loan.component.scss']
})
export class PrepayLoanComponent implements OnInit {
export class PrepayLoanComponent implements OnInit, OnDestroy {
@Input() dataObject: any;
/** Loan Id */
@@ -66,6 +66,9 @@ export class PrepayLoanComponent implements OnInit {
this.prepayData = this.dataObject;
}
ngOnDestroy(): void {
}
/**
* Creates the prepay loan form.
*/
@@ -1,273 +1,273 @@
/** Recurring Deposits Account Buttons Configuration */
export class LoansAccountButtonConfiguration {
optionArray: {
name: string,
taskPermissionName?: string,
}[];
optionArray: {
name: string,
taskPermissionName?: string,
}[];
optionPaymentArray: {
name: string,
taskPermissionName?: string,
}[];
optionPaymentArray: {
name: string,
taskPermissionName?: string,
}[];
buttonsArray: {
name: string,
icon: string,
taskPermissionName?: string,
}[];
buttonsArray: {
name: string,
icon: string,
taskPermissionName?: string,
}[];
constructor(status: string) {
this.setOptions(status);
this.setButtons(status);
}
get singleButtons() {
return this.buttonsArray;
}
get options() {
return this.optionArray;
}
get optionsPayment() {
return this.optionPaymentArray;
constructor(status: string) {
this.setOptions(status);
this.setButtons(status);
}
setButtons(status: string) {
switch (status) {
case 'Active':
this.buttonsArray = [
{
name: 'Add Loan Charge',
icon: 'plus',
taskPermissionName: 'CREATE_LOANCHARGE',
},
{
name: 'Foreclosure',
icon: 'heart-broken',
taskPermissionName: 'FORECLOSURE_LOAN',
},
{
name: 'Make Repayment',
icon: 'coins',
taskPermissionName: 'REPAYMENT_LOAN',
},
{
name: 'Undo Disbursal',
icon: 'undo',
taskPermissionName: 'DISBURSALUNDO_LOAN',
}
];
break;
case 'Submitted and pending approval':
this.buttonsArray = [
{
name: 'Add Loan Charge',
icon: 'plus',
taskPermissionName: 'CREATE_LOANCHARGE',
},
{
name: 'Approve',
icon: 'check',
taskPermissionName: 'APPROVE_LOAN',
},
{
name: 'Modify Application',
icon: 'edit',
taskPermissionName: 'UPDATE_LOAN',
},
{
name: 'Reject',
icon: 'times',
taskPermissionName: 'REJECT_LOAN',
},
];
break;
case 'Approved':
this.buttonsArray = [
{
name: 'Disburse',
icon: 'hand-holding-usd',
taskPermissionName: 'DISBURSE_LOAN',
},
{
name: 'Disburse to Savings',
icon: 'piggy-bank',
taskPermissionName: 'DISBURSETOSAVINGS_LOAN',
},
{
name: 'Undo Approval',
icon: 'undo',
taskPermissionName: 'APPROVALUNDO_LOAN',
},
];
break;
case 'Overpaid':
this.buttonsArray = [
{
name: 'Transfer Funds',
icon: 'exchange',
taskPermissionName: 'CREATE_ACCOUNTTRANSFER',
},
{
name: 'Credit Balance Refund',
icon: 'coins',
taskPermissionName: 'CREATE_CREDIT_BALANCE_REFUND',
}
];
break;
case 'Closed (written off)':
this.buttonsArray = [
{
name: 'Recovery Payment',
icon: 'briefcase',
taskPermissionName: 'RECOVERYPAYMENT_LOAN',
},
];
break;
case 'Closed (obligations met)':
this.buttonsArray = [
{
name: 'Goodwill Credit',
icon: 'coins',
taskPermissionName: 'CREATE_GOODWILL_TRANSACTION',
},
{
name: 'Payout Refund',
icon: 'coins',
taskPermissionName: 'CREATE_PAYOUT_REFUND',
},
{
name: 'Merchant Issued Refund',
icon: 'coins',
taskPermissionName: 'CREATE_MERCHANT_ISSUED_REFUND',
}
];
break;
default:
this.buttonsArray = [];
}
}
get singleButtons() {
return this.buttonsArray;
}
setOptions(status: string) {
switch (status) {
case 'Active':
this.optionArray = [
{
name: 'Waive Interest',
taskPermissionName: 'WAIVEINTERESTPORTION_LOAN',
},
{
name: 'Reschedule',
taskPermissionName: 'CREATE_RESCHEDULELOAN',
},
{
name: 'Write Off',
taskPermissionName: 'WRITEOFF_LOAN',
},
{
name: 'Close (as Rescheduled)',
taskPermissionName: 'CLOSEASRESCHEDULED_LOAN',
},
{
name: 'Close',
taskPermissionName: 'CLOSE_LOAN',
},
{
name: 'Loan Screen Report',
taskPermissionName: 'READ_LOAN',
},
{
name: 'View Guarantors',
taskPermissionName: 'READ_GUARANTOR',
},
{
name: 'Create Guarantor',
taskPermissionName: 'CREATE_GUARANTOR',
},
{
name: 'Recover From Guarantor',
taskPermissionName: 'RECOVERGUARANTEES_LOAN',
},
];
this.optionPaymentArray = [
{
name: 'Goodwill Credit',
taskPermissionName: 'CREATE_GOODWILL_TRANSACTION',
},
{
name: 'Payout Refund',
taskPermissionName: 'CREATE_PAYOUT_REFUND',
},
{
name: 'Merchant Issued Refund',
taskPermissionName: 'CREATE_MERCHANT_ISSUED_REFUND',
}
];
break;
case 'Submitted and pending approval':
this.optionArray = [
{
name: 'Withdrawn by client',
taskPermissionName: 'WITHDRAW_LOAN',
},
{
name: 'Delete',
taskPermissionName: 'DELETE_LOAN',
},
{
name: 'Add Collateral',
taskPermissionName: 'CREATE_COLLATERAL',
},
{
name: 'View Guarantors',
taskPermissionName: 'READ_GUARANTOR',
},
{
name: 'Create Guarantor',
taskPermissionName: 'CREATE_GUARANTOR',
},
{
name: 'Loan Screen Reports',
taskPermissionName: 'READ_LOAN',
},
];
this.optionPaymentArray = [];
break;
case 'Approved':
this.optionArray = [
{
name: 'Add Loan Charge',
taskPermissionName: 'CREATE_LOANCHARGE',
},
{
name: 'View Guarantors',
taskPermissionName: 'READ_GUARANTOR',
},
{
name: 'Create Guarantor',
taskPermissionName: 'CREATE_GUARANTOR',
},
{
name: 'Loan Screen Report',
taskPermissionName: 'READ_LOAN',
},
];
this.optionPaymentArray = [];
break;
default:
this.optionArray = [];
this.optionPaymentArray = [];
}
}
get options() {
return this.optionArray;
}
addOption(option: { name: string, icon?: string, taskPermissionName?: string }) {
this.optionArray.push(option);
}
get optionsPayment() {
return this.optionPaymentArray;
}
addButton(option: { name: string, icon: string, taskPermissionName?: string }) {
this.buttonsArray.push(option);
setButtons(status: string) {
switch (status) {
case 'Active':
this.buttonsArray = [
{
name: 'Add Loan Charge',
icon: 'plus',
taskPermissionName: 'CREATE_LOANCHARGE',
},
{
name: 'Foreclosure',
icon: 'heart-broken',
taskPermissionName: 'FORECLOSURE_LOAN',
},
{
name: 'Make Repayment',
icon: 'coins',
taskPermissionName: 'REPAYMENT_LOAN',
},
{
name: 'Undo Disbursal',
icon: 'undo',
taskPermissionName: 'DISBURSALUNDO_LOAN',
}
];
break;
case 'Submitted and pending approval':
this.buttonsArray = [
{
name: 'Add Loan Charge',
icon: 'plus',
taskPermissionName: 'CREATE_LOANCHARGE',
},
{
name: 'Approve',
icon: 'check',
taskPermissionName: 'APPROVE_LOAN',
},
{
name: 'Modify Application',
icon: 'edit',
taskPermissionName: 'UPDATE_LOAN',
},
{
name: 'Reject',
icon: 'times',
taskPermissionName: 'REJECT_LOAN',
},
];
break;
case 'Approved':
this.buttonsArray = [
{
name: 'Disburse',
icon: 'hand-holding-usd',
taskPermissionName: 'DISBURSE_LOAN',
},
{
name: 'Disburse to Savings',
icon: 'piggy-bank',
taskPermissionName: 'DISBURSETOSAVINGS_LOAN',
},
{
name: 'Undo Approval',
icon: 'undo',
taskPermissionName: 'APPROVALUNDO_LOAN',
},
];
break;
case 'Overpaid':
this.buttonsArray = [
{
name: 'Transfer Funds',
icon: 'exchange',
taskPermissionName: 'CREATE_ACCOUNTTRANSFER',
},
{
name: 'Credit Balance Refund',
icon: 'coins',
taskPermissionName: 'CREATE_CREDIT_BALANCE_REFUND',
}
];
break;
case 'Closed (written off)':
this.buttonsArray = [
{
name: 'Recovery Payment',
icon: 'briefcase',
taskPermissionName: 'RECOVERYPAYMENT_LOAN',
},
];
break;
case 'Closed (obligations met)':
this.buttonsArray = [
{
name: 'Goodwill Credit',
icon: 'coins',
taskPermissionName: 'CREATE_GOODWILL_TRANSACTION',
},
{
name: 'Payout Refund',
icon: 'coins',
taskPermissionName: 'CREATE_PAYOUT_REFUND',
},
{
name: 'Merchant Issued Refund',
icon: 'coins',
taskPermissionName: 'CREATE_MERCHANT_ISSUED_REFUND',
}
];
break;
default:
this.buttonsArray = [];
}
}
setOptions(status: string) {
switch (status) {
case 'Active':
this.optionArray = [
{
name: 'Waive Interest',
taskPermissionName: 'WAIVEINTERESTPORTION_LOAN',
},
{
name: 'Reschedule',
taskPermissionName: 'CREATE_RESCHEDULELOAN',
},
{
name: 'Write Off',
taskPermissionName: 'WRITEOFF_LOAN',
},
{
name: 'Close (as Rescheduled)',
taskPermissionName: 'CLOSEASRESCHEDULED_LOAN',
},
{
name: 'Close',
taskPermissionName: 'CLOSE_LOAN',
},
{
name: 'Loan Screen Report',
taskPermissionName: 'READ_LOAN',
},
{
name: 'View Guarantors',
taskPermissionName: 'READ_GUARANTOR',
},
{
name: 'Create Guarantor',
taskPermissionName: 'CREATE_GUARANTOR',
},
{
name: 'Recover From Guarantor',
taskPermissionName: 'RECOVERGUARANTEES_LOAN',
}
];
this.optionPaymentArray = [
{
name: 'Goodwill Credit',
taskPermissionName: 'CREATE_GOODWILL_TRANSACTION',
},
{
name: 'Payout Refund',
taskPermissionName: 'CREATE_PAYOUT_REFUND',
},
{
name: 'Merchant Issued Refund',
taskPermissionName: 'CREATE_MERCHANT_ISSUED_REFUND',
}
];
break;
case 'Submitted and pending approval':
this.optionArray = [
{
name: 'Withdrawn by client',
taskPermissionName: 'WITHDRAW_LOAN',
},
{
name: 'Delete',
taskPermissionName: 'DELETE_LOAN',
},
{
name: 'Add Collateral',
taskPermissionName: 'CREATE_COLLATERAL',
},
{
name: 'View Guarantors',
taskPermissionName: 'READ_GUARANTOR',
},
{
name: 'Create Guarantor',
taskPermissionName: 'CREATE_GUARANTOR',
},
{
name: 'Loan Screen Reports',
taskPermissionName: 'READ_LOAN',
},
];
this.optionPaymentArray = [];
break;
case 'Approved':
this.optionArray = [
{
name: 'Add Loan Charge',
taskPermissionName: 'CREATE_LOANCHARGE',
},
{
name: 'View Guarantors',
taskPermissionName: 'READ_GUARANTOR',
},
{
name: 'Create Guarantor',
taskPermissionName: 'CREATE_GUARANTOR',
},
{
name: 'Loan Screen Report',
taskPermissionName: 'READ_LOAN',
},
];
this.optionPaymentArray = [];
break;
default:
this.optionArray = [];
this.optionPaymentArray = [];
}
}
addOption(option: { name: string, icon?: string, taskPermissionName?: string }) {
this.optionArray.push(option);
}
addButton(option: { name: string, icon: string, taskPermissionName?: string }) {
this.buttonsArray.push(option);
}
}
@@ -6,8 +6,9 @@
<div class="profile-image-container">
<div>
<img mat-card-md-image class="profile-image" matTooltip="Loans Account"
[src]="'assets/images/loans_account_placeholder.png'">
<mifosx-svg-icon [iconClass]="" iconFile="account_placeholder"
iconName="LOAN_ACCOUNT" iconWidth="210" matTooltip="Loan Account">
</mifosx-svg-icon>
</div>
</div>
@@ -18,7 +19,7 @@
<div fxFlex="60%">
<h3>
<i class="fa fa-stop" matTooltip="{{ loanDetailsData.status.value }}"
[ngClass]="loanDetailsData.inArrears?'status-active-overdue':(loanDetailsData.status.code|statusLookup)"></i>
[ngClass]="loanDetailsData.inArrears?'status-active-overdue':( iconLoanStatusColor() | statusLookup)"></i>
Loan Product: {{loanDetailsData.loanProductName}}<span
class="m-l-10">({{loanDetailsData.accountNo}})</span>
</h3>
@@ -147,6 +147,17 @@ export class LoansViewComponent implements OnInit {
});
}
if (!this.loanDetailsData.chargedOff) {
// Charge-Off only when there is not Interest Recalculation and the Interest Rate is zero
if (!this.loanDetailsData.chargedOff && !this.loanDetailsData.isInterestRecalculationEnabled && this.loanDetailsData.interestRatePerPeriod === 0) {
this.buttonConfig.addButton({
name: 'Charge-Off',
icon: 'coins',
taskPermissionName: 'CHARGEOFF_LOAN'
});
}
}
}
}
@@ -187,6 +198,13 @@ export class LoansViewComponent implements OnInit {
});
}
iconLoanStatusColor() {
if (this.loanDetailsData.chargedOff) {
return 'loanStatusType.chargeoff';
}
return this.loanDetailsData.status.code;
}
/**
* Delete loan Account
*/
@@ -1,7 +1,8 @@
<div class="container">
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="20px" class="transaction-buttons" *ngIf="checkStatus()">
<mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="accruals">Hide Accruals</mat-checkbox>
<mat-checkbox [formControl]="hideAccrualsParam" (click)="hideAccruals()" class="accruals">Hide
Accruals</mat-checkbox>
<button mat-raised-button color="primary" class="transaction-button" [routerLink]="['export']">
Export
</button>
@@ -12,76 +13,90 @@
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Id </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.id }} </td>
</ng-container>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Id </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.id }}
</td>
</ng-container>
<ng-container matColumnDef="office">
<th mat-header-cell *matHeaderCellDef> Office </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.officeName }} </td>
</ng-container>
<ng-container matColumnDef="office">
<th mat-header-cell *matHeaderCellDef> Office </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{
transaction.officeName }} </td>
</ng-container>
<ng-container matColumnDef="externalId">
<th mat-header-cell *matHeaderCellDef> External Id </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)">
<mifosx-external-identifier externalId="{{transaction.externalId}}"></mifosx-external-identifier>
</td>
</ng-container>
<ng-container matColumnDef="externalId">
<th mat-header-cell *matHeaderCellDef> External Id </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)">
<mifosx-external-identifier externalId="{{transaction.externalId}}"></mifosx-external-identifier>
</td>
</ng-container>
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Transaction Date </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.date | dateFormat }} </td>
</ng-container>
<ng-container matColumnDef="date">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Transaction Date </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.date | dateFormat }} </td>
</ng-container>
<ng-container matColumnDef="transactionType">
<th mat-header-cell *matHeaderCellDef> Transaction Type </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.type.value }} </td>
</ng-container>
<ng-container matColumnDef="transactionType">
<th mat-header-cell *matHeaderCellDef> Transaction Type </th>
<td mat-cell *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{
transaction.type.value }} </td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell class="center" *matHeaderCellDef> Amount </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.amount | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="amount">
<th mat-header-cell class="center" *matHeaderCellDef> Amount </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction"
[ngClass]="loanTransactionColor(transaction)"> {{ transaction.amount | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="principal">
<th mat-header-cell class="center" *matHeaderCellDef> Breakdown </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.principalPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="principal">
<th mat-header-cell class="center" *matHeaderCellDef> Breakdown </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction"
[ngClass]="loanTransactionColor(transaction)"> {{ transaction.principalPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="interest">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.interestPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="interest">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction"
[ngClass]="loanTransactionColor(transaction)"> {{ transaction.interestPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="fee">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.feeChargesPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="fee">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction"
[ngClass]="loanTransactionColor(transaction)"> {{ transaction.feeChargesPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="penalties">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.penaltyChargesPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="penalties">
<th mat-header-cell *matHeaderCellDef> </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction"
[ngClass]="loanTransactionColor(transaction)"> {{ transaction.penaltyChargesPortion | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="loanBalance">
<th mat-header-cell class="r-amount" *matHeaderCellDef> Loan Balance </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction" [ngClass]="loanTransactionColor(transaction)"> {{ transaction.outstandingLoanBalance | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="loanBalance">
<th mat-header-cell class="r-amount" *matHeaderCellDef> Loan Balance </th>
<td mat-cell class="r-amount td-min-space" *matCellDef="let transaction"
[ngClass]="loanTransactionColor(transaction)"> {{ transaction.outstandingLoanBalance | formatNumber }} </td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell class="center" *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let transaction" class="center td-min-space">
<button class="account-action-button" *ngIf="!transaction.manuallyReversed" mat-raised-button color="primary" (click)="routeEdit($event)"
[routerLink]="[transaction.id, 'reciept']" matTooltip="View Receipts">
<i class="fa fa-file-text"></i>
</button>
<button class="account-action-button" mat-raised-button color="primary" matTooltip="View Journal Entries" matTooltipPosition="left"
(click)="routeEdit($event)" [routerLink]="['/','journal-entry', 'view', 'L'+transaction.id ]">
<i class="fa fa-arrow-circle-right"></i>
</button>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell class="center" *matHeaderCellDef> Actions </th>
<td mat-cell *matCellDef="let transaction" class="center td-min-space">
<button class="account-action-button" *ngIf="allowUndoTransaction(transaction)" mat-raised-button color="primary" matTooltip="Undo Transaction"
matTooltipPosition="left" (click)="undoTransaction(transaction, $event)">
<i class="fa fa-undo"></i>
</button>
<button class="account-action-button" *ngIf="!transaction.manuallyReversed" mat-raised-button color="primary"
(click)="routeEdit($event)" [routerLink]="[transaction.id, 'reciept']" matTooltip="View Receipts">
<i class="fa fa-file-text"></i>
</button>
<button class="account-action-button" mat-raised-button color="primary" matTooltip="View Journal Entries"
matTooltipPosition="left" (click)="routeEdit($event)"
[routerLink]="['/','journal-entry', 'view', 'L'+transaction.id ]">
<i class="fa fa-arrow-circle-right"></i>
</button>
</td>
</ng-container>
<!-- Sub header -->
<ng-container matColumnDef="header">
@@ -105,15 +120,18 @@
</ng-container>
<ng-container matColumnDef="header-action">
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> </th>
<th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> </th>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-header-row *matHeaderRowDef="['header', 'header-principal', 'header-interest', 'header-fees', 'header-penalties', 'header-action']"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row" (click)="showTransactions(row)"></tr>
<tr mat-header-row
*matHeaderRowDef="['header', 'header-principal', 'header-interest', 'header-fees', 'header-penalties', 'header-action']">
</tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row" (click)="showTransactions(row)">
</tr>
</table>
<mat-paginator [pageSize]="50" [pageSizeOptions]="[50, 100, 200]" showFirstLastButtons></mat-paginator>
<mat-paginator [pageSize]="100" [pageSizeOptions]="[50, 100, 200]" showFirstLastButtons></mat-paginator>
</div>
@@ -32,6 +32,9 @@
.accrual {
color: $msg-default;
}
.chargeoff {
color: $status-chargeoff;
}
}
}
@@ -4,6 +4,11 @@ import { FormControl } from '@angular/forms';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { Dates } from 'app/core/utils/dates';
import { LoansService } from 'app/loans/loans.service';
import { MatDialog } from '@angular/material/dialog';
import { SettingsService } from 'app/settings/settings.service';
import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component';
@Component({
selector: 'mifosx-transactions-tab',
@@ -32,7 +37,11 @@ export class TransactionsTabComponent implements OnInit {
* @param {ActivatedRoute} route Activated Route.
*/
constructor(private route: ActivatedRoute,
private router: Router) {
private dateUtils: Dates,
private router: Router,
private dialog: MatDialog,
private loansService: LoansService,
private settingsService: SettingsService) {
this.route.parent.parent.data.subscribe((data: { loanDetailsData: any }) => {
this.transactions = data.loanDetailsData.transactions;
this.tempTransaction = data.loanDetailsData.transactions;
@@ -42,6 +51,14 @@ export class TransactionsTabComponent implements OnInit {
ngOnInit() {
this.hideAccrualsParam = new FormControl(false);
this.setLoanTransactions(this.transactions);
}
setLoanTransactions(transactions: any) {
this.transactions = transactions;
this.transactions.forEach((element: any) => {
element.date = this.dateUtils.parseDate(element.date);
});
this.dataSource = new MatTableDataSource(this.transactions);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
@@ -99,16 +116,26 @@ export class TransactionsTabComponent implements OnInit {
}
}
loanTransactionColor(loanTransaction: any): string {
if (loanTransaction.manuallyReversed) {
allowUndoTransaction(transaction: any) {
if (transaction.manuallyReversed) {
return false;
}
return ([27].includes(transaction.type.id));
}
loanTransactionColor(transaction: any): string {
if (transaction.manuallyReversed) {
return 'strike';
}
if (loanTransaction.transactionRelations && loanTransaction.transactionRelations.length > 0) {
if (transaction.transactionRelations && transaction.transactionRelations.length > 0) {
return 'linked';
}
if (this.isAccrual(loanTransaction.type)) {
if (this.isAccrual(transaction.type)) {
return 'accrual';
}
if (this.isChargeOff(transaction.type)) {
return 'chargeoff';
}
return '';
}
@@ -120,8 +147,59 @@ export class TransactionsTabComponent implements OnInit {
$event.stopPropagation();
}
/**
* Stops the propagation to view pages.
* @param $event Mouse Event
*/
undoTransaction(transaction: any, $event: MouseEvent) {
$event.stopPropagation();
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
const loanId = this.route.parent.parent.snapshot.params['loanId'];
let command = 'undo';
let operationDate = transaction.date;
let payload = {};
if (this.isChargeOff(transaction.type)) {
command = 'undo-charge-off';
operationDate = this.settingsService.businessDate;
}
payload = {
transactionDate: this.dateUtils.formatDate(operationDate && new Date(operationDate), dateFormat),
transactionAmount: 0,
dateFormat,
locale
};
const undoTransactionAccountDialogRef = this.dialog.open(ConfirmationDialogComponent, {
data: { heading: 'Undo Transaction', dialogContext: `Are you sure you want undo the transaction type ${transaction.type.value} with id ${transaction.id}` }
});
undoTransactionAccountDialogRef.afterClosed().subscribe((response: { confirm: any }) => {
if (response.confirm) {
let transactionId = transaction.id;
if (this.isChargeOff(transaction.type)) {
transactionId = null;
}
this.loansService.executeLoansAccountTransactionsCommand(loanId, command, payload, transactionId).subscribe((responseCmd: any) => {
transaction.manuallyReversed = true;
this.reload();
});
}
});
}
private isAccrual(transactionType: any): boolean {
return (transactionType.accrual || transactionType.code === 'loanTransactionType.overdueCharge');
}
private isChargeOff(transactionType: any): boolean {
return (transactionType.chargeoff || transactionType.code === 'loanTransactionType.chargeOff');
}
private reload() {
const clientId = this.route.parent.parent.snapshot.params['clientId'];
const loanId = this.route.parent.parent.snapshot.params['loanId'];
const url: string = this.router.url;
this.router.navigateByUrl(`/clients/${clientId}/loans-accounts`, { skipLocationChange: true })
.then(() => this.router.navigate([url]));
}
}
+3 -1
View File
@@ -74,6 +74,7 @@ import { DisburseToSavingsAccountComponent } from './loans-view/loan-account-act
import { LoansAccountDatatableStepComponent } from './loans-account-stepper/loans-account-datatable-step/loans-account-datatable-step.component';
import { RescheduleLoanTabComponent } from './loans-view/reschedule-loan-tab/reschedule-loan-tab.component';
import { AdjustLoanChargeComponent } from './loans-view/loan-account-actions/adjust-loan-charge/adjust-loan-charge.component';
import { ChargeOffComponent } from './loans-view/loan-account-actions/charge-off/charge-off.component';
/**
* Loans Module
@@ -146,7 +147,8 @@ import { AdjustLoanChargeComponent } from './loans-view/loan-account-actions/adj
DisburseToSavingsAccountComponent,
LoansAccountDatatableStepComponent,
RescheduleLoanTabComponent,
AdjustLoanChargeComponent
AdjustLoanChargeComponent,
ChargeOffComponent
],
providers: [ ],
})
-1
View File
@@ -589,7 +589,6 @@ export class LoansService {
delete loansAccountData.principalAmount;
return loansAccountData;
}
}
@@ -20,8 +20,8 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!smsCampaignFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -59,7 +59,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -113,8 +113,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
+1
View File
@@ -16,6 +16,7 @@ export class StatusLookupPipe implements PipeTransform {
'loanStatusType.approved': 'status-approved',
'loanStatusType.active': 'status-active',
'loanStatusType.overpaid': 'status-overpaid',
'loanStatusType.chargeoff': 'status-chargeoff',
'savingsAccountStatusType.submitted.and.pending.approval': 'status-pending',
'savingsAccountStatusType.approved': 'status-approved',
'savingsAccountStatusType.active': 'status-active',
@@ -245,8 +245,8 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!fixedDepositProductFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -68,7 +68,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -38,8 +38,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -34,8 +34,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -221,8 +221,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -97,7 +97,7 @@
<mat-divider fxFlex="98%"></mat-divider>
<mat-checkbox fxFlex="48%" labelPosition="before" formControlName="withHoldTax" class="margin-v" matTooltip="An boolean flag to attach taxes to interest posting">
Is Withhold Tax Applicable?
Is Withhold Tax Applicable?
</mat-checkbox>
<mat-form-field fxFlex="48%" *ngIf="fixedDepositProductSettingsForm.value.withHoldTax">
@@ -120,8 +120,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -19,7 +19,7 @@
<mat-form-field fxFlex="31%">
<mat-label>Maximum</mat-label>
<input type="number" matInput formControlName="maxDepositAmount" matTooltip="The maximum deposit amount allowed when a fixed deposit account based on this fixed deposit product is opened.">
</mat-form-field>
@@ -81,8 +81,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -429,8 +429,8 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!loanProductFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -134,7 +134,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -46,8 +46,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -58,8 +58,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -466,8 +466,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -396,8 +396,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -256,8 +256,8 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!recurringDepositProductFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -70,7 +70,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -38,8 +38,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -34,8 +34,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -61,7 +61,7 @@
</div>
<div fxFlex="100%" *ngIf="chart.value.chartSlabs.length === 0">
<h3 class="mat-h3">It's required to add at least one Slab</h3>
<h3 class="mat-h3">It's required to add at least one Slab</h3>
</div>
<table fxFlex="98%" class="mat-elevation-z1" mat-table [dataSource]="chart.value.chartSlabs" *ngIf="chart.value.chartSlabs.length !== 0" multiTemplateDataRows>
@@ -221,8 +221,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -134,8 +134,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -80,8 +80,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -293,8 +293,8 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!savingProductFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -68,7 +68,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -38,8 +38,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -31,8 +31,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -127,8 +127,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -68,8 +68,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -84,8 +84,8 @@
Previous
</button>
<button mat-raised-button matStepperNext [disabled]="!shareProductFormValid">
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -68,7 +68,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -38,8 +38,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -31,8 +31,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -50,7 +50,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -66,8 +66,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -42,8 +42,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -138,7 +138,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -47,8 +47,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -144,8 +144,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
+5 -2
View File
@@ -35,6 +35,7 @@ import { DirectivesModule } from 'app/directives/directives.module';
import { EntityDatatableTabComponent } from './tabs/entity-datatable-tab/entity-datatable-tab.component';
import { DatatableSingleRowComponent } from './tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component';
import { DatatableMultiRowComponent } from './tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component';
import { SvgIconComponent } from './svg-icon/svg-icon.component';
/**
* Shared Module
@@ -75,7 +76,8 @@ import { DatatableMultiRowComponent } from './tabs/entity-datatable-tab/datatabl
EntityDocumentsTabComponent,
EntityDatatableTabComponent,
DatatableSingleRowComponent,
DatatableMultiRowComponent
DatatableMultiRowComponent,
SvgIconComponent
],
exports: [
FileUploadComponent,
@@ -96,7 +98,8 @@ import { DatatableMultiRowComponent } from './tabs/entity-datatable-tab/datatabl
ExternalIdentifierComponent,
EntityNotesTabComponent,
EntityDocumentsTabComponent,
EntityDatatableTabComponent
EntityDatatableTabComponent,
SvgIconComponent
]
})
export class SharedModule { }
@@ -0,0 +1,3 @@
<svg preserveAspectRatio="xMidYMid meet" class="icon" [ngClass]="iconClass" [style.width.px]="iconWidth">
<use [attr.xlink:href]="'assets/images/icons_' + iconFile + '.svg#' + iconName"></use>
</svg>

After

Width:  |  Height:  |  Size: 202 B

@@ -0,0 +1,9 @@
@import "assets/styles/helper";
.icon {
flex: 1;
}
.chargeoff {
color: #ffa726;
}
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SvgIconComponent } from './svg-icon.component';
describe('SvgIconComponent', () => {
let component: SvgIconComponent;
let fixture: ComponentFixture<SvgIconComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SvgIconComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SvgIconComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,19 @@
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'mifosx-svg-icon',
templateUrl: './svg-icon.component.html',
styleUrls: ['./svg-icon.component.scss']
})
export class SvgIconComponent implements OnInit {
@Input() iconFile: string;
@Input() iconName: string;
@Input() iconClass: string;
@Input() iconWidth: string;
constructor() { }
ngOnInit(): void {
}
}
@@ -71,7 +71,7 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -38,8 +38,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -97,8 +97,8 @@
Previous
</button>
<button mat-raised-button matStepperNext>
Next&nbsp;&nbsp;
<fa-icon icon="arrow-right"></fa-icon>
Next
<fa-icon icon="arrow-right" class="m-l-10"></fa-icon>
</button>
</div>
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg">
<g id="LOAN_ACCOUNT">
<path style="opacity:0.932" fill="currentColor" d="M 108.5,19.5 C 125.617,18.6409 138.783,25.3076 148,39.5C 156.644,57.4625 154.477,73.9625 141.5,89C 140.034,89.6355 138.7,90.4688 137.5,91.5C 131.067,86.5552 123.733,84.3885 115.5,85C 124.73,82.6707 129.23,76.8373 129,67.5C 128.394,64.4522 126.894,61.9522 124.5,60C 118.459,57.2291 112.625,54.0624 107,50.5C 105.833,43.8315 108.667,40.8315 115.5,41.5C 118.706,41.3474 121.706,42.0141 124.5,43.5C 126.171,41.4902 126.838,39.1569 126.5,36.5C 123.167,35.8333 119.833,35.1667 116.5,34.5C 116.5,32.1667 116.5,29.8333 116.5,27.5C 114.5,27.5 112.5,27.5 110.5,27.5C 110.5,30.1667 110.5,32.8333 110.5,35.5C 99.5074,37.4837 95.6741,43.817 99,54.5C 103.954,59.3966 109.787,62.8966 116.5,65C 122.705,72.4464 120.872,76.9464 111,78.5C 107.183,78.0041 103.516,77.0041 100,75.5C 97.5268,77.2254 97.0268,79.3921 98.5,82C 101.957,83.7435 105.623,84.7435 109.5,85C 100.167,85.6667 90.8333,85.6667 81.5,85C 69.0875,66.552 69.9208,48.7187 84,31.5C 90.996,24.9179 99.1627,20.9179 108.5,19.5 Z"/>
<path style="opacity:0.961" fill="currentColor" d="M 178.5,83.5 C 187.528,84.0275 191.028,88.6941 189,97.5C 174.525,112.308 159.691,126.808 144.5,141C 116.167,141.333 87.8333,141.667 59.5,142C 47.5,154 35.5,166 23.5,178C 15.1786,180.927 10.3453,178.094 9,169.5C 8.43426,158.479 8.76759,147.479 10,136.5C 23.5,123 37,109.5 50.5,96C 76.0795,94.3523 101.746,94.019 127.5,95C 134.199,99.1875 135.199,104.521 130.5,111C 118.935,112.457 107.268,112.957 95.5,112.5C 95.2865,114.144 95.6198,115.644 96.5,117C 112.167,117.667 127.833,117.667 143.5,117C 154.759,105.237 166.426,94.0707 178.5,83.5 Z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

+3
View File
@@ -68,6 +68,7 @@ $status-inactive: #666f73;
$status-deleted: #000000;
$status-pending: #ffa500;
$status-approved: #0f36e4;
$status-chargeoff: #f39c12;
$status-overpaid: #800080;
$status-active-overdue: #ff0000;
$status-matured: #ff4000;
@@ -75,6 +76,8 @@ $state-done: #00ce00;
$status-transfer-progress:#FF4000;
$status-transfer-hold:#DF0101;
$error-log: #ffa726;
.column-mandatory {
color: $status-active;
text-align: center;
+4
View File
@@ -22,6 +22,10 @@
color: $status-overpaid;
}
.status-chargeoff {
color: $status-chargeoff;
}
.status-active-overdue {
color: $status-active-overdue;
}