From 55280eae2a863587ed4d2c9c1db83f94eb7ef1e1 Mon Sep 17 00:00:00 2001 From: Muskan Khedia <36980003+muskankhedia@users.noreply.github.com> Date: Wed, 22 Jul 2020 20:32:55 +0530 Subject: [PATCH] refactor: Loans Module (#1150) Fixes: #1149 --- .../general-tab/general-tab.component.html | 35 ++- ...curring-deposits-account-view.component.ts | 2 +- .../recurring-deposits-buttons.config.ts | 4 + .../add-loan-charge.component.html | 62 ----- .../add-loan-charge.component.scss | 3 - .../loan-action-button.resolver.ts | 2 + .../loan-charge-template.resolver.ts | 31 --- .../loan-details-general.resolver.ts | 31 --- .../common-resolvers/loan-details.resolver.ts | 2 +- src/app/loans/loans-routing.module.ts | 35 +-- .../account-details.component.ts | 2 +- src/app/loans/loans-view/button-config.ts | 173 -------------- .../general-tab/general-tab.component.ts | 2 +- .../add-collateral.component.html | 2 +- .../add-collateral.component.ts | 2 +- .../add-loan-charge.component.html | 55 +++++ .../add-loan-charge.component.scss | 0 .../add-loan-charge.component.spec.ts | 0 .../add-loan-charge.component.ts | 15 +- .../assign-loan-officer.component.html | 2 +- .../close-as-rescheduled.component.html | 2 +- .../close-as-rescheduled.component.ts | 2 +- .../create-guarantor.component.html | 88 +++++-- .../create-guarantor.component.scss | 31 +++ .../create-guarantor.component.ts | 69 +++++- .../disburse-loan-account.component.html | 2 +- .../disburse-loan-account.component.ts | 2 +- .../disburse/disburse.component.html | 2 +- .../disburse/disburse.component.ts | 2 +- .../foreclosure/foreclosure.component.html | 2 +- .../foreclosure/foreclosure.component.ts | 2 +- .../loan-account-actions.component.ts | 9 +- .../loan-reschedule.component.html | 2 +- .../loan-reschedule.component.ts | 2 +- .../loan-screen-reports.component.ts | 1 - .../loans-account-close.component.html | 2 +- .../loans-account-close.component.ts | 2 +- .../make-repayment.component.html | 2 +- .../make-repayment.component.ts | 2 +- .../prepay-loan/prepay-loan.component.html | 2 +- .../prepay-loan/prepay-loan.component.ts | 2 +- .../recovery-repayment.component.html | 2 +- .../recovery-repayment.component.ts | 2 +- .../reject-loan/reject-loan.component.html | 2 +- .../reject-loan/reject-loan.component.ts | 2 +- .../undo-approval.component.html | 2 +- .../undo-approval/undo-approval.component.ts | 2 +- .../undo-disbursal.component.html | 2 +- .../undo-disbursal.component.ts | 4 +- .../waive-interest.component.html | 2 +- .../waive-interest.component.ts | 2 +- .../withdrawn-by-client.component.html | 2 +- .../withdrawn-by-client.component.ts | 2 +- .../write-off-page.component.html | 2 +- .../write-off-page.component.ts | 2 +- .../loans-view/loan-accounts-button-config.ts | 223 ++++++++++++++++++ .../loans-view/loans-view.component.html | 14 +- .../loans-view/loans-view.component.scss | 7 + .../loans/loans-view/loans-view.component.ts | 97 ++++---- .../overdue-charges-tab.component.ts | 2 +- src/app/loans/loans.module.ts | 2 +- src/app/loans/loans.service.ts | 6 + .../confirmation-dialog.component.html | 2 +- .../confirmation-dialog.component.ts | 19 ++ src/assets/images/loans.png | Bin 0 -> 16169 bytes 65 files changed, 622 insertions(+), 470 deletions(-) delete mode 100644 src/app/loans/add-loan-charge/add-loan-charge.component.html delete mode 100644 src/app/loans/add-loan-charge/add-loan-charge.component.scss delete mode 100644 src/app/loans/common-resolvers/loan-charge-template.resolver.ts delete mode 100644 src/app/loans/common-resolvers/loan-details-general.resolver.ts delete mode 100644 src/app/loans/loans-view/button-config.ts create mode 100644 src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.html create mode 100644 src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.scss rename src/app/loans/{ => loans-view/loan-account-actions}/add-loan-charge/add-loan-charge.component.spec.ts (100%) rename src/app/loans/{ => loans-view/loan-account-actions}/add-loan-charge/add-loan-charge.component.ts (88%) create mode 100644 src/app/loans/loans-view/loan-accounts-button-config.ts create mode 100644 src/assets/images/loans.png diff --git a/src/app/clients/clients-view/general-tab/general-tab.component.html b/src/app/clients/clients-view/general-tab/general-tab.component.html index 8dee82543..1b9233971 100644 --- a/src/app/clients/clients-view/general-tab/general-tab.component.html +++ b/src/app/clients/clients-view/general-tab/general-tab.component.html @@ -129,7 +129,7 @@ Type - + @@ -137,20 +137,30 @@ Actions - - - - + + + + + + + @@ -193,11 +203,10 @@ Type - + - Closed Date {{element.timeline.closedOnDate | date}} diff --git a/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.ts b/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.ts index 1031fa98e..b0eb1ec54 100644 --- a/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.ts +++ b/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-account-view.component.ts @@ -99,7 +99,7 @@ export class RecurringDepositsAccountViewComponent implements OnInit { } if (!this.isprematureAllowed) { - this.buttonConfig.addOption({ + this.buttonConfig.addButton({ name: 'Close', icon: 'fa fa-arrow-right' }); diff --git a/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-buttons.config.ts b/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-buttons.config.ts index 40b32caa3..71c7baa57 100644 --- a/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-buttons.config.ts +++ b/src/app/deposits/recurring-deposits/recurring-deposits-account-view/recurring-deposits-buttons.config.ts @@ -133,4 +133,8 @@ export class RecurringDepositsButtonsConfiguration { this.optionArray.push(option); } + addButton(option: { name: string, icon: string, taskPermissionName?: string }) { + this.buttonsArray.push(option); + } + } diff --git a/src/app/loans/add-loan-charge/add-loan-charge.component.html b/src/app/loans/add-loan-charge/add-loan-charge.component.html deleted file mode 100644 index 365db7f98..000000000 --- a/src/app/loans/add-loan-charge/add-loan-charge.component.html +++ /dev/null @@ -1,62 +0,0 @@ -
- - - -
- - - -
- - Charge - - - {{ loanCharge.name + ' (' + loanCharge.currency.name + ')' }} - - - - Charge is required - - - - - Amount - - - Amount is required - - - - - Charge Calculation - - - - - Charge Time - - - - - Due On - - - - - Due Date is required - - - -
- - - - - - -
-
- -
- -
diff --git a/src/app/loans/add-loan-charge/add-loan-charge.component.scss b/src/app/loans/add-loan-charge/add-loan-charge.component.scss deleted file mode 100644 index c5d1982b3..000000000 --- a/src/app/loans/add-loan-charge/add-loan-charge.component.scss +++ /dev/null @@ -1,3 +0,0 @@ -.container{ - width: 37rem; -} diff --git a/src/app/loans/common-resolvers/loan-action-button.resolver.ts b/src/app/loans/common-resolvers/loan-action-button.resolver.ts index 410b20926..6d999769b 100644 --- a/src/app/loans/common-resolvers/loan-action-button.resolver.ts +++ b/src/app/loans/common-resolvers/loan-action-button.resolver.ts @@ -58,6 +58,8 @@ export class LoanActionButtonResolver implements Resolve { return this.loansService.getLoanScreenReportsData(); } else if (loanActionButton === 'approve') { return this.loansService.getLoanApprovalTemplate(loanId); + } else if (loanActionButton === 'add-loan-charge') { + return this.loansService.getLoanChargeTemplateResource(loanId); } else { return undefined; } diff --git a/src/app/loans/common-resolvers/loan-charge-template.resolver.ts b/src/app/loans/common-resolvers/loan-charge-template.resolver.ts deleted file mode 100644 index 0af6438eb..000000000 --- a/src/app/loans/common-resolvers/loan-charge-template.resolver.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** Angular Imports */ -import { Injectable } from '@angular/core'; -import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; - -/** rxjs Imports */ -import { Observable } from 'rxjs'; - -/** Custom Services */ -import { LoansService } from '../loans.service'; - -/** - * Loan Charge Template data resolver. - */ -@Injectable() -export class LoanChargeTemplateResolver implements Resolve { - - /** - * @param {LoansService} LoansService loans service. - */ - constructor(private loansService: LoansService) {} - - /** - * Returns the Loan Charge Template. - * @returns {Observable} - */ - resolve(route: ActivatedRouteSnapshot): Observable { - const loanId = route.paramMap.get('loanId'); - return this.loansService.getLoanChargeTemplateResource(loanId); - } - -} diff --git a/src/app/loans/common-resolvers/loan-details-general.resolver.ts b/src/app/loans/common-resolvers/loan-details-general.resolver.ts deleted file mode 100644 index 592f84a20..000000000 --- a/src/app/loans/common-resolvers/loan-details-general.resolver.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** Angular Imports */ -import { Injectable } from '@angular/core'; -import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; - -/** rxjs Imports */ -import { Observable } from 'rxjs'; - -/** Custom Services */ -import { LoansService } from '../loans.service'; - -/** - * Clients data resolver. - */ -@Injectable() -export class LoanDetailsGeneralResolver implements Resolve { - - /** - * @param {LoansService} LoansService Loans service. - */ - constructor(private loansService: LoansService) { } - - /** - * Returns the Loans data. - * @returns {Observable} - */ - resolve(route: ActivatedRouteSnapshot): Observable { - const loanId = route.parent.paramMap.get('loanId'); - return this.loansService.getLoanAccountDetails(loanId); - } - -} diff --git a/src/app/loans/common-resolvers/loan-details.resolver.ts b/src/app/loans/common-resolvers/loan-details.resolver.ts index a404e2033..339e0c88c 100644 --- a/src/app/loans/common-resolvers/loan-details.resolver.ts +++ b/src/app/loans/common-resolvers/loan-details.resolver.ts @@ -24,7 +24,7 @@ export class LoanDetailsResolver implements Resolve { * @returns {Observable} */ resolve(route: ActivatedRouteSnapshot): Observable { - const loanId = route.paramMap.get('loanId'); + const loanId = route.paramMap.get('loanId') || route.parent.paramMap.get('loanId'); return this.loansService.getLoanAccountAssociationDetails(loanId); } diff --git a/src/app/loans/loans-routing.module.ts b/src/app/loans/loans-routing.module.ts index 1d2a3644d..b1bf29be5 100644 --- a/src/app/loans/loans-routing.module.ts +++ b/src/app/loans/loans-routing.module.ts @@ -6,7 +6,6 @@ import { Routes, RouterModule } from '@angular/router'; import { extract } from '../core/i18n/i18n.service'; /** Custom Components */ -import { AddLoanChargeComponent } from './add-loan-charge/add-loan-charge.component'; import { LoansViewComponent } from './loans-view/loans-view.component'; import { GeneralTabComponent } from './loans-view/general-tab/general-tab.component'; import { AccountDetailsComponent } from './loans-view/account-details/account-details.component'; @@ -27,9 +26,7 @@ import { StandingInstructionsTabComponent } from 'app/loans/loans-view/standing- import { EditLoansAccountComponent } from './edit-loans-account/edit-loans-account.component'; /** Custom Resolvers */ -import { LoanChargeTemplateResolver } from './common-resolvers/loan-charge-template.resolver'; import { LoanDetailsResolver } from './common-resolvers/loan-details.resolver'; -import { LoanDetailsGeneralResolver } from './common-resolvers/loan-details-general.resolver'; import { LoanNotesResolver } from './common-resolvers/loan-notes.resolver'; import { LoanDetailsChargesResolver } from './common-resolvers/loan-details-charges.resolver'; import { LoanDatatablesResolver } from './common-resolvers/loan-datatables.resolver'; @@ -69,18 +66,12 @@ const routes: Routes = [ { path: 'general', component: GeneralTabComponent, - data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false }, - resolve: { - loanDetailsData: LoanDetailsGeneralResolver - } + data: { title: extract('General'), breadcrumb: 'General', routeParamBreadcrumb: false } }, { path: 'accountdetail', component: AccountDetailsComponent, - data: { title: extract('Account Detail'), breadcrumb: 'Account Detail', routeParamBreadcrumb: false }, - resolve: { - loanDetailsData: LoanDetailsGeneralResolver - } + data: { title: extract('Account Detail'), breadcrumb: 'Account Detail', routeParamBreadcrumb: false } }, { path: 'original-schedule', @@ -125,10 +116,7 @@ const routes: Routes = [ { path: 'overdue-charges', component: OverdueChargesTabComponent, - data: { title: extract('Overdue Charges'), breadcrumb: 'Overdue Charges', routeParamBreadcrumb: false }, - resolve: { - loanDetailsData: LoanDetailsGeneralResolver - } + data: { title: extract('Overdue Charges'), breadcrumb: 'Overdue Charges', routeParamBreadcrumb: false } }, { path: 'floating-interest-rates', @@ -152,7 +140,7 @@ const routes: Routes = [ data: { title: extract('Loan Documents'), breadcrumb: 'Loan Documents', routeParamBreadcrumb: false }, resolve: { loanDocuments: LoanDocumentsResolver, - loanDetailsData: LoanDetailsGeneralResolver + loanDetailsData: LoanDetailsResolver }, }, { @@ -166,10 +154,7 @@ const routes: Routes = [ { path: 'standing-instruction', component: StandingInstructionsTabComponent, - data: { title: extract('Standing Instructions'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false }, - resolve: { - loanDetailsData: LoanDetailsGeneralResolver - }, + data: { title: extract('Standing Instructions'), breadcrumb: 'Standing Instructions', routeParamBreadcrumb: false } }, { path: 'datatables', @@ -182,14 +167,6 @@ const routes: Routes = [ } }] }, - { - path: 'add-loan-charge', - component: AddLoanChargeComponent, - data: { title: extract('Add Loan Charge'), breadcrumb: 'Add Loan Charge', routeParamBreadcrumb: false }, - resolve: { - loanChargeTemplate: LoanChargeTemplateResolver - } - }, { path: 'actions/:action', component: LoanAccountActionsComponent, @@ -217,8 +194,6 @@ const routes: Routes = [ exports: [RouterModule], declarations: [], providers: [ - LoanChargeTemplateResolver, - LoanDetailsGeneralResolver, LoanDetailsResolver, LoanNotesResolver, LoanDetailsChargesResolver, diff --git a/src/app/loans/loans-view/account-details/account-details.component.ts b/src/app/loans/loans-view/account-details/account-details.component.ts index 3c3195646..26f6bcc35 100644 --- a/src/app/loans/loans-view/account-details/account-details.component.ts +++ b/src/app/loans/loans-view/account-details/account-details.component.ts @@ -15,7 +15,7 @@ export class AccountDetailsComponent implements OnInit { }[]; constructor(private route: ActivatedRoute) { - this.route.data.subscribe((data: { loanDetailsData: any, }) => { + this.route.parent.data.subscribe((data: { loanDetailsData: any, }) => { this.loanDetails = data.loanDetailsData; }); } diff --git a/src/app/loans/loans-view/button-config.ts b/src/app/loans/loans-view/button-config.ts deleted file mode 100644 index d0bcd8839..000000000 --- a/src/app/loans/loans-view/button-config.ts +++ /dev/null @@ -1,173 +0,0 @@ -export const ButtonConfig = { - 'Submitted and pending approval': { - singlebuttons: [ - { - name: 'Add Loan Charge', - icon: 'fa fa-plus', - taskPermissionName: 'CREATE_LOANCHARGE', - }, - { - name: 'Approve', - icon: 'fa fa-check', - taskPermissionName: 'APPROVE_LOAN', - }, - { - name: 'Modify Application', - icon: 'fa fa-pincel-square-o', - taskPermissionName: 'UPDATE_LOAN', - }, - { - name: 'Reject', - icon: 'fa fa-times', - taskPermissionName: 'REJECT_LOAN', - }, - ], - options: [ - { - 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', - }, - ], - }, - - Approved: { - singlebuttons: [ - { - name: 'Disburse', - icon: 'fa fa-flag', - taskPermissionName: 'DISBURSE_LOAN', - }, - { - name: 'Disburse to Savings', - icon: 'fa fa-flag', - taskPermissionName: 'DISBURSETOSAVINGS_LOAN', - }, - { - name: 'Undo Approval', - icon: 'fa fa-undo', - taskPermissionName: 'APPROVALUNDO_LOAN', - }, - ], - options: [ - { - 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', - }, - ], - }, - - Active: { - singlebuttons: [ - { - name: 'Add Loan Charge', - icon: 'fa fa-plus', - taskPermissionName: 'CREATE_LOANCHARGE', - }, - { - name: 'Foreclosure', - icon: 'icon-dollar', - taskPermissionName: 'FORECLOSURE_LOAN', - }, - { - name: 'Make Repayment', - icon: 'fa fa-dollar', - taskPermissionName: 'REPAYMENT_LOAN', - }, - { - name: 'Undo Disbursal', - icon: 'fa fa-undo', - taskPermissionName: 'DISBURSALUNDO_LOAN', - }, - ], - options: [ - { - 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', - }, - ], - }, - - Overpaid: { - singlebuttons: [ - { - name: 'Transfer Funds', - icon: 'fa fa-exchange', - taskPermissionName: 'CREATE_ACCOUNTTRANSFER', - }, - ], - }, - - ClosedWrittenOff: { - singlebuttons: [ - { - name: 'Recovery Payment', - icon: 'fa fa-briefcase', - taskPermissionName: 'RECOVERYPAYMENT_LOAN', - }, - ], - }, -}; diff --git a/src/app/loans/loans-view/general-tab/general-tab.component.ts b/src/app/loans/loans-view/general-tab/general-tab.component.ts index 6e95cd02e..e1e51702f 100644 --- a/src/app/loans/loans-view/general-tab/general-tab.component.ts +++ b/src/app/loans/loans-view/general-tab/general-tab.component.ts @@ -32,7 +32,7 @@ export class GeneralTabComponent implements OnInit { detailsDataSource: MatTableDataSource; constructor(private route: ActivatedRoute) { - this.route.data.subscribe((data: { loanDetailsData: any, }) => { + this.route.parent.data.subscribe((data: { loanDetailsData: any, }) => { this.loanDetails = data.loanDetailsData; }); } diff --git a/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.html b/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.html index 87e6d3a57..fc226102b 100644 --- a/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.html +++ b/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.html @@ -33,7 +33,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.ts b/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.ts index e328c28b6..8e43296b1 100644 --- a/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/add-collateral/add-collateral.component.ts @@ -62,7 +62,7 @@ export class AddCollateralComponent implements OnInit { const collateralForm = this.collateralForm.value; collateralForm.locale = 'en'; this.loanService.createLoanCollateral(loanId, collateralForm).subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.html b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.html new file mode 100644 index 000000000..1e064b05f --- /dev/null +++ b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.html @@ -0,0 +1,55 @@ +
+ + + +
+ + Charge + + + {{ loanCharge.name + ' (' + loanCharge?.currency.name + ')' }} + + + + Charge is required + + + + + Amount + + + Amount is required + + + + + Charge Calculation + + + + + Charge Time + + + + + Due On + + + + + Due Date is required + + + +
+ + + + + + +
+
\ No newline at end of file diff --git a/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.scss b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/loans/add-loan-charge/add-loan-charge.component.spec.ts b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.spec.ts similarity index 100% rename from src/app/loans/add-loan-charge/add-loan-charge.component.spec.ts rename to src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.spec.ts diff --git a/src/app/loans/add-loan-charge/add-loan-charge.component.ts b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.ts similarity index 88% rename from src/app/loans/add-loan-charge/add-loan-charge.component.ts rename to src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.ts index 4e55a5a1a..d4b3cf1fb 100644 --- a/src/app/loans/add-loan-charge/add-loan-charge.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component.ts @@ -5,13 +5,13 @@ import { Router, ActivatedRoute } from '@angular/router'; import { DatePipe } from '@angular/common'; /** Custom Services */ -import { LoansService } from '../loans.service'; +import { LoansService } from '../../../loans.service'; /** * Create Add Loan Charge component. */ @Component({ - selector: 'mifosx-addloancharge', + selector: 'mifosx-add-loan-charge', templateUrl: './add-loan-charge.component.html', styleUrls: ['./add-loan-charge.component.scss'] }) @@ -28,6 +28,9 @@ export class AddLoanChargeComponent implements OnInit { id: number; name: string; amount: number; + currency: { + name: string; + }; chargeCalculationType: { value: any; }; @@ -51,10 +54,10 @@ export class AddLoanChargeComponent implements OnInit { private router: Router, private datePipe: DatePipe, private loansService: LoansService) { - this.route.data.subscribe((data: { loanChargeTemplate: any }) => { - this.loanChargeOptions = data.loanChargeTemplate.chargeOptions; + this.route.data.subscribe((data: { actionButtonData: any }) => { + this.loanChargeOptions = data.actionButtonData.chargeOptions; }); - this.loanId = this.route.snapshot.params['loanId']; + this.loanId = this.route.parent.snapshot.params['loanId']; } /** @@ -102,7 +105,7 @@ export class AddLoanChargeComponent implements OnInit { loanCharge.locale = 'en'; loanCharge.dateFormat = dateFormat; this.loansService.createLoanCharge(this.loanId, 'charges', loanCharge).subscribe(res => { - this.router.navigate(['../'], { relativeTo: this.route }); + this.router.navigate(['../../'], { relativeTo: this.route }); }); } } diff --git a/src/app/loans/loans-view/loan-account-actions/assign-loan-officer/assign-loan-officer.component.html b/src/app/loans/loans-view/loan-account-actions/assign-loan-officer/assign-loan-officer.component.html index 668d60efd..001bb977c 100644 --- a/src/app/loans/loans-view/loan-account-actions/assign-loan-officer/assign-loan-officer.component.html +++ b/src/app/loans/loans-view/loan-account-actions/assign-loan-officer/assign-loan-officer.component.html @@ -31,7 +31,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.html b/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.html index 2a75397fa..869e73892 100644 --- a/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.html +++ b/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.html @@ -24,7 +24,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.ts b/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.ts index 98f2bb6f3..96cb993b0 100644 --- a/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/close-as-rescheduled/close-as-rescheduled.component.ts @@ -68,7 +68,7 @@ export class CloseAsRescheduledComponent implements OnInit { closeForm.dateFormat = dateFormat; this.loanService.submitLoanActionButton(this.loanId, closeForm, 'close-rescheduled') .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } } diff --git a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.html b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.html index 0add49ca3..657fbdaa9 100644 --- a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.html +++ b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.html @@ -5,32 +5,67 @@
- - Existing Client - + + Existing Client + - + Name - + Name is required + + + {{ client.displayName }} + + + + + Relationship + + + {{ relationType.name }} + + + + + + + + Account + + + {{ accountOption.productName }} - {{ accountOption.accountNo }} + + + + + + Amount + + + + + - - Relationship - - - {{ relationType.name }} - - - - + + + Relationship + + + {{ relationType.name }} + + + + First Name @@ -89,7 +124,7 @@
- + @@ -97,4 +132,25 @@ - \ No newline at end of file + + +
+
+
Client Details
+
+
+
Name
+
{{newGuarantorForm.controls.name.value.displayName}}
+
+
+
Id
+
{{newGuarantorForm.controls.name.value.id}}
+
+
+
Office
+
{{newGuarantorForm.controls.name.value.officeName}}
+
+
+
+ + diff --git a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.scss b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.scss index e69de29bb..efe1f45f4 100644 --- a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.scss +++ b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.scss @@ -0,0 +1,31 @@ +.container { + + .mat-table { + display: block; + font-family: Tahoma, Verdana; + width: 100%; + } + + .mat-row, + .mat-header-row { + display: flex; + border-bottom-width: 1px; + border-bottom-style: solid; + align-items: center; + min-height: 48px; + padding: 0 24px; + } + + .mat-cell, + .mat-header-cell { + flex: 1; + overflow: hidden; + word-wrap: break-word; + } + + h3 { + padding-left: 0; + margin-bottom: 0; + } + +} diff --git a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts index feacd649b..d57768c09 100644 --- a/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/create-guarantor/create-guarantor.component.ts @@ -1,11 +1,12 @@ /** Angular Imports */ -import { Component, OnInit, Input } from '@angular/core'; +import { Component, OnInit, Input, AfterViewInit } from '@angular/core'; import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; /** Custom Services */ import { LoansService } from 'app/loans/loans.service'; import { DatePipe } from '@angular/common'; +import { ClientsService } from 'app/clients/clients.service'; /** * Create Guarantor Action @@ -15,7 +16,7 @@ import { DatePipe } from '@angular/common'; templateUrl: './create-guarantor.component.html', styleUrls: ['./create-guarantor.component.scss'] }) -export class CreateGuarantorComponent implements OnInit { +export class CreateGuarantorComponent implements OnInit, AfterViewInit { @Input() dataObject: any; /** New Guarantor Form */ @@ -30,6 +31,10 @@ export class CreateGuarantorComponent implements OnInit { minDate = new Date(2000, 0, 1); /** Maximum date allowed. */ maxDate = new Date(); + /** Client data. */ + clientsData: any = []; + /** Account Options */ + accountOptions: any = []; /** * @param {FormBuilder} formBuilder Form Builder. @@ -42,7 +47,8 @@ export class CreateGuarantorComponent implements OnInit { private loanService: LoansService, private route: ActivatedRoute, private router: Router, - private datePipe: DatePipe) { + private datePipe: DatePipe, + private clientsService: ClientsService) { this.loanId = this.route.parent.snapshot.params['loanId']; } @@ -57,7 +63,9 @@ export class CreateGuarantorComponent implements OnInit { this.newGuarantorForm = this.formBuilder.group({ 'existingClient': [''], 'name': ['', Validators.required], - 'clientRelationshipTypeId': [''] + 'clientRelationshipTypeId': [''], + 'savingsId': [''], + 'amount': [''] }); } @@ -86,8 +94,12 @@ export class CreateGuarantorComponent implements OnInit { this.newGuarantorForm.addControl('mobileNumber', new FormControl('')); this.newGuarantorForm.addControl('housePhoneNumber', new FormControl('')); this.newGuarantorForm.removeControl('name'); + this.newGuarantorForm.removeControl('savingsId'); + this.newGuarantorForm.removeControl('amount'); } else { this.newGuarantorForm.addControl('name', new FormControl('')); + this.newGuarantorForm.addControl('savingsId', new FormControl('')); + this.newGuarantorForm.addControl('amount', new FormControl('')); this.newGuarantorForm.removeControl('firstname'); this.newGuarantorForm.removeControl('lastname'); this.newGuarantorForm.removeControl('dob'); @@ -101,6 +113,39 @@ export class CreateGuarantorComponent implements OnInit { }); } + /** + * Subscribes to Clients search filter: + */ + ngAfterViewInit() { + if (this.newGuarantorForm.value.existingClient) { + this.newGuarantorForm.get('name').valueChanges.subscribe((value: string) => { + if (value.length >= 2) { + this.clientsService.getFilteredClients('displayName', 'ASC', true, value) + .subscribe((data: any) => { + this.clientsData = data.pageItems; + }); + } + }); + } + } + + clientSelected(clientDetails: any){ + console.log(clientDetails); + this.accountOptions = []; + this.loanService.guarantorAccountResource(this.loanId, clientDetails.id).subscribe((response: any) => { + this.accountOptions = response.accountLinkingOptions; + }) + } + + /** + * Displays Client name in form control input. + * @param {any} client Client data. + * @returns {string} Client name if valid otherwise undefined. + */ + displayClient(client: any): string | undefined { + return client ? client.displayName : undefined; + } + /** Submits the new guarantor details form */ submit() { const prevdob: Date = this.newGuarantorForm.value.dob; @@ -108,17 +153,25 @@ export class CreateGuarantorComponent implements OnInit { // TODO: Update once language and date settings are setup const dateFormat = 'dd-MM-yyyy'; const locale = 'en'; - const newGuarantorData = { + let newGuarantorData = { ... this.newGuarantorForm.value, - dob: this.datePipe.transform(prevdob, dateFormat), locale, - dateFormat, guarantorTypeId }; + + if(this.newGuarantorForm.value.existingClient) { + newGuarantorData['entityId'] = this.newGuarantorForm.controls.name.value.id; + } else { + newGuarantorData['dob'] = this.datePipe.transform(prevdob, dateFormat), + newGuarantorData['dateFormat'] = dateFormat + } + delete newGuarantorData.existingClient; + delete newGuarantorData.name; + this.loanService.createNewGuarantor(this.loanId, newGuarantorData) .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.html b/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.html index cb2498298..ffe3c5534 100644 --- a/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.html +++ b/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.html @@ -40,7 +40,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.ts b/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.ts index 1e5aaa5a0..e52d94bd3 100644 --- a/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/disburse-loan-account/disburse-loan-account.component.ts @@ -72,7 +72,7 @@ export class DisburseLoanAccountComponent implements OnInit { disbursementForm.locale = 'en'; disbursementForm.dateFormat = dateFormat; this.loanService.loanActionButtons(loanId, 'disbursetosavings', disbursementForm).subscribe((response: any) => { - this.router.navigate(['../general'], {relativeTo: this.route}); + this.router.navigate(['../../general'], {relativeTo: this.route}); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.html b/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.html index fae3fa03b..7cc85268c 100644 --- a/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.html +++ b/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.html @@ -80,7 +80,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.ts b/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.ts index ceeb3a3db..11474a8c6 100644 --- a/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/disburse/disburse.component.ts @@ -109,7 +109,7 @@ export class DisburseComponent implements OnInit { disbursementLoanData.dateFormat = dateFormat; this.loanService.loanActionButtons(this.loanId, 'disburse', disbursementLoanData ) .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.html b/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.html index 525b80205..5a9d6842b 100644 --- a/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.html +++ b/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.html @@ -49,7 +49,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts b/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts index d8b83e2ec..f8f40e6eb 100644 --- a/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/foreclosure/foreclosure.component.ts @@ -117,7 +117,7 @@ export class ForeclosureComponent implements OnInit { this.loanService.loanForclosureData(this.loanId, formData) .subscribe((response: any) => { - this.router.navigate([`../general`], { relativeTo: this.route }); + this.router.navigate([`../../general`], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts index 627543ab6..b189adefb 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/loan-account-actions.component.ts @@ -33,7 +33,8 @@ export class LoanAccountActionsComponent { withdrawn_by_client: boolean, undo_disbursal: boolean, loan_screen_reports: boolean, - approve: boolean } = { + approve: boolean, + add_loan_charge: boolean } = { close: false, undo_approval: false, write_off: false, @@ -54,7 +55,8 @@ export class LoanAccountActionsComponent { withdrawn_by_client: false, undo_disbursal: false, loan_screen_reports: false, - approve: false }; + approve: false, + add_loan_charge: false }; actionButtonData: any; actionName: any; @@ -74,6 +76,9 @@ export class LoanAccountActionsComponent { if (this.actionName === 'change-loan-officer') { this.actionName = 'assign-loan-officer'; } + for (const key of Object.keys(this.actions)) { + this.actions[key] = false; + } this.actions[this.actionName.replace(/-/g, '_')] = true; }); } diff --git a/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.html b/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.html index 711f62abf..140bbd6e4 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.html +++ b/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.html @@ -88,7 +88,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.ts index f767b67cb..43508ceac 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/loan-reschedule/loan-reschedule.component.ts @@ -81,7 +81,7 @@ export class LoanRescheduleComponent implements OnInit { // TODO: needs to be updated // mentioned in Community App: // location.path('/loans/' + scope.loanId + '/viewreschedulerequest/'+ data.resourceId); - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/loan-screen-reports/loan-screen-reports.component.ts b/src/app/loans/loans-view/loan-account-actions/loan-screen-reports/loan-screen-reports.component.ts index 9179a6973..17391b8ce 100644 --- a/src/app/loans/loans-view/loan-account-actions/loan-screen-reports/loan-screen-reports.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/loan-screen-reports/loan-screen-reports.component.ts @@ -52,7 +52,6 @@ export class LoanScreenReportsComponent implements OnInit { ngOnInit() { this.templatesData = this.dataObject; this.createLoanScreenReportForm(); - console.log('templateData: ', this.templatesData); } /** diff --git a/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.html b/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.html index 087831899..67595ca60 100644 --- a/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.html +++ b/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.html @@ -24,7 +24,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.ts b/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.ts index 8c8a3faa8..d0c7974b4 100644 --- a/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/loans-account-close/loans-account-close.component.ts @@ -69,7 +69,7 @@ export class LoansAccountCloseComponent implements OnInit { closeForm.dateFormat = dateFormat; this.loanService.submitLoanActionButton(this.loanId, closeForm, 'close') .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html index 8c8d971da..65a6ff2bb 100644 --- a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html +++ b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.html @@ -80,7 +80,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts index 885b78738..17a94da37 100644 --- a/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/make-repayment/make-repayment.component.ts @@ -108,7 +108,7 @@ export class MakeRepaymentComponent implements OnInit { repaymentLoanData.dateFormat = dateFormat; this.loanService.submitLoanActionButton(this.loanId, repaymentLoanData, 'repayment') .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.html b/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.html index 509b3d89b..354210f97 100644 --- a/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.html +++ b/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.html @@ -93,7 +93,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts b/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts index 6ccf2394c..8190a7103 100644 --- a/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/prepay-loan/prepay-loan.component.ts @@ -120,7 +120,7 @@ export class PrepayLoanComponent implements OnInit { prepayLoanData.dateFormat = dateFormat; this.loanService.submitLoanActionButton(this.loanId, prepayLoanData, 'repayment') .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.html b/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.html index 632c2de22..a7c488d7a 100644 --- a/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.html +++ b/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.html @@ -81,7 +81,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.ts b/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.ts index 54d1cb42b..f8255a345 100644 --- a/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/recovery-repayment/recovery-repayment.component.ts @@ -109,7 +109,7 @@ export class RecoveryRepaymentComponent implements OnInit { recoveryRepaymentLoanData.dateFormat = dateFormat; this.loanService.submitLoanActionButton(this.loanId, recoveryRepaymentLoanData, 'recoverypayment') .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.html b/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.html index b80fb0b54..da666d03f 100644 --- a/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.html +++ b/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.html @@ -24,7 +24,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.ts b/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.ts index f86edd1d5..9c3f45f33 100644 --- a/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/reject-loan/reject-loan.component.ts @@ -68,7 +68,7 @@ export class RejectLoanComponent implements OnInit { rejectForm.locale = 'en'; rejectForm.dateFormat = dateFormat; this.loanService.loanActionButtons(this.loanId, 'reject', rejectForm).subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.html b/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.html index 98586f8eb..82a963ebc 100644 --- a/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.html +++ b/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.html @@ -8,7 +8,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.ts b/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.ts index 63c4d0f6c..b38a355c1 100644 --- a/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/undo-approval/undo-approval.component.ts @@ -38,7 +38,7 @@ export class UndoApprovalComponent implements OnInit { submit() { const loanId = this.route.parent.snapshot.params['loanId']; this.loanService.loanActionButtons(loanId, 'undoapproval', { 'note': this.note.value }).subscribe((response: any) => { - this.router.navigate(['../general'], {relativeTo: this.route}); + this.router.navigate(['../../general'], {relativeTo: this.route}); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.html b/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.html index 7a66639d4..fe9ce104e 100644 --- a/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.html +++ b/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.html @@ -8,7 +8,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.ts b/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.ts index ee67a8597..8a179d3cf 100644 --- a/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/undo-disbursal/undo-disbursal.component.ts @@ -45,8 +45,8 @@ export class UndoDisbursalComponent implements OnInit { * Submits the undo disbursal form. */ submit() { - this.loansService.loanActionButtons(this.loanId, 'undoDisbursal', {'note': this.note.value}).subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.loansService.loanActionButtons(this.loanId, 'undodisbursal', {'note': this.note.value}).subscribe((response: any) => { + this.router.navigate(['../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.html b/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.html index de973ee2b..0ef68e338 100644 --- a/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.html +++ b/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.html @@ -32,7 +32,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.ts b/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.ts index b4cb5113c..837f4c184 100644 --- a/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/waive-interest/waive-interest.component.ts @@ -71,7 +71,7 @@ export class WaiveInterestComponent implements OnInit { loanInterestForm.locale = 'en'; loanInterestForm.dateFormat = dateFormat; this.loanService.submitLoanActionButton(loanId, loanInterestForm, 'waiveinterest').subscribe((response: any) => { - this.router.navigate(['../general'], {relativeTo: this.route}); + this.router.navigate(['../../general'], {relativeTo: this.route}); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.html b/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.html index f7cf1e210..d63bfbdac 100644 --- a/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.html +++ b/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.html @@ -24,7 +24,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.ts b/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.ts index 6808a1a02..025bcc307 100644 --- a/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/withdrawn-by-client/withdrawn-by-client.component.ts @@ -73,7 +73,7 @@ export class WithdrawnByClientComponent implements OnInit { WithdrawnByClientLoanData.dateFormat = dateFormat; this.loanService.loanActionButtons(this.loanId, 'withdrawnByApplicant', WithdrawnByClientLoanData) .subscribe((response: any) => { - this.router.navigate(['../general'], { relativeTo: this.route }); + this.router.navigate(['../../../general'], { relativeTo: this.route }); }); } diff --git a/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.html b/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.html index 0cdb7102e..da20e2163 100644 --- a/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.html +++ b/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.html @@ -31,7 +31,7 @@ - + diff --git a/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.ts b/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.ts index 30a913629..73d538b9f 100644 --- a/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.ts +++ b/src/app/loans/loans-view/loan-account-actions/write-off-page/write-off-page.component.ts @@ -70,7 +70,7 @@ export class WriteOffPageComponent implements OnInit { writeOffForm.locale = 'en'; writeOffForm.dateFormat = dateFormat; this.loanService.submitLoanActionButton(loanId, writeOffForm, 'writeoff').subscribe((response: any) => { - this.router.navigate(['../general'], {relativeTo: this.route}); + this.router.navigate(['../../../general'], {relativeTo: this.route}); }); } diff --git a/src/app/loans/loans-view/loan-accounts-button-config.ts b/src/app/loans/loans-view/loan-accounts-button-config.ts new file mode 100644 index 000000000..2c8e49fe0 --- /dev/null +++ b/src/app/loans/loans-view/loan-accounts-button-config.ts @@ -0,0 +1,223 @@ +/** Recurring Deposits Account Buttons Configuration */ +export class LoansAccountButtonConfiguration { + + optionArray: { + name: 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; + } + + setButtons(status: string) { + switch (status) { + case 'Active': + this.buttonsArray = [ + { + name: 'Add Loan Charge', + icon: 'fa fa-plus', + taskPermissionName: 'CREATE_LOANCHARGE', + }, + { + name: 'Foreclosure', + icon: 'icon-dollar', + taskPermissionName: 'FORECLOSURE_LOAN', + }, + { + name: 'Make Repayment', + icon: 'fa fa-dollar', + taskPermissionName: 'REPAYMENT_LOAN', + }, + { + name: 'Undo Disbursal', + icon: 'fa fa-undo', + taskPermissionName: 'DISBURSALUNDO_LOAN', + }, + ]; + break; + case 'Submitted and pending approval': + this.buttonsArray = [ + { + name: 'Add Loan Charge', + icon: 'fa fa-plus', + taskPermissionName: 'CREATE_LOANCHARGE', + }, + { + name: 'Approve', + icon: 'fa fa-check', + taskPermissionName: 'APPROVE_LOAN', + }, + { + name: 'Modify Application', + icon: 'fa fa-pincel-square-o', + taskPermissionName: 'UPDATE_LOAN', + }, + { + name: 'Reject', + icon: 'fa fa-times', + taskPermissionName: 'REJECT_LOAN', + }, + ]; + break; + case 'Approved': + this.buttonsArray = [ + { + name: 'Disburse', + icon: 'fa fa-flag', + taskPermissionName: 'DISBURSE_LOAN', + }, + { + name: 'Disburse to Savings', + icon: 'fa fa-flag', + taskPermissionName: 'DISBURSETOSAVINGS_LOAN', + }, + { + name: 'Undo Approval', + icon: 'fa fa-undo', + taskPermissionName: 'APPROVALUNDO_LOAN', + }, + ]; + break; + case 'Overpaid': + this.buttonsArray = [ + { + name: 'Transfer Funds', + icon: 'fa fa-exchange', + taskPermissionName: 'CREATE_ACCOUNTTRANSFER', + }, + ]; + break; + case 'Closed (written off)': + this.buttonsArray = [ + { + name: 'Recovery Payment', + icon: 'fa fa-briefcase', + taskPermissionName: 'RECOVERYPAYMENT_LOAN', + }, + ]; + 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', + }, + ]; + 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', + }, + ]; + 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', + }, + ]; + break; + default: + this.optionArray = []; + } + } + + addOption(option: { name: string, icon?: string, taskPermissionName?: string }) { + this.optionArray.push(option); + } + + addButton(option: { name: string, icon: string, taskPermissionName?: string }) { + this.buttonsArray.push(option); + } + +} diff --git a/src/app/loans/loans-view/loans-view.component.html b/src/app/loans/loans-view/loans-view.component.html index 4897eae77..19f43f9f1 100644 --- a/src/app/loans/loans-view/loans-view.component.html +++ b/src/app/loans/loans-view/loans-view.component.html @@ -3,6 +3,14 @@ + +
+
+ +
+
+
@@ -32,15 +40,15 @@ - + - + - + diff --git a/src/app/loans/loans-view/loans-view.component.scss b/src/app/loans/loans-view/loans-view.component.scss index 4a99956cf..7fee1927b 100644 --- a/src/app/loans/loans-view/loans-view.component.scss +++ b/src/app/loans/loans-view/loans-view.component.scss @@ -14,6 +14,13 @@ } } } + .profile-image-container { + margin: 1%; + .profile-image { + object-fit: cover; + border-radius: 20px; + } + } .loan-actions { align-self: flex-end; margin: 0 1%; diff --git a/src/app/loans/loans-view/loans-view.component.ts b/src/app/loans/loans-view/loans-view.component.ts index ae30c6cb2..a8d0117df 100644 --- a/src/app/loans/loans-view/loans-view.component.ts +++ b/src/app/loans/loans-view/loans-view.component.ts @@ -7,10 +7,10 @@ import { MatDialog } from '@angular/material'; import { LoansService } from '../loans.service'; /** Custom Buttons Configuration */ -import { ButtonConfig } from './button-config'; +import { LoansAccountButtonConfiguration } from './loan-accounts-button-config'; /** Dialog Components */ -import { LoansConfirmationDialogBoxComponent } from '../custom-dialog/loans-confirmation-dialog-box/loans-confirmation-dialog-box.component'; +import { ConfirmationDialogComponent } from '../../shared/confirmation-dialog/confirmation-dialog.component'; import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; @Component({ @@ -20,23 +20,20 @@ import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.co }) export class LoansViewComponent implements OnInit { + /** Loan Details Data */ loanDetailsData: any; + /** Loan Datatables */ loanDatatables: any; + /** Recalculate Interest */ recalculateInterest: any; + /** Status */ status: string; - buttons: { - singlebuttons: { - name: string, - icon: string, - taskPermissionName: string, - }[], - options?: { - name: string, - taskPermissionName: string - }[] - }; + /** Loan Id */ loanId: number; + /** Client Id */ clientId: any; + /** Button Configuration */ + buttonConfig: LoansAccountButtonConfiguration; constructor(private route: ActivatedRoute, private router: Router, @@ -54,72 +51,69 @@ export class LoansViewComponent implements OnInit { this.recalculateInterest = this.loanDetailsData.recalculateInterest || true; this.status = this.loanDetailsData.status.value; + this.setConditionalButtons(); + } + + // Defines the buttons based on the status of the loan account + setConditionalButtons() { + this.buttonConfig = new LoansAccountButtonConfiguration(this.status); - // Defines the buttons based on the status of the loan account if (this.status === 'Submitted and pending approval') { - this.buttons = ButtonConfig['Submitted and pending approval']; - this.buttons.options.splice(1, 0, { - name: (this.loanDetailsData.loanOfficerName ? 'Change Loan Officer' : 'Assign Loan Officer' ), + this.buttonConfig.addOption({ + name: (this.loanDetailsData.loanOfficerName ? 'Change Loan Officer' : 'Assign Loan Officer'), taskPermissionName: 'DISBURSE_LOAN' }); if (this.loanDetailsData.isVariableInstallmentsAllowed) { - this.buttons.options.push({ - name: 'Edit Repayment Schedule', - taskPermissionName: 'ADJUST_REPAYMENT_SCHEDULE' - }) ; - } + this.buttonConfig.addOption({ + name: 'Edit Repayment Schedule', + taskPermissionName: 'ADJUST_REPAYMENT_SCHEDULE' + }); + } } else if (this.status === 'Approved') { - this.buttons = ButtonConfig['Approved']; - this.buttons.singlebuttons.splice(1, 0, { - name: (this.loanDetailsData.loanOfficerName ? 'Change Loan Officer' : 'Assign Loan Officer' ), + this.buttonConfig.addButton({ + name: (this.loanDetailsData.loanOfficerName ? 'Change Loan Officer' : 'Assign Loan Officer'), icon: 'fa fa-user', taskPermissionName: 'DISBURSE_LOAN' }); } else if (this.status === 'Active') { - this.buttons = ButtonConfig['Active']; if (this.loanDetailsData.canDisburse) { - this.buttons.singlebuttons.splice(1, 0, { - name: 'Disburse', - icon: 'fa fa-flag', - taskPermissionName: 'DISBURSE_LOAN' + this.buttonConfig.addButton({ + name: 'Disburse', + icon: 'fa fa-flag', + taskPermissionName: 'DISBURSE_LOAN' }); - this.buttons.singlebuttons.splice(1, 0, { - name: 'Disburse To Savings', - icon: 'fa fa-flag', - taskPermissionName: 'DISBURSETOSAVINGS_LOAN' + this.buttonConfig.addButton({ + name: 'Disburse To Savings', + icon: 'fa fa-flag', + taskPermissionName: 'DISBURSETOSAVINGS_LOAN' }); } // loan officer not assigned to loan, below logic // helps to display otherwise not if (!this.loanDetailsData.loanOfficerName) { - this.buttons.singlebuttons.splice(1, 0, { - name: 'Assign Loan Officer', - icon: 'fa fa-user', - taskPermissionName: 'UPDATELOANOFFICER_LOAN' + this.buttonConfig.addButton({ + name: 'Assign Loan Officer', + icon: 'fa fa-user', + taskPermissionName: 'UPDATELOANOFFICER_LOAN' }); } if (this.recalculateInterest) { - this.buttons.singlebuttons.splice(1, 0, { - name: 'Prepay Loan', - icon: 'fa fa-money', - taskPermissionName: 'REPAYMENT_LOAN' - }); + this.buttonConfig.addButton({ + name: 'Prepay Loan', + icon: 'fa fa-money', + taskPermissionName: 'REPAYMENT_LOAN' + }); } - } else if (this.status === 'Overpaid') { - this.buttons = ButtonConfig['Overpaid']; - } else if (this.status === 'Closed (written off)') { - this.buttons = ButtonConfig['ClosedWrittenOff']; } - } loanAction(button: string) { @@ -146,8 +140,8 @@ export class LoansViewComponent implements OnInit { * Recover from guarantor action */ private recoverFromGuarantor() { - const recoverFromGuarantorDialogRef = this.dialog.open(LoansConfirmationDialogBoxComponent, { - data: { heading: 'Recover from Guarantor', dialogContext: 'Are you sure you want recover from Guarantor ?' } + const recoverFromGuarantorDialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { heading: 'Recover from Guarantor', dialogContext: 'Are you sure you want recover from Guarantor ?', type: 'Mild' } }); recoverFromGuarantorDialogRef.afterClosed().subscribe((response: any) => { if (response.confirm) { @@ -158,6 +152,9 @@ export class LoansViewComponent implements OnInit { }); } + /** + * Delete loan Account + */ private deleteLoanAccount() { const deleteGuarantorDialogRef = this.dialog.open(DeleteDialogComponent, { data: { deleteContext: `with loan id: ${this.loanId}` } diff --git a/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts b/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts index 26bb4f217..66f3f3ef4 100644 --- a/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts +++ b/src/app/loans/loans-view/overdue-charges-tab/overdue-charges-tab.component.ts @@ -33,7 +33,7 @@ export class OverdueChargesTabComponent implements OnInit { * @param {ActivatedRoute} route Activated Route. */ constructor(private route: ActivatedRoute) { - this.route.data.subscribe(( data: { loanDetailsData: any }) => { + this.route.parent.data.subscribe(( data: { loanDetailsData: any }) => { this.loanDetails = data.loanDetailsData; }); } diff --git a/src/app/loans/loans.module.ts b/src/app/loans/loans.module.ts index 95e2ea480..0dc4fd5e9 100644 --- a/src/app/loans/loans.module.ts +++ b/src/app/loans/loans.module.ts @@ -9,7 +9,7 @@ import { SharedModule } from 'app/shared/shared.module'; import { PipesModule } from '../pipes/pipes.module'; /** Custom Components */ -import { AddLoanChargeComponent } from './add-loan-charge/add-loan-charge.component'; +import { AddLoanChargeComponent } from './loans-view/loan-account-actions/add-loan-charge/add-loan-charge.component'; import { LoansViewComponent } from './loans-view/loans-view.component'; import { GeneralTabComponent } from './loans-view/general-tab/general-tab.component'; import { AccountDetailsComponent } from './loans-view/account-details/account-details.component'; diff --git a/src/app/loans/loans.service.ts b/src/app/loans/loans.service.ts index fef7ed108..3c04f51bb 100644 --- a/src/app/loans/loans.service.ts +++ b/src/app/loans/loans.service.ts @@ -358,4 +358,10 @@ export class LoansService { return this.http.get(`/loans/${loanId}/template`, { params: httpParams }); } + guarantorAccountResource(loanId: string, clientId: any): Observable { + const httpParams = new HttpParams() + .set('clientId', clientId); + return this.http.get(`/loans/${loanId}/guarantors/accounts/template`, { params: httpParams }); + } + } diff --git a/src/app/shared/confirmation-dialog/confirmation-dialog.component.html b/src/app/shared/confirmation-dialog/confirmation-dialog.component.html index 0e0295502..3e5d716ba 100644 --- a/src/app/shared/confirmation-dialog/confirmation-dialog.component.html +++ b/src/app/shared/confirmation-dialog/confirmation-dialog.component.html @@ -4,5 +4,5 @@
- + diff --git a/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts b/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts index 3f9be5997..34ed626c8 100644 --- a/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts +++ b/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts @@ -12,6 +12,7 @@ import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; }) export class ConfirmationDialogComponent implements OnInit { + color: string; /** * @param {MatDialogRef} dialogRef Component reference to dialog. * @param {any} data Provides a deleteContext. @@ -20,6 +21,24 @@ export class ConfirmationDialogComponent implements OnInit { @Inject(MAT_DIALOG_DATA) public data: any) { } ngOnInit() { + this.setColor(); } + setColor() { + switch (this.data.type) { + case 'Basic': + this.color = 'primary'; + break; + case 'Mild': + this.color = 'accent'; + break; + case 'Strong': + this.color = 'warn'; + break; + default: + this.color = 'warn'; + } + } + + } diff --git a/src/assets/images/loans.png b/src/assets/images/loans.png new file mode 100644 index 0000000000000000000000000000000000000000..08c1add56bc2c7b9ceb7c43386225d0f4989cd6c GIT binary patch literal 16169 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