| import { LoansAllComponent } from './loans-all/loans-all.component'; | import { LoansAllComponent } from './loans-all/loans-all.component'; | ||||
| import {LenderNameService} from './service/lender-name.service'; | import {LenderNameService} from './service/lender-name.service'; | ||||
| import { LenderAaaIncomeComponent } from './pay-in/lender-aaa-income/lender-aaa-income.component'; | import { LenderAaaIncomeComponent } from './pay-in/lender-aaa-income/lender-aaa-income.component'; | ||||
| import { LenderConnectiveIncomeComponent } from './pay-in/lender-connective-income/lender-connective-income.component'; | |||||
| UploadingProgressCardComponent, | UploadingProgressCardComponent, | ||||
| LoanSelectComponent, | LoanSelectComponent, | ||||
| LoansAllComponent, | LoansAllComponent, | ||||
| LenderAaaIncomeComponent | |||||
| LenderAaaIncomeComponent, | |||||
| LenderConnectiveIncomeComponent, | |||||
| ], | ], | ||||
| imports: [ | imports: [ | ||||
| BrowserModule, | BrowserModule, |
| import {PayInModel} from './pay-in.model'; | |||||
| export class PayInConnectiveModel { | |||||
| private AgencyName = 'Connective'; | |||||
| public LoanAccount: string; | |||||
| public Name: string; | |||||
| public Settled: Date; | |||||
| public Lender: string; | |||||
| public LoanAmount: number; | |||||
| public Balance: number; | |||||
| public Associate: string; | |||||
| public Comm: number; | |||||
| public Type: string; | |||||
| public Percent: number; | |||||
| public Paid: number; | |||||
| public GST: number; | |||||
| public Total: number; | |||||
| public Period: Date; | |||||
| public matchedPayIn?: PayInModel | -1; | |||||
| constructor(payload: Partial<PayInConnectiveModel>){ | |||||
| this.Period = new Date(payload.Period); | |||||
| this.LoanAccount = payload.LoanAccount || ''; | |||||
| this.Name = payload.Name || ''; | |||||
| this.Settled = new Date(payload.Settled); | |||||
| this.Lender = payload.Lender || ''; | |||||
| if ( this.Lender.indexOf(this.AgencyName) === -1 ){ | |||||
| this.Lender += '_' + this.AgencyName; | |||||
| } | |||||
| this.LoanAmount = payload.LoanAmount || 0; | |||||
| this.Balance = payload.Balance || 0; | |||||
| this.Associate = payload.Associate || ''; | |||||
| this.Comm = payload.Comm || 0; | |||||
| this.Type = payload.Type || ''; | |||||
| this.Percent = payload.Percent || 0; | |||||
| this.Paid = payload.Paid || 0; | |||||
| this.GST = payload.GST || 0; | |||||
| this.Total = payload.Total || 0; | |||||
| this.matchedPayIn = payload.matchedPayIn || -1; | |||||
| } | |||||
| public asPayIn(): PayInModel { | |||||
| if ( this.matchedPayIn !== undefined && this.matchedPayIn !== -1 ) { | |||||
| return this.matchedPayIn; | |||||
| } | |||||
| const pi = new PayInModel({}); | |||||
| pi.Lender = this.Lender; | |||||
| pi.LoanNumber = this.LoanAccount; | |||||
| pi.Amount = this.LoanAmount; | |||||
| pi.Settlement = this.Settled; | |||||
| pi.IncomeAmount = this.Comm; | |||||
| pi.IncomeType = this.Type; | |||||
| pi.Balance = this.Balance; | |||||
| pi.OffsetBalance = -1; | |||||
| pi.Ts = this.Period; | |||||
| return pi; | |||||
| } | |||||
| public isMatch(pi: PayInModel): boolean { | |||||
| return this.LoanAccount === pi.LoanNumber && this.LoanAccount !== '' && | |||||
| this.Lender === pi.Lender && this.Lender !== '' && | |||||
| this.Comm === pi.IncomeAmount && | |||||
| this.Balance === pi.Balance && | |||||
| this.Type === pi.IncomeType; | |||||
| } | |||||
| } |
| import {UploadMetaModel} from './uploadMetaModel'; | import {UploadMetaModel} from './uploadMetaModel'; | ||||
| import {PayInModel} from './pay-in.model'; | import {PayInModel} from './pay-in.model'; | ||||
| import {PayInAAARowModel} from './Pay.In.AAA.Row.model'; | import {PayInAAARowModel} from './Pay.In.AAA.Row.model'; | ||||
| import {PayInConnectiveModel} from './pay-in-connective.model'; | |||||
| public PayIn: PayInModel[]; | public PayIn: PayInModel[]; | ||||
| public AAA?: PayInAAARowModel[]; | public AAA?: PayInAAARowModel[]; | ||||
| public Connective?: PayInConnectiveModel[]; | |||||
| public IsDuplicate: boolean; | public IsDuplicate: boolean; | ||||
| public Uid?: string; // client side unique id when upload | public Uid?: string; // client side unique id when upload | ||||
| payload.AAA.forEach( v => { this.AAA.push(new PayInAAARowModel(v)); }); | payload.AAA.forEach( v => { this.AAA.push(new PayInAAARowModel(v)); }); | ||||
| } | } | ||||
| this.Connective = []; | |||||
| if ( payload.Connective ) { | |||||
| payload.Connective.forEach( v => { this.Connective.push(new PayInConnectiveModel(v)); }); | |||||
| } | |||||
| this.IsDuplicate = payload.IsDuplicate || false; | this.IsDuplicate = payload.IsDuplicate || false; | ||||
| this.Uid = payload.Uid || '' ; | this.Uid = payload.Uid || '' ; | ||||
| this.Input = new UploadMetaModel(payload.Input || {}); | this.Input = new UploadMetaModel(payload.Input || {}); |
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> | |||||
| <kendo-grid [data]="data" (cellClick)="onCellClick($event)"> | <kendo-grid [data]="data" (cellClick)="onCellClick($event)"> | ||||
| <ng-template kendoGridToolbarTemplate> | <ng-template kendoGridToolbarTemplate> | ||||
| AAA | AAA |
| <kendo-grid [data]="gridView" (cellClick)="onCellClick($event)" | |||||
| [groupable]="true" | |||||
| [group]="groups" | |||||
| > | |||||
| <ng-template kendoGridToolbarTemplate> | |||||
| Connective | |||||
| </ng-template> | |||||
| <kendo-grid-column field="Period" format='{0:yyyy MMMM}' width="200"> </kendo-grid-column> | |||||
| <kendo-grid-column field="LoanAccount" width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="Name" width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="Settled" format='{0:MM/dd/yyyy}' width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="Lender" width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="LoanAmount" format='{0:c}' width="150" > </kendo-grid-column> | |||||
| <kendo-grid-column field="Balance" format='{0:c}' width="150" > </kendo-grid-column> | |||||
| <kendo-grid-column field="Associate" width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="Comm" format='{0:c}'> </kendo-grid-column> | |||||
| <kendo-grid-column field="Type" width="50"> </kendo-grid-column> | |||||
| <kendo-grid-column field="Percent" format='{0:p}' width="80"> </kendo-grid-column> | |||||
| <kendo-grid-column field="Paid" format='{0:c}' width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="GST" format='{0:c}' width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="Total" format='{0:c}' width="150"> </kendo-grid-column> | |||||
| <kendo-grid-column field="matchedPayIn" title="Matched" format='{0:c}'> | |||||
| <ng-template kendoGridCellTemplate let-dataItem> | |||||
| <kendo-icon *ngIf="dataItem.matchedPayIn === -1" [name]="'close-circle'" [size]="'small'" [themeColor]="'warning'"></kendo-icon> | |||||
| <kendo-icon *ngIf="dataItem.matchedPayIn !== -1" [name]="'tick'" [size]="'small'" [themeColor]="'success'"></kendo-icon> | |||||
| {{ dataItem.matchedPayIn === -1? 'Not matched': dataItem.matchedPayIn.Id}} | |||||
| </ng-template> | |||||
| </kendo-grid-column> | |||||
| </kendo-grid> |
| kendo-grid{ | |||||
| height: 100%; | |||||
| } |
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||||
| import { LenderConnectiveIncomeComponent } from './lender-connective-income.component'; | |||||
| describe('LenderConnectiveIncomeComponent', () => { | |||||
| let component: LenderConnectiveIncomeComponent; | |||||
| let fixture: ComponentFixture<LenderConnectiveIncomeComponent>; | |||||
| beforeEach(async () => { | |||||
| await TestBed.configureTestingModule({ | |||||
| declarations: [ LenderConnectiveIncomeComponent ] | |||||
| }) | |||||
| .compileComponents(); | |||||
| }); | |||||
| beforeEach(() => { | |||||
| fixture = TestBed.createComponent(LenderConnectiveIncomeComponent); | |||||
| component = fixture.componentInstance; | |||||
| fixture.detectChanges(); | |||||
| }); | |||||
| it('should create', () => { | |||||
| expect(component).toBeTruthy(); | |||||
| }); | |||||
| }); |
| import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; | |||||
| import {UploadAnalysisModel} from '../../models/upload.analysis.model'; | |||||
| import {PayInModel} from '../../models/pay-in.model'; | |||||
| import {CellCloseEvent} from '@progress/kendo-angular-grid'; | |||||
| import {PayInConnectiveModel} from '../../models/pay-in-connective.model'; | |||||
| import {DataResult, GroupDescriptor, process} from '@progress/kendo-data-query'; | |||||
| @Component({ | |||||
| selector: 'app-lender-connective-income', | |||||
| templateUrl: './lender-connective-income.component.html', | |||||
| styleUrls: ['./lender-connective-income.component.scss'] | |||||
| }) | |||||
| export class LenderConnectiveIncomeComponent implements OnInit { | |||||
| private Lender = 'Connective'; | |||||
| @Input() public analysis = new UploadAnalysisModel({}); | |||||
| @Input() newPayInUpdate: PayInModel; | |||||
| @Output() Selected: EventEmitter<PayInModel> = new EventEmitter<PayInModel>(); | |||||
| public data: PayInConnectiveModel[] = []; | |||||
| private payInCandidates: PayInModel[] = []; | |||||
| public groups: GroupDescriptor[] = [{ field: 'Lender' }]; | |||||
| public gridView: DataResult; | |||||
| constructor() { } | |||||
| ngOnInit(): void { | |||||
| this.analysis.Connective.forEach(v => { | |||||
| v.matchedPayIn = this.matchPayIn(v); | |||||
| this.data.push(new PayInConnectiveModel(v)); | |||||
| }); | |||||
| this.gridView = process(this.data, { group: this.groups }); | |||||
| } | |||||
| ngOnChanges(changes): void { // Todo: build super class for common features | |||||
| 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; | |||||
| } | |||||
| }); | |||||
| } | |||||
| } | |||||
| public onCellClick(event: CellCloseEvent): void{ | |||||
| this.Selected.emit(event.dataItem.asPayIn()); | |||||
| } | |||||
| private matchPayIn(v: PayInConnectiveModel): PayInModel | -1 { | |||||
| const idx = this.payInCandidates.findIndex( pi => this.isMatch(v, pi) ); | |||||
| if ( idx === -1 ) { return -1; } | |||||
| return this.payInCandidates[idx]; | |||||
| } | |||||
| private isMatch( v: PayInConnectiveModel, pi: PayInModel): boolean { | |||||
| if ( v === null || pi === null ){ | |||||
| return false; | |||||
| } | |||||
| return v.isMatch(pi); | |||||
| } | |||||
| @Input() set payIn(pis: PayInModel[]) { | |||||
| this.payInCandidates = []; | |||||
| pis.forEach( v => this.payInCandidates.push(new PayInModel(v))); | |||||
| this.data.forEach( v => { | |||||
| v.matchedPayIn = this.matchPayIn(v); | |||||
| }); | |||||
| } | |||||
| get PayIn(): PayInModel[] { | |||||
| return this.payInCandidates; | |||||
| } | |||||
| } |
| <kendo-combobox | <kendo-combobox | ||||
| [formControl]="formGroup.get('Lender')" | [formControl]="formGroup.get('Lender')" | ||||
| [data]="lenderListView | async" | [data]="lenderListView | async" | ||||
| [allowCustom]="true" | |||||
| [loading]="lenderNameService.loading"> | [loading]="lenderNameService.loading"> | ||||
| </kendo-combobox> | </kendo-combobox> | ||||
| </ng-template> | </ng-template> |
| [newPayInUpdate]="newPayInUpdateSubject | async" | [newPayInUpdate]="newPayInUpdateSubject | async" | ||||
| (Selected)="onSelected($event)"> | (Selected)="onSelected($event)"> | ||||
| </app-lender-aaa-income> | </app-lender-aaa-income> | ||||
| <app-lender-connective-income *ngIf="ua.Lender === 'Connective'" [analysis]="ua" | |||||
| [payIn]="payIn.gridData.data" | |||||
| [newPayInUpdate]="newPayInUpdateSubject | async" | |||||
| (Selected)="onSelected($event)"> | |||||
| </app-lender-connective-income> | |||||
| </div> | </div> | ||||
| kendo-grid{ | kendo-grid{ | ||||
| height: 100%; | height: 100%; | ||||
| } | } | ||||
| app-lender-connective-income, | |||||
| app-lender-aaa-income { | |||||
| height:100%; | |||||
| } | |||||
| } | } |