diff --git a/src/app/loans/common-resolvers/loans-account-transaction-template.resolver.ts b/src/app/loans/common-resolvers/loans-account-transaction-template.resolver.ts new file mode 100644 index 000000000..4892f099f --- /dev/null +++ b/src/app/loans/common-resolvers/loans-account-transaction-template.resolver.ts @@ -0,0 +1,33 @@ +/** 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 Account Transaction Template data resolver. + */ +@Injectable() +export class LoansAccountTransactionTemplateResolver implements Resolve { + + /** + * @param {LoansService} LoansService Loans service. + */ + constructor(private loansService: LoansService) { } + + /** + * Returns the Loans Account Transaction Template data. + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const loanAccountId = route.parent.parent.parent.paramMap.get('loanId'); + const transactionId = route.paramMap.get('id'); + return this.loansService.getLoansAccountTransactionTemplate(loanAccountId, transactionId); + } + +} diff --git a/src/app/loans/common-resolvers/loans-account-transaction.resolver.ts b/src/app/loans/common-resolvers/loans-account-transaction.resolver.ts new file mode 100644 index 000000000..08cf4f037 --- /dev/null +++ b/src/app/loans/common-resolvers/loans-account-transaction.resolver.ts @@ -0,0 +1,33 @@ +/** 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 Account Transaction data resolver. + */ +@Injectable() +export class LoansAccountTransactionResolver implements Resolve { + + /** + * @param {LoansService} LoansService Loans service. + */ + constructor(private loansService: LoansService) { } + + /** + * Returns the Loans Account Transaction data. + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const loanAccountId = route.parent.parent.parent.paramMap.get('loanId'); + const transactionId = route.paramMap.get('id'); + return this.loansService.getLoansAccountTransaction(loanAccountId, transactionId); + } + +} diff --git a/src/app/loans/common-resolvers/loans-transaction-reciept.resolver.ts b/src/app/loans/common-resolvers/loans-transaction-reciept.resolver.ts new file mode 100644 index 000000000..9f56f6915 --- /dev/null +++ b/src/app/loans/common-resolvers/loans-transaction-reciept.resolver.ts @@ -0,0 +1,36 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { ReportsService } from 'app/reports/reports.service'; + +/** + * Loans Transaction Reciept resolver. + */ +@Injectable() +export class LoansTransactionRecieptResolver implements Resolve { + + /** + * @param {ReportsService} reportsService Reports service. + */ + constructor(private reportsService: ReportsService) { } + + /** + * Returns the Loans Transaction Reciept + * @param {ActivatedRouteSnapshot} route Route Snapshot + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const transactionId = route.paramMap.get('id'); + const data = { + 'output-type': 'PDF', + R_transactionId: transactionId + }; + return this.reportsService.getPentahoRunReportData({name: 'Loan Transaction Receipt'}, data, 'default', 'en', 'dd MMMM yyyy'); + } + +} diff --git a/src/app/loans/loans-routing.module.ts b/src/app/loans/loans-routing.module.ts index 83f3eb1f6..d01b3ef3a 100644 --- a/src/app/loans/loans-routing.module.ts +++ b/src/app/loans/loans-routing.module.ts @@ -24,6 +24,11 @@ import { CreateLoansAccountComponent } from './create-loans-account/create-loans import { LoanDocumentsTabComponent } from './loans-view/loan-documents-tab/loan-documents-tab.component'; import { StandingInstructionsTabComponent } from 'app/loans/loans-view/standing-instructions-tab/standing-instructions-tab.component'; import { EditLoansAccountComponent } from './edit-loans-account/edit-loans-account.component'; +import { ViewChargeComponent } from './loans-view/view-charge/view-charge.component'; +import { ViewTransactionComponent } from './loans-view/transactions/view-transaction/view-transaction.component'; +import { EditTransactionComponent } from './loans-view/transactions/edit-transaction/edit-transaction.component'; +import { ViewRecieptComponent } from './loans-view/transactions/view-reciept/view-reciept.component'; +import { ExportTransactionsComponent } from './loans-view/transactions/export-transactions/export-transactions.component'; /** Custom Resolvers */ import { LoanDetailsResolver } from './common-resolvers/loan-details.resolver'; @@ -36,7 +41,9 @@ import { LoansAccountTemplateResolver } from './common-resolvers/loans-account-t import { LoanDocumentsResolver } from './common-resolvers/loan-documents.resolver'; import { LoansAccountAndTemplateResolver } from './common-resolvers/loans-account-and-template.resolver'; import { LoansAccountChargeResolver } from './common-resolvers/loans-account-charge.resolver'; -import { ViewChargeComponent } from './loans-view/view-charge/view-charge.component'; +import { LoansAccountTransactionResolver } from './common-resolvers/loans-account-transaction.resolver'; +import { LoansTransactionRecieptResolver } from './common-resolvers/loans-transaction-reciept.resolver'; +import { LoansAccountTransactionTemplateResolver } from './common-resolvers/loans-account-transaction-template.resolver'; /** Loans Route. */ const routes: Routes = [ @@ -93,11 +100,50 @@ const routes: Routes = [ }, { path: 'transactions', - component: TransactionsTabComponent, - data: { title: extract('Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false }, + data: { title: extract('Loans Account Transactions'), breadcrumb: 'Transactions', routeParamBreadcrumb: false }, resolve: { loanDetailsAssociationData: LoanDetailsChargesResolver - } + }, + children: [ + { + path: '', + component: TransactionsTabComponent + + }, + { + path: 'export', + component: ExportTransactionsComponent + }, + { + path: ':id', + data: { routeParamBreadcrumb: 'id' }, + children: [ + { + path: '', + component: ViewTransactionComponent, + resolve: { + loansAccountTransaction: LoansAccountTransactionResolver + } + }, + { + path: 'edit', + component: EditTransactionComponent, + data: { breadcrumb: 'Edit', routeParamBreadcrumb: false }, + resolve: { + loansAccountTransactionTemplate: LoansAccountTransactionTemplateResolver + } + }, + { + path: 'reciept', + component: ViewRecieptComponent, + data: { breadcrumb: 'Reciept', routeParamBreadcrumb: false }, + resolve: { + loansTransactionReciept: LoansTransactionRecieptResolver + } + } + ] + } + ] }, { path: 'loan-collateral', @@ -222,7 +268,10 @@ const routes: Routes = [ LoansAccountTemplateResolver, LoanDocumentsResolver, LoansAccountAndTemplateResolver, - LoansAccountChargeResolver + LoansAccountChargeResolver, + LoansAccountTransactionResolver, + LoansAccountTransactionTemplateResolver, + LoansTransactionRecieptResolver ] }) 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 a0d531b4e..2e02ab6b3 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 @@ -130,7 +130,6 @@ export class CreateGuarantorComponent implements OnInit, AfterViewInit { } clientSelected(clientDetails: any) { - console.log(clientDetails); this.accountOptions = []; this.loanService.guarantorAccountResource(this.loanId, clientDetails.id).subscribe((response: any) => { this.accountOptions = response.accountLinkingOptions; diff --git a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.html b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.html index 189a205d9..8d73b82c6 100644 --- a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.html +++ b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.html @@ -1,8 +1,8 @@
-
+
Hide Accruals -
- +
- + - + - + - + - + - + - + - + - + - + - - + @@ -101,7 +103,7 @@ - +
Date {{ ele.id }} {{ transaction.id }} Office {{ ele.officeName }} {{ transaction.officeName }} Transaction Date {{ ele.date | date }} {{ transaction.date | date }} Transaction Type {{ ele.type.value }} {{ transaction.type.value }} Amount {{ ele.amount | number }} {{ transaction.amount | number }} Breakdown {{ ele.principalPortion | number }} {{ transaction.principalPortion | number }} {{ ele.interestPortion | number }} {{ transaction.interestPortion | number }} {{ ele.feeChargesPortion | number }} {{ transaction.feeChargesPortion | number }} {{ ele.penaltyChargesPortion | number }} {{ transaction.penaltyChargesPortion | number }} Loan Balance {{ ele.outstandingLoanBalance | number }} {{ transaction.outstandingLoanBalance | number }} - - - - - - + Actions + +
diff --git a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.scss b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.scss index 747d2b7e1..dbb5ffba5 100644 --- a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.scss +++ b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.scss @@ -1,22 +1,28 @@ -table { - width: 100%; - margin: 3% 0%; -} - .container { padding-bottom: 2%; -} -.transaction-buttons { - margin-right: 5%; - padding-top: 5%; -} + .transaction-buttons { + padding-bottom: 1rem; + padding-top: 1rem; + .accruals { + padding-top: 1%; + } + } -.strike { - text-decoration: line-through; - color: red; -} - -.accruals { - padding-top: 1%; + table { + width: 100%; + .account-action-button{ + min-width: 26px; + padding: 0 0 3px 0; + margin: 0 10%; + line-height: 25px; + } + .select-row:hover { + cursor: pointer; + } + .strike { + text-decoration: line-through; + color: red; + } + } } diff --git a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts index 1ff495a86..e0dc480fc 100644 --- a/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts +++ b/src/app/loans/loans-view/transactions-tab/transactions-tab.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import {FormControl} from '@angular/forms'; @Component({ @@ -11,20 +11,27 @@ export class TransactionsTabComponent implements OnInit { /** Loan Details Data */ transactions: any; - showTransactions: any; + /** Show Transactions Data */ + showTransactionsData: any; + /** Temporary Transaction Data */ tempTransaction: any; + /** Form control to handle accural parameter */ + hideAccrualsParam: FormControl; + /** Stores the status of the loan account */ + status: string; /** Columns to be displayed in original schedule table. */ displayedColumns: string[] = ['id', 'office', 'transactionDate', 'transactionType', 'amount', 'principal', 'interest', 'fee', 'penalties', 'loanBalance', 'actions']; - hideAccrualsParam: FormControl; /** * Retrieves the loans with associations data from `resolve`. * @param {ActivatedRoute} route Activated Route. */ - constructor(private route: ActivatedRoute) { - this.route.data.subscribe(( data: { loanDetailsAssociationData: any }) => { + constructor(private route: ActivatedRoute, + private router: Router) { + this.route.parent.data.subscribe(( data: { loanDetailsAssociationData: any }) => { this.transactions = data.loanDetailsAssociationData.transactions; this.tempTransaction = data.loanDetailsAssociationData.transactions; + this.status = data.loanDetailsAssociationData.status.value; }); } @@ -35,14 +42,25 @@ export class TransactionsTabComponent implements OnInit { this.tempTransaction = this.removeItem(this.tempTransaction, element); } }); - this.showTransactions = this.transactions; + this.showTransactionsData = this.transactions; + } + + /** + * Checks Status of the loan account + */ + checkStatus() { + if (this.status === 'Active' || this.status === 'Closed (obligations met)' || this.status === 'Overpaid' || + this.status === 'Closed (rescheduled)' || this.status === 'Closed (written off)') { + return true; + } + return false; } hideAccruals() { if (!this.hideAccrualsParam.value) { - this.showTransactions = this.tempTransaction; + this.showTransactionsData = this.tempTransaction; } else { - this.showTransactions = this.transactions; + this.showTransactionsData = this.transactions; } } @@ -50,4 +68,22 @@ export class TransactionsTabComponent implements OnInit { return arr.filter((f: any) => f !== item); } + /** + * Show Transactions Details + * @param transactionsData Transactions Data + */ + showTransactions(transactionsData: any) { + if (transactionsData.type.id === 2 || transactionsData.type.id === 4 || transactionsData.type.id === 1) { + this.router.navigate([transactionsData.id], { relativeTo: this.route }); + } + } + + /** + * Stops the propagation to view pages. + * @param $event Mouse Event + */ + routeEdit($event: MouseEvent) { + $event.stopPropagation(); + } + } diff --git a/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.html b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.html new file mode 100644 index 000000000..c02f4933d --- /dev/null +++ b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.html @@ -0,0 +1,80 @@ +
+ + + +
+ + + + + Transaction Date + + + + + Transaction Date is required + + + + + Transaction Amount + + + Transaction Amount is required + + + + + Payment Type + + + {{ paymentType.name }} + + + + +
+ Show Payment Details + +
+ + + Account Number + + + + + Cheque + + + + + Routing Code + + + + + Receipt Number + + + + + Bank + + + + + + + + +
+ +
+ +
+ +
diff --git a/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.scss b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.scss new file mode 100644 index 000000000..15176bd11 --- /dev/null +++ b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.scss @@ -0,0 +1,5 @@ +.container { + width: 37rem; + margin-top: 3%; + padding-bottom: 2%; +} diff --git a/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.spec.ts b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.spec.ts new file mode 100644 index 000000000..abea649f7 --- /dev/null +++ b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditTransactionComponent } from './edit-transaction.component'; + +describe('EditTransactionComponent', () => { + let component: EditTransactionComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EditTransactionComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EditTransactionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.ts b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.ts new file mode 100644 index 000000000..6b86ad72f --- /dev/null +++ b/src/app/loans/loans-view/transactions/edit-transaction/edit-transaction.component.ts @@ -0,0 +1,123 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms'; +import { Router, ActivatedRoute } from '@angular/router'; +import { DatePipe } from '@angular/common'; + +/** Custom Services */ +import { LoansService } from 'app/loans/loans.service'; + +/** + * Edit Transaction component. + */ +@Component({ + selector: 'mifosx-edit-transaction', + templateUrl: './edit-transaction.component.html', + styleUrls: ['./edit-transaction.component.scss'] +}) +export class EditTransactionComponent implements OnInit { + + /** Minimum Due Date allowed. */ + minDate = new Date(2000, 0, 1); + /** Maximum Due Date allowed. */ + maxDate = new Date(); + /** Loans account transaction form. */ + editTransactionForm: FormGroup; + /** loans account transaction payment options. */ + paymentTypeOptions: { + id: number, + name: string, + description: string, + isCashPayment: boolean, + position: number + }[]; + /** Flag to enable payment details fields. */ + addPaymentDetailsFlag: Boolean = false; + /** loan account's Id */ + loanAccountId: string; + /** Transaction Template */ + transactionTemplateData: any; + + /** + * Retrieves the Loan Account transaction template data from `resolve`. + * @param {FormBuilder} formBuilder Form Builder. + * @param {LoansService} loansService Loans Service. + * @param {ActivatedRoute} route Activated Route. + * @param {DatePipe} datePipe DatePipe. + * @param {Router} router Router for navigation. + */ + constructor(private formBuilder: FormBuilder, + private route: ActivatedRoute, + private router: Router, + private datePipe: DatePipe, + private loansService: LoansService) { + this.route.data.subscribe((data: { loansAccountTransactionTemplate: any }) => { + this.transactionTemplateData = data.loansAccountTransactionTemplate; + this.paymentTypeOptions = this.transactionTemplateData.paymentTypeOptions; + }); + this.loanAccountId = this.route.parent.parent.parent.snapshot.params['loanId']; + } + + /** + * Creates the Loan account transaction form when component loads. + */ + ngOnInit() { + this.createEditTransactionForm(); + this.editTransactionForm.patchValue({ + 'transactionDate': this.transactionTemplateData.date && new Date(this.transactionTemplateData.date), + 'transactionAmount': this.transactionTemplateData.amount, + 'paymentTypeId': this.transactionTemplateData.paymentTypeId + }); + } + + /** + * Method to create the Loan Account Transaction Form. + */ + createEditTransactionForm() { + this.editTransactionForm = this.formBuilder.group({ + 'transactionDate': ['', Validators.required], + 'transactionAmount': ['', Validators.required], + 'paymentTypeId': [''], + }); + } + + /** + * Method to add payment detail fields to the UI. + */ + addPaymentDetails() { + this.addPaymentDetailsFlag = !this.addPaymentDetailsFlag; + if (this.addPaymentDetailsFlag) { + this.editTransactionForm.addControl('accountNumber', new FormControl('')); + this.editTransactionForm.addControl('checkNumber', new FormControl('')); + this.editTransactionForm.addControl('routingCode', new FormControl('')); + this.editTransactionForm.addControl('receiptNumber', new FormControl('')); + this.editTransactionForm.addControl('bankNumber', new FormControl('')); + } else { + this.editTransactionForm.removeControl('accountNumber'); + this.editTransactionForm.removeControl('checkNumber'); + this.editTransactionForm.removeControl('routingCode'); + this.editTransactionForm.removeControl('receiptNumber'); + this.editTransactionForm.removeControl('bankNumber'); + } + } + + /** + * Method to submit the transaction details. + */ + submit() { + const prevTransactionDate: Date = this.editTransactionForm.value.transactionDate; + // TODO: Update once language and date settings are setup + const dateFormat = 'dd-MM-yyyy'; + this.editTransactionForm.patchValue({ + transactionDate: this.datePipe.transform(prevTransactionDate, dateFormat) + }); + const transactionData = this.editTransactionForm.value; + transactionData.locale = 'en'; + transactionData.dateFormat = dateFormat; + this.loansService.executeLoansAccountTransactionsCommand(this.loanAccountId, 'modify', transactionData, this.transactionTemplateData.id) + .subscribe((res: any) => { + this.router.navigate(['../'], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.html b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.html new file mode 100644 index 000000000..81124a89e --- /dev/null +++ b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.html @@ -0,0 +1,35 @@ +
+ +
+ + + From Date + + + + + From date is required + + + + + To Date + + + + + To date is required + + + +
+ +
+ + +
+ +
+ + diff --git a/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.scss b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.scss new file mode 100644 index 000000000..a9fa6acab --- /dev/null +++ b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.scss @@ -0,0 +1,5 @@ +.generate-button { + max-height: 2%; + padding: 1% 0 2% 6%; + align-self: center; +} diff --git a/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.spec.ts b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.spec.ts new file mode 100644 index 000000000..9965db862 --- /dev/null +++ b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ExportTransactionsComponent } from './export-transactions.component'; + +describe('ExportTransactionsComponent', () => { + let component: ExportTransactionsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ExportTransactionsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ExportTransactionsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts new file mode 100644 index 000000000..29fa935a9 --- /dev/null +++ b/src/app/loans/loans-view/transactions/export-transactions/export-transactions.component.ts @@ -0,0 +1,87 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; +import { FormBuilder, Validators } from '@angular/forms'; +import { DatePipe } from '@angular/common'; +import { ActivatedRoute } from '@angular/router'; + +/** Custom Services */ +import { ReportsService } from 'app/reports/reports.service'; + +/** + * Export Client Loans Transactions Component + */ +@Component({ + selector: 'mifosx-export-transactions', + templateUrl: './export-transactions.component.html', + styleUrls: ['./export-transactions.component.scss'] +}) +export class ExportTransactionsComponent implements OnInit { + + /** Minimum date allowed. */ + minDate = new Date(2000, 0, 1); + /** Maximum date allowed. */ + maxDate = new Date(); + /** Transactions Report Form */ + transactionsReportForm: any; + /** substitute for resolver */ + hideOutput = true; + /** trusted resource url for pentaho output */ + pentahoUrl: any; + /** Loans Account Id */ + loansAccountId: any; + + /** + * Fetches loans account data from grandparent's `resolve` + * @param {DomSanitizer} sanitizer DOM Sanitizer + * @param {ReportsService} reportsService Reports Service + * @param {FormBuilder} formBuilder Form Builder + * @param {DatePipe} datePipe Date Pipe + * @param {ActivatedRoute} route Activated Route + */ + constructor(private sanitizer: DomSanitizer, + private reportsService: ReportsService, + private formBuilder: FormBuilder, + private datePipe: DatePipe, + private route: ActivatedRoute) { + this.route.parent.data.subscribe((data: { loanDetailsAssociationData: any }) => { + this.loansAccountId = data.loanDetailsAssociationData.accountNo; + }); + } + + + ngOnInit() { + this.createTransactionsReportForm(); + } + + /** + * Creates the transactions report form. + */ + createTransactionsReportForm() { + this.transactionsReportForm = this.formBuilder.group({ + 'fromDate': ['', Validators.required], + 'toDate': ['', Validators.required], + }); + } + + /** + * Generates client loans transactions report. + */ + generate() { + const data = { + 'output-type': 'PDF', + R_startDate: this.datePipe.transform(this.transactionsReportForm.value.fromDate, 'yyyy-MM-dd'), + R_endDate: this.datePipe.transform(this.transactionsReportForm.value.toDate, 'yyyy-MM-dd'), + R_selectLoan: this.loansAccountId + }; + this.reportsService.getPentahoRunReportData({ name: 'Client Loan Account Schedule'}, data, 'default', 'en', 'dd MMMM yyyy') + .subscribe( (res: any) => { + const contentType = res.headers.get('Content-Type'); + const file = new Blob([res.body], {type: contentType}); + const filecontent = URL.createObjectURL(file); + this.pentahoUrl = this.sanitizer.bypassSecurityTrustResourceUrl(filecontent); + this.hideOutput = false; + }); + } + +} diff --git a/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.html b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.html new file mode 100644 index 000000000..1a422f09a --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.html @@ -0,0 +1,10 @@ + + +
+ +
+ + + +
diff --git a/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.scss b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.scss new file mode 100644 index 000000000..b88a8cdbc --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.scss @@ -0,0 +1,7 @@ +.container { + max-width: 50rem; + .back-button { + max-height: 2%; + margin-bottom: 2%; + } +} diff --git a/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.spec.ts b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.spec.ts new file mode 100644 index 000000000..a831d071f --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewRecieptComponent } from './view-reciept.component'; + +describe('ViewRecieptComponent', () => { + let component: ViewRecieptComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ViewRecieptComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewRecieptComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.ts b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.ts new file mode 100644 index 000000000..06c9944d0 --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-reciept/view-reciept.component.ts @@ -0,0 +1,40 @@ +/** Angular Imports */ +import { Component, OnInit } from '@angular/core'; +import { DomSanitizer } from '@angular/platform-browser'; +import { ActivatedRoute } from '@angular/router'; + +/** + * View Transaction Reciept Component + */ +@Component({ + selector: 'mifosx-view-reciept', + templateUrl: './view-reciept.component.html', + styleUrls: ['./view-reciept.component.scss'] +}) +export class ViewRecieptComponent implements OnInit { + + /** trusted resource url for pentaho output */ + pentahoUrl: any; + /** Transaction Reciept Data */ + transactionRecieptData: any; + + /** + * Fetches transaction reciept `resolve` + * @param {DomSanitizer} sanitizer DOM Sanitizer + * @param {ActivatedRoute} route Activated Route + */ + constructor(private sanitizer: DomSanitizer, + private route: ActivatedRoute) { + this.route.data.subscribe((data: { loansTransactionReciept: any }) => { + this.transactionRecieptData = data.loansTransactionReciept; + }); + } + + ngOnInit() { + const contentType = this.transactionRecieptData.headers.get('Content-Type'); + const file = new Blob([this.transactionRecieptData.body], {type: contentType}); + const filecontent = URL.createObjectURL(file); + this.pentahoUrl = this.sanitizer.bypassSecurityTrustResourceUrl(filecontent); + } + +} diff --git a/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.html b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.html new file mode 100644 index 000000000..133ccb249 --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.html @@ -0,0 +1,119 @@ +
+ + + + +
+ +
+ + + + + +
+ +
+ Transaction Id +
+ +
+ {{ transactionData.id }} +
+ +
+ Type +
+ +
+ {{ transactionData.type.value }} +
+ +
+ Transaction Date +
+ +
+ {{ transactionData.date | date }} +
+ +
+ Currency +
+ +
+ {{ transactionData.currency.name }} +
+ +
+ Amount +
+ +
+ {{ transactionData.amount }} +
+ + + +
+ Payment Type +
+ +
+ {{ transactionData.paymentDetailData.paymentType.name }} +
+ +
+ Account No. +
+ +
+ {{ transactionData.paymentDetailData.accountNumber }} +
+ +
+ Cheque Number +
+ +
+ {{ transactionData.paymentDetailData.checkNumber }} +
+ +
+ Routing Code +
+ +
+ {{ transactionData.paymentDetailData.routingCode }} +
+ +
+ Receipt No. +
+ +
+ {{ transactionData.paymentDetailData.receiptNumber }} +
+ +
+ Bank No. +
+ +
+ {{ transactionData.paymentDetailData.bankNumber }} +
+ +
+ +
+ +
+ +
+ +
diff --git a/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.scss b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.scss new file mode 100644 index 000000000..ace4543b6 --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.scss @@ -0,0 +1,14 @@ +.container { + max-width: 37rem; + padding-bottom: 2%; + .content { + div { + margin: 1rem 0; + word-wrap: break-word; + } + } +} + +.transaction-buttons { + margin-top: 3%; +} diff --git a/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.spec.ts b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.spec.ts new file mode 100644 index 000000000..bbff0d11b --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewTransactionComponent } from './view-transaction.component'; + +describe('ViewTransactionComponent', () => { + let component: ViewTransactionComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ViewTransactionComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewTransactionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.ts b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.ts new file mode 100644 index 000000000..1286f8c8f --- /dev/null +++ b/src/app/loans/loans-view/transactions/view-transaction/view-transaction.component.ts @@ -0,0 +1,70 @@ +/** Angular Imports */ +import { Component } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatDialog } from '@angular/material'; +import { DatePipe } from '@angular/common'; + +/** Custom Services */ +import { LoansService } from 'app/loans/loans.service'; +import { ConfirmationDialogComponent } from 'app/shared/confirmation-dialog/confirmation-dialog.component'; + +/** Custom Dialogs */ + +/** + * View Transaction Component. + * TODO: Add support for account transfers. + */ +@Component({ + selector: 'mifosx-view-transaction', + templateUrl: './view-transaction.component.html', + styleUrls: ['./view-transaction.component.scss'] +}) +export class ViewTransactionComponent { + + /** Transaction data. */ + transactionData: any; + + /** + * Retrieves the Transaction data from `resolve`. + * @param {LoansService} loansService Loans Service + * @param {ActivatedRoute} route Activated Route. + * @param {Router} router Router for navigation. + * @param {MatDialog} dialog Dialog reference. + * @param {DatePipe} datePipe DatePipe. + */ + constructor(private loansService: LoansService, + private route: ActivatedRoute, + private datePipe: DatePipe, + private router: Router, + public dialog: MatDialog) { + this.route.data.subscribe((data: { loansAccountTransaction: any }) => { + this.transactionData = data.loansAccountTransaction; + }); + } + + /** + * Undo the loans transaction + */ + undoTransaction() { + const accountId = this.route.parent.parent.parent.snapshot.params['loanId']; + const undoTransactionAccountDialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { heading: 'Undo Transaction', dialogContext: `Are you sure you want undo the transaction ${this.transactionData.id}` } + }); + undoTransactionAccountDialogRef.afterClosed().subscribe((response: { confirm: any }) => { + if (response.confirm) { + const locale = 'en'; + const dateFormat = 'dd MMMM yyyy'; + const data = { + transactionDate: this.datePipe.transform(this.transactionData.date && new Date(this.transactionData.date), dateFormat), + transactionAmount: 0, + dateFormat, + locale + }; + this.loansService.executeLoansAccountTransactionsCommand(accountId, 'undo', data, this.transactionData.id).subscribe(() => { + this.router.navigate(['../'], { relativeTo: this.route }); + }); + } + }); + } + +} diff --git a/src/app/loans/loans.module.ts b/src/app/loans/loans.module.ts index f865eb03d..401a618cf 100644 --- a/src/app/loans/loans.module.ts +++ b/src/app/loans/loans.module.ts @@ -56,6 +56,10 @@ import { StandingInstructionsTabComponent } from './loans-view/standing-instruct import { EditLoansAccountComponent } from './edit-loans-account/edit-loans-account.component'; import { LoanScreenReportsComponent } from './loans-view/loan-account-actions/loan-screen-reports/loan-screen-reports.component'; import { ApproveLoanComponent } from './loans-view/loan-account-actions/approve-loan/approve-loan.component'; +import { ViewRecieptComponent } from './loans-view/transactions/view-reciept/view-reciept.component'; +import { ExportTransactionsComponent } from './loans-view/transactions/export-transactions/export-transactions.component'; +import { ViewTransactionComponent } from './loans-view/transactions/view-transaction/view-transaction.component'; +import { EditTransactionComponent } from './loans-view/transactions/edit-transaction/edit-transaction.component'; /** Dialog Components */ import { LoansAccountViewGuarantorDetailsDialogComponent } from './custom-dialog/loans-account-view-guarantor-details-dialog/loans-account-view-guarantor-details-dialog.component'; @@ -121,7 +125,11 @@ import { LoanAccountLoadDocumentsDialogComponent } from './custom-dialog/loan-ac EditLoansAccountComponent, LoanScreenReportsComponent, ApproveLoanComponent, - ViewChargeComponent + ViewChargeComponent, + ViewTransactionComponent, + EditTransactionComponent, + ViewRecieptComponent, + ExportTransactionsComponent ], entryComponents: [ LoansAccountAddCollateralDialogComponent, diff --git a/src/app/loans/loans.service.ts b/src/app/loans/loans.service.ts index 366a54905..7c4d55991 100644 --- a/src/app/loans/loans.service.ts +++ b/src/app/loans/loans.service.ts @@ -404,4 +404,38 @@ export class LoansService { return this.http.delete(`/loans/${accountId}/charges/${chargeId}`); } + /** + * @param {string} accountId Loans Account Id + * @param {string} transactionId Transaction Id + * @returns {Observable} + */ + getLoansAccountTransaction(accountId: string, transactionId: string): Observable { + return this.http.get(`/loans/${accountId}/transactions/${transactionId}`); + } + + /** + * @param {string} accountId Loans Account Id + * @param {string} transactionId Transaction Id + * @returns {Observable} + */ + getLoansAccountTransactionTemplate(accountId: string, transactionId: string): Observable { + const httpParams = new HttpParams().set('template', 'true'); + return this.http.get(`/loans/${accountId}/transactions/${transactionId}`, { params: httpParams }); + } + + /** + * @param {string} accountId Loans Account Id + * @param {string} command Command + * @param {any} data Data + * @param {string} transactionId Transaction Id + * @returns {Observable} + */ + executeLoansAccountTransactionsCommand(accountId: string, command: string, data: any, transactionId?: any): Observable { + const httpParams = new HttpParams().set('command', command); + if (transactionId) { + return this.http.post(`/loans/${accountId}/transactions/${transactionId}`, data, { params: httpParams }); + } + return this.http.post(`/loans/${accountId}/transactions`, data, { params: httpParams }); + } + }