From 562b82658cdf02cbbdb0736a4d55a8a8e172dc5a Mon Sep 17 00:00:00 2001 From: Patrick Sun Date: Thu, 29 Apr 2021 18:10:10 +1000 Subject: [PATCH] upload lender automatically if there is already a match. --- src/app/app.component.scss | 53 +++++++++++++++++++ src/app/loan-select/loan-select.component.ts | 14 ++++- src/app/models/Pay.In.AAA.Row.model.ts | 18 +++++-- src/app/models/pay-in-list.filter.model.ts | 2 +- src/app/models/pay-in.model.ts | 14 +++++ src/app/observable/pay.in.observable.ts | 13 ----- .../lender-aaa-income.component.html | 6 ++- .../lender-aaa-income.component.ts | 17 +++--- src/app/pay-in/pay-in.component.html | 7 ++- src/app/pay-in/pay-in.component.scss | 14 +++++ src/app/pay-in/pay-in.component.ts | 52 +++++++++++++++--- 11 files changed, 172 insertions(+), 38 deletions(-) delete mode 100644 src/app/observable/pay.in.observable.ts diff --git a/src/app/app.component.scss b/src/app/app.component.scss index 0e67a0e..6e81a47 100644 --- a/src/app/app.component.scss +++ b/src/app/app.component.scss @@ -43,3 +43,56 @@ .upload-details div[role="tabpanel"]{ padding:0px; } + +@keyframes flash-background { + from {background-color: white;} + to {background-color: lightgoldenrodyellow;} +} +kendo-grid.filterByUploadMeta { + .k-grid-add-row.k-grid-edit-row.ng-star-inserted { + animation: flash-background 1s infinite; + opacity: 1; + } + + .k-state-selected { + animation: flash-background 1s 3; + opacity: 1; + } + + tr { + position: relative; + } + @keyframes flash{ + 50% { opacity: 0.5 } + } + + tr.dup { + td:first-child{ + position: relative; + div { + display:unset; + transition: display 1s; + z-index:1; + } + } + } + + tr.missingLoan { + td:last-child { + text-align: left; + &::before{ + color: #020202; + background: #ffe172; + width: 110px; + content: "missing loan"; + text-align: right; + position: absolute; + overflow:hidden; + right: 0; + border-radius: 10px 0 0 10px; + animation: flash 1s 3; + } + }; + } +} + diff --git a/src/app/loan-select/loan-select.component.ts b/src/app/loan-select/loan-select.component.ts index a7869c2..a1d0193 100644 --- a/src/app/loan-select/loan-select.component.ts +++ b/src/app/loan-select/loan-select.component.ts @@ -62,11 +62,21 @@ export class LoanSelectComponent implements OnInit, ControlValueAccessor { } onLoanSelected(loan: LoanModel): void { - if (loan !== undefined && this.Loan !== undefined && this.Loan.Id !== loan.Id){ + let changed = false; + if ( loan === null || loan === undefined) { + if (this.Loan.Id !== '') { + changed = true; + } + }else{ + changed = this.Loan.Id !== loan.Id; + } + + if (changed ){ this.valueChange.emit(loan); this.onChange(loan); - this.Loan = loan; } + + // update changes if (loan === undefined || loan == null ){ this.Loan = new LoanModel({}); }else{ diff --git a/src/app/models/Pay.In.AAA.Row.model.ts b/src/app/models/Pay.In.AAA.Row.model.ts index 87b57c4..663e419 100644 --- a/src/app/models/Pay.In.AAA.Row.model.ts +++ b/src/app/models/Pay.In.AAA.Row.model.ts @@ -6,7 +6,7 @@ export class PayInAAARowModel { public Period: Date; public LoanNumber: string; public Settlement: Date; - public LoanAmount: number; + public LoanFacility: number; public Balance: number; public InTrail: number; @@ -16,8 +16,8 @@ export class PayInAAARowModel { this.Period = new Date(payload.Period); this.LoanNumber = payload.LoanNumber || ''; this.Settlement = new Date(payload.Settlement); - this.LoanAmount = payload.LoanAmount || 0; - this.Balance = payload.Balance || 0; + this.LoanFacility = payload.LoanFacility || 0; + this.Balance = payload.Balance || -1; this.InTrail = payload.InTrail || 0; this.matchedPayIn = payload.matchedPayIn || -1; } @@ -29,12 +29,22 @@ export class PayInAAARowModel { const pi = new PayInModel({}); pi.Lender = this.Lender; pi.LoanNumber = this.LoanNumber; - pi.Amount = this.LoanAmount; + pi.Amount = this.LoanFacility; pi.Settlement = this.Settlement; pi.IncomeAmount = this.InTrail; pi.IncomeType = 'Trail'; + pi.Balance = this.Balance; + pi.OffsetBalance = -1; pi.Ts = this.Period; return pi; } + + public isMatch(pi: PayInModel): boolean { + return this.LoanNumber === pi.LoanNumber && this.LoanNumber !== '' && + this.Lender === pi.Lender && this.Lender !== '' && + this.InTrail === pi.IncomeAmount && + this.Balance === pi.Balance && + 'Trail' === pi.IncomeType; + } } diff --git a/src/app/models/pay-in-list.filter.model.ts b/src/app/models/pay-in-list.filter.model.ts index dd94afa..7a65f8b 100644 --- a/src/app/models/pay-in-list.filter.model.ts +++ b/src/app/models/pay-in-list.filter.model.ts @@ -28,7 +28,7 @@ export class PayInListFilterModel { } const bigNumber = 9999999999; - this.Take = payload.Take || 10; + this.Take = payload.Take || 0; this.Skip = payload.Skip || 0; this.TsFrom = payload.TsFrom? new Date(payload.TsFrom) : new Date('1900-01-01'); this.TsTo = payload.TsTo? new Date(payload.TsTo) : new Date('2038-01-01'); diff --git a/src/app/models/pay-in.model.ts b/src/app/models/pay-in.model.ts index f809568..c3dbe9a 100644 --- a/src/app/models/pay-in.model.ts +++ b/src/app/models/pay-in.model.ts @@ -41,6 +41,20 @@ export class PayInModel { this.UploadId = payload.UploadId; } + public isEqual(pi: PayInModel): boolean { + return pi !== undefined && pi !== null && + this.Amount === pi.Amount && + this.Balance === pi.Balance && + this.Lender === pi.Lender && + this.LoanId === pi.LoanId && + this.LoanNumber === pi.LoanNumber && + this.OffsetBalance === pi.OffsetBalance && + this.Settlement.getDate() === pi.Settlement.getDate() && + this.IncomeAmount === pi.IncomeAmount && + this.IncomeType === pi.IncomeType && + this.Ts.getDate() === pi.Ts.getDate() && + this.UploadId === pi.UploadId; + } } diff --git a/src/app/observable/pay.in.observable.ts b/src/app/observable/pay.in.observable.ts deleted file mode 100644 index 977bac8..0000000 --- a/src/app/observable/pay.in.observable.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {BehaviorSubject} from 'rxjs'; -import {PayInModel} from '../models/pay-in.model'; - - -export class PayInObservable extends BehaviorSubject { - constructor() { - super(null); - } - - Next(pis: PayInModel[]): void { - super.next(pis); - } -} diff --git a/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.html b/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.html index b1ffc25..c26acdf 100644 --- a/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.html +++ b/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.html @@ -6,12 +6,14 @@ - + - + + + {{ dataItem.matchedPayIn === -1? 'Not matched': dataItem.matchedPayIn.Id}} diff --git a/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.ts b/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.ts index e082497..97d417c 100644 --- a/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.ts +++ b/src/app/pay-in/lender-aaa-income/lender-aaa-income.component.ts @@ -24,15 +24,19 @@ export class LenderAaaIncomeComponent implements OnInit, OnChanges { this.analysis.AAA.forEach(v => { v.matchedPayIn = this.matchPayIn(v); this.data.push(new PayInAAARowModel(v)); - v.InTrail = 20; - this.data.push(new PayInAAARowModel(v)); }); - console.log(this); } ngOnChanges(changes): void { if (changes.newPayInUpdate){ + const piNew = changes.newPayInUpdate.currentValue as PayInModel; this.data.forEach(v => { + // remove old matches + if (v.matchedPayIn !== -1 && v.matchedPayIn.Id === piNew.Id){ + v.matchedPayIn = -1; + } + + // add new matches if ( this.isMatch(v, changes.newPayInUpdate.currentValue) ){ v.matchedPayIn = changes.newPayInUpdate.currentValue; } @@ -54,12 +58,10 @@ export class LenderAaaIncomeComponent implements OnInit, OnChanges { if ( v === null || pi === null ){ return false; } - return v.LoanNumber === pi.LoanNumber && - this.Lender === pi.Lender && - v.InTrail === pi.IncomeAmount && - 'Trail' === pi.IncomeType; + return v.isMatch(pi); } + @Input() set payIn(pis: PayInModel[]) { this.payInCandidates = []; pis.forEach( v => this.payInCandidates.push(new PayInModel(v))); @@ -68,7 +70,6 @@ export class LenderAaaIncomeComponent implements OnInit, OnChanges { v.matchedPayIn = this.matchPayIn(v); }); - console.log ('new payin comes in'); } get PayIn(): PayInModel[] { diff --git a/src/app/pay-in/pay-in.component.html b/src/app/pay-in/pay-in.component.html index 4082342..29b9083 100644 --- a/src/app/pay-in/pay-in.component.html +++ b/src/app/pay-in/pay-in.component.html @@ -13,6 +13,7 @@ kendoGridSelectBy [selectedKeys]="gridSelection" + [rowClass]="rowClassCallbackBind" (add)="addHandler($event)" (cancel)="cancelHandler($event)" @@ -22,6 +23,7 @@ (pageChange)="pageChange($event)" (sortChange)="sortChange($event)" + [ngClass]="{ 'filterByUploadMeta': uploadMeta.Id > 0 }" >
@@ -39,6 +41,7 @@ +
dup
@@ -55,9 +58,9 @@ - + diff --git a/src/app/pay-in/pay-in.component.scss b/src/app/pay-in/pay-in.component.scss index 26c77df..817601f 100644 --- a/src/app/pay-in/pay-in.component.scss +++ b/src/app/pay-in/pay-in.component.scss @@ -14,6 +14,20 @@ kendo-grid { margin-right: 10px; } } + + div.duplicate { + background: darkgrey; + position: absolute; + top: 0px; + transform: rotate( + -45deg + ); + display: none; + width: 50px; + left: -15px; + text-align: center; + color: white; + } } .balance { diff --git a/src/app/pay-in/pay-in.component.ts b/src/app/pay-in/pay-in.component.ts index 6172380..ece6753 100644 --- a/src/app/pay-in/pay-in.component.ts +++ b/src/app/pay-in/pay-in.component.ts @@ -6,7 +6,7 @@ import {PayInService} from '../service/pay-in.service'; import {PayInListResult} from '../models/pay-in-list-result.model'; import {Router} from '@angular/router'; import {PopupIncomeFilterComponent} from '../popup-income-filter/popup-income-filter.component'; -import {GridComponent, PageChangeEvent, SortSettings} from '@progress/kendo-angular-grid'; +import {GridComponent, PageChangeEvent, RowClassArgs, SortSettings} from '@progress/kendo-angular-grid'; import {SortDescriptor} from '@progress/kendo-data-query'; import {UploadMetaModel} from '../models/uploadMetaModel'; import {debounce} from 'ts-debounce'; @@ -47,6 +47,7 @@ export class PayInComponent implements OnInit { public showOffsetBalance = true; @Input() public pageable = true; + @Input() public pageSize = 15; public gridSelection: number[] = []; public sortable: SortSettings = { @@ -55,15 +56,21 @@ export class PayInComponent implements OnInit { public loading = false; public lenderListView: Observable; + public rowClassCallbackBind: any; private debouncedLoadFilteredData = () => {}; + constructor(private pis: PayInService, private lss: LoanSingleService, private router: Router, private lenderNameService: LenderNameService) { this.lenderListView = this.lenderNameService; this.lenderNameService.query(); + if ( this.pageable ) { + this.filter.Take = this.pageSize; + } + this.rowClassCallbackBind = this.rowClassCallback.bind(this); } ngOnInit(): void { @@ -100,7 +107,7 @@ export class PayInComponent implements OnInit { this.filter.UploadIds = [ value.Id.toString() ]; } this.debouncedLoadFilteredData(); - //console.log('upload filter changed', value, this.filter); + // console.log('upload filter changed', value, this.filter); } get uploadMeta(): UploadMetaModel { @@ -143,10 +150,13 @@ export class PayInComponent implements OnInit { this.showOffsetBalance = offsetBalance >= 0 ; this.incomeFormGroup = this.createFormGroup(new PayInModelEx({})); + + // console.log(this.incomeFormGroup); sender.addRow(this.incomeFormGroup); } + private createFormGroup(dataItem: PayInModelEx): FormGroup { const Loan = this.filterLoan.Id !== '' ? this.filterLoan : dataItem.Loan; const UploadMeta = this.filterUploadMeta.Id !== 0 ? this.filterUploadMeta : dataItem.UploadMeta ; @@ -178,7 +188,6 @@ export class PayInComponent implements OnInit { } public cancelHandler({ sender, rowIndex }): void { - // console.log(sender); this.closeEditor(sender, rowIndex); } @@ -195,6 +204,7 @@ export class PayInComponent implements OnInit { this.Loan.cuPayIn( model); this.updatePiInGrid(model); this.Updated.emit(model); + console.log(this); }, err => { // TODO: this.errorOccurred.emit('Error saving Income'); @@ -253,7 +263,9 @@ export class PayInComponent implements OnInit { } private closeEditor(grid, rowIndex = this.editedRowIndex): void{ - grid.closeRow(rowIndex); + if ( rowIndex !== undefined ){ + grid.closeRow(rowIndex); + } this.editedRowIndex = undefined; this.incomeFormGroup = undefined; } @@ -310,12 +322,15 @@ export class PayInComponent implements OnInit { } public onLoanChange(loan: LoanModel): void { - if ( loan.Id !== '' ) { + if ( loan !== undefined && loan.Id !== '' ) { this.incomeFormGroup.get('Lender').setValue(loan.Lender); this.incomeFormGroup.get('Lender').disable({onlySelf: true, emitEvent: false}); this.incomeFormGroup.get('LoanNumber').setValue(loan.LenderLoanNumber); this.incomeFormGroup.get('LoanNumber').disable({onlySelf: true, emitEvent: false}); + }else{ + this.incomeFormGroup.get('Lender').enable({onlySelf: true, emitEvent: false}); + this.incomeFormGroup.get('LoanNumber').enable({onlySelf: true, emitEvent: false}); } } @@ -326,6 +341,7 @@ export class PayInComponent implements OnInit { } public selectOrAddPayIn(pi: PayInModel): void{ + const row = this.gridData.data.findIndex( v => { return v.LoanNumber === pi.LoanNumber && v.Lender === pi.Lender && @@ -336,9 +352,33 @@ export class PayInComponent implements OnInit { if ( row >= 0 ) { // we found it this.ScrollTo(row); } else{ + this.gridSelection = []; // select none this.incomeFormGroup = this.createFormGroup(new PayInModelEx(pi)); - // this.closeEditor(this.grid); this.grid.addRow(this.incomeFormGroup); } } + + public rowClassCallback( context: RowClassArgs): any { + const pi = context.dataItem as PayInModel; + const rowIndex = context.index; + + const duplicate = this.checkDup(pi, rowIndex); + + return { + dup: duplicate, + missingLoan: pi.LoanId === '' + }; + } + private checkDup(pi: PayInModel, rowIndex: number): boolean { + let found = false; + if (this.uploadMeta.Id <= 0 ) { + return false; // dup check is only available for upload filtered situation. + } + this.gridData.data.forEach( (v, index) => { + if ( v.isEqual(pi) && index !== rowIndex ){ + found = true; + } + }); + return found; + } }