feat: add loan button (assign/change loan officer) (#867)

Fixes: #248
This commit is contained in:
Muskan Khedia
2020-06-13 00:23:40 +05:30
committed by GitHub
parent 5729887a62
commit de701543e1
13 changed files with 218 additions and 11 deletions
@@ -0,0 +1,34 @@
/** 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';
/**
* Loans notes data resolver.
*/
@Injectable()
export class LoanActionButtonResolver implements Resolve<Object> {
/**
* @param {LoansService} LoansService Loans service.
*/
constructor(private loansService: LoansService) { }
/**
* Returns the Loans Notes Data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const loanId = route.parent.paramMap.get('loanId');
const loanActionButton = route.paramMap.get('action');
// if (loanActionButton === 'assign-loan-officer') {
return this.loansService.getLoanTemplate(loanId);
// }
}
}
+6 -1
View File
@@ -27,6 +27,7 @@ import { LoanDetailsChargesResolver } from './common-resolvers/loan-details-char
import { LoanAccountActionsComponent } from './loans-view/loan-account-actions/loan-account-actions.component';
import { LoanDatatablesResolver } from './common-resolvers/loan-datatables.resolver';
import { LoanDatatableResolver } from './common-resolvers/loan-datatable.resolver';
import { LoanActionButtonResolver } from './common-resolvers/loan-action-button-resolver';
const routes: Routes = [
{
@@ -129,6 +130,9 @@ const routes: Routes = [
path: ':action',
component: LoanAccountActionsComponent,
data: { title: extract('Loan Account Actions'), routeParamBreadcrumb: 'action' },
resolve: {
actionButtonData: LoanActionButtonResolver
}
},
]
}]
@@ -145,7 +149,8 @@ const routes: Routes = [
LoanNotesResolver,
LoanDetailsChargesResolver,
LoanDatatablesResolver,
LoanDatatableResolver
LoanDatatableResolver,
LoanActionButtonResolver
]
})
@@ -0,0 +1,42 @@
<div class="container">
<form [formGroup]="assignOfficerForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label> To Loan Officer</mat-label>
<mat-select required formControlName="toLoanOfficerId">
<mat-option *ngFor="let loanOfficer of loanOfficers" [value]="loanOfficer.id">
{{ loanOfficer.displayName }}
</mat-option>
</mat-select>
<mat-error *ngIf="assignOfficerForm.controls.toLoanOfficerId.hasError('required')">
Loan Officer is <strong>required</strong>
</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>Assignment Date</mat-label>
<input matInput [min]="minDate" [max]="maxDate" [matDatepicker]="assignOnDatePicker" required formControlName="assignmentDate">
<mat-datepicker-toggle matSuffix [for]="assignOnDatePicker"></mat-datepicker-toggle>
<mat-datepicker #assignOnDatePicker></mat-datepicker>
<mat-error *ngIf="assignOfficerForm.controls.assignmentDate.hasError('required')">
Assignment Date <strong>is required</strong>
</mat-error>
</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]="!assignOfficerForm.valid" *mifosxHasPermission="'BULKREASSIGN_LOAN'">Submit</button>
</mat-card-actions>
</mat-card-content>
</form>
</div>
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AssignLoanOfficerComponent } from './assign-loan-officer.component';
describe('AssignLoanOfficerComponent', () => {
let component: AssignLoanOfficerComponent;
let fixture: ComponentFixture<AssignLoanOfficerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AssignLoanOfficerComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AssignLoanOfficerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,75 @@
import { Component, OnInit, Input } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { DatePipe } from '@angular/common';
import { MatDialog } from '@angular/material';
import { LoansService } from 'app/loans/loans.service';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'mifosx-assign-loan-officer',
templateUrl: './assign-loan-officer.component.html',
styleUrls: ['./assign-loan-officer.component.scss']
})
export class AssignLoanOfficerComponent implements OnInit {
@Input() dataObject: any;
/** Loan Id */
loanId: string;
loanOfficers: any[];
/** Minimum Date allowed. */
minDate = new Date(2000, 0, 1);
/** Maximum Date allowed. */
maxDate = new Date();
/** Assign loan Officer form. */
assignOfficerForm: FormGroup;
/**
* @param {FormBuilder} formBuilder Form Builder.
* @param {LoansService} systemService Loan Service.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
*/
constructor(private formBuilder: FormBuilder,
private loanService: LoansService,
private route: ActivatedRoute,
private router: Router,
private datePipe: DatePipe) {
this.loanId = this.route.parent.snapshot.params['loanId'];
}
/**
* Creates the assign officer form.
*/
ngOnInit() {
this.createassignOfficerForm();
this.loanOfficers = this.dataObject.loanOfficerOptions;
}
/**
* Creates the create close form.
*/
createassignOfficerForm() {
this.assignOfficerForm = this.formBuilder.group({
'toLoanOfficerId': ['', Validators.required],
'assignmentDate': [new Date(), Validators.required]
});
}
submit() {
const assignmentDatee = this.assignOfficerForm.value.assignmentDate;
const dateFormat = 'yyyy-MM-dd';
this.assignOfficerForm.patchValue({
assignmentDate: this.datePipe.transform(assignmentDatee, dateFormat)
});
const assignForm = this.assignOfficerForm.value;
assignForm.locale = 'en';
assignForm.dateFormat = dateFormat;
assignForm.fromLoanOfficerId = this.dataObject.loanOfficerId || '';
this.loanService.loanActionButtons(this.loanId, assignForm, 'assignLoanOfficer')
.subscribe((response: any) => {
this.router.navigate([`../../${this.loanId}/general`], { relativeTo: this.route });
});
}
}
@@ -2,5 +2,6 @@
<mat-card>
<mifosx-loans-account-close *ngIf="actions.close"></mifosx-loans-account-close>
<mifosx-undo-approval *ngIf="actions.undo_approval"></mifosx-undo-approval>
<mifosx-assign-loan-officer *ngIf="actions.assign_loan_officer" [dataObject]="actionButtonData" ></mifosx-assign-loan-officer>
</mat-card>
</div>
@@ -13,7 +13,14 @@ import { ActivatedRoute, Router } from '@angular/router';
export class LoanAccountActionsComponent {
/** flag object to store possible actions and render appropriate UI to the user */
actions: { close: boolean, undo_approval: boolean } = { close: false, undo_approval: false };
actions: { close: boolean,
undo_approval: boolean,
assign_loan_officer: boolean } = {
close: false,
undo_approval: false,
assign_loan_officer: false };
actionButtonData: any;
actionName: any;
/**
* @param router Router.
@@ -21,11 +28,16 @@ export class LoanAccountActionsComponent {
*/
constructor(private router: Router,
private route: ActivatedRoute) {
this.route.data.subscribe(( data: { actionButtonData: any }) => {
this.actionButtonData = data.actionButtonData;
});
this.route.params.subscribe(params => {
if (params['action'].indexOf('-') > 0) {
this.actions[params['action'].replace('-', '_')] = true;
this.actionName = params['action'];
if (this.actionName === 'change-loan-officer') {
this.actionName = 'assign-loan-officer';
}
this.actions[params['action']] = true;
this.actions[this.actionName.replace(/-/g, '_')] = true;
});
}
@@ -37,7 +37,7 @@ export class UndoApprovalComponent implements OnInit {
*/
submit() {
const loanId = this.route.parent.snapshot.params['loanId'];
this.loanService.undoLoanApproval(loanId, {'note': this.note.value}).subscribe((response: any) => {
this.loanService.loanActionButtons(loanId, {'note': this.note.value}, 'undoapproval').subscribe((response: any) => {
this.router.navigate(['../general'], {relativeTo: this.route});
});
}
@@ -111,7 +111,7 @@ export class LoansViewComponent implements OnInit {
}
loanAction(button: string) {
button = button.replace(' ', '-').toLowerCase();
button = button.replace(/\s/g, '-').toLowerCase();
this.router.navigate([button], { relativeTo: this.route });
}
+2
View File
@@ -25,6 +25,7 @@ import { DatatableTabComponent } from './loans-view/datatable-tab/datatable-tab.
import { MultiRowComponent } from './loans-view/datatable-tab/multi-row/multi-row.component';
import { SingleRowComponent } from './loans-view/datatable-tab/single-row/single-row.component';
import { UndoApprovalComponent } from './loans-view/loan-account-actions/undo-approval/undo-approval.component';
import { AssignLoanOfficerComponent } from './loans-view/loan-account-actions/assign-loan-officer/assign-loan-officer.component';
/**
* Loans Module
@@ -50,6 +51,7 @@ import { UndoApprovalComponent } from './loans-view/loan-account-actions/undo-ap
MultiRowComponent,
SingleRowComponent,
UndoApprovalComponent,
AssignLoanOfficerComponent,
],
providers: [DatePipe],
})
+14 -3
View File
@@ -26,6 +26,18 @@ export class LoansService {
return this.http.get(`/loans/${loanId}/transactions/template`, { params: httpParams });
}
/**
* Returns the loan template data with specific condition
* @param loanId Loan Id
*/
getLoanTemplate(loanId: string): Observable<any> {
const httpParams = new HttpParams()
.set('fields', 'id,loanOfficerId,loanOfficerOptions')
.set('staffInSelectedOfficeOnly', 'true')
.set('template', 'true');
return this.http.get(`/loans/${loanId}`, { params: httpParams });
}
/**
* @param {any} loanCharge to apply on a Loan Account.
* @returns {Observable<any>}
@@ -146,13 +158,12 @@ export class LoansService {
}
/*
* Undo Loan Approval.
* @param {string} loanId Loan Id.
* @param {any} data Data.
* @returns {Observable<any>}
*/
undoLoanApproval(loanId: string, data: any): Observable<any> {
const httpParams = new HttpParams().set('command', 'undoapproval');
loanActionButtons(loanId: string, data: any, command: any): Observable<any> {
const httpParams = new HttpParams().set('command', command);
return this.http.post(`/loans/${loanId}`, data, {params: httpParams});
}
+1 -1
View File
@@ -10,7 +10,7 @@ export const environment = {
production: false,
version: env.npm_package_version + '-dev',
fineractPlatformTenantId: 'default', // For connecting to server running elsewhere update the tenant identifier
baseApiUrl: 'https://staging.mifos.io', // For connecting to server running elsewhere update the base API URL
baseApiUrl: 'https://dev.mifos.io', // For connecting to server running elsewhere update the base API URL
apiProvider: '/fineract-provider/api',
apiVersion: '/v1',
serverUrl: '',