Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/1977 - Fix contact transaction history #1985

Merged
merged 4 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ describe('TransactionGuarantorsComponent', () => {

it('should create', () => {
expect(component).toBeTruthy();
expect(component.getGetParams()['parent']).toBeUndefined();
expect(component.getParams()['parent']).toBeUndefined();
});

it('should load items with loan', () => {
component.loan = { id: '1' } as Transaction;
fixture.detectChanges();
expect(component).toBeTruthy();
expect(component.getGetParams()['parent']).toEqual('1');
expect(component.getParams()['parent']).toEqual('1');
});

it('should have delete', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ReportService } from 'app/shared/services/report.service';
import { TransactionSchC2Service } from 'app/shared/services/transaction-schC2.service';
import { Transaction } from 'app/shared/models/transaction.model';
import { TableLazyLoadEvent } from 'primeng/table';
import { QueryParams } from 'app/shared/services/api.service';

@Component({
selector: 'app-transaction-guarantors',
Expand Down Expand Up @@ -39,11 +40,11 @@ export class TransactionGuarantorsComponent extends TransactionListTableBaseComp
super(messageService, confirmationService, elementRef, activatedRoute, router, store, reportService);
}

override getGetParams(): { [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean> } {
override getParams(): QueryParams {
if (this.loan?.id) {
return { ...super.getGetParams(), parent: this.loan.id };
return { ...super.getParams(), parent: this.loan.id };
}
return super.getGetParams();
return super.getParams();
}
override loadTableItems(event: TableLazyLoadEvent): void {
if (!this.loan?.id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ScheduleCTransactionTypes } from 'app/shared/models/schc-transaction.mo
import { ScheduleC1TransactionTypes } from 'app/shared/models/schc1-transaction.model';
import { ScheduleDTransactionTypes } from 'app/shared/models/schd-transaction.model';
import { isPulledForwardLoan, ScheduleIds, Transaction } from 'app/shared/models/transaction.model';
import { QueryParams } from 'app/shared/services/api.service';
import { ReportService } from 'app/shared/services/report.service';
import { LabelList } from 'app/shared/utils/label.utils';
import { ReattRedesTypes, ReattRedesUtils } from 'app/shared/utils/reatt-redes/reatt-redes.utils';
Expand Down Expand Up @@ -211,8 +212,10 @@ export abstract class TransactionListTableBaseComponent extends TableListBaseCom
return {} as Transaction;
}

override getGetParams(): { [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean> } {
return { report_id: this.reportId, page_size: this.rowsPerPage };
override getParams(): QueryParams {
const params: QueryParams = { ...super.getParams(), page_size: this.rowsPerPage };
if (this.reportId) params['report_id'] = this.reportId;
return params;
}

override async editItem(item: Transaction): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ <h3>Office</h3>
itemName="transactions"
[emptyMessage]="emptyMessage"
(loadTableItems)="loadTransactions($event)"
(rowsPerPageChange)="onRowsPerPageChange($event)"
>
<ng-template #header> </ng-template>
<ng-template #body let-transaction>
Expand All @@ -308,8 +309,8 @@ <h3>Office</h3>
{{ transaction.transaction_type_identifier | label: scheduleTransactionTypeLabels }}
</a>
</td>
<td>{{ transaction.formType }}</td>
<td>{{ transaction.reportType }}</td>
<td>{{ transaction.form_type }}</td>
<td>{{ transaction.report_code_label }}</td>
<td>{{ transaction.date | date: 'MM/dd/yyyy' }}</td>
<td>{{ transaction.amount | currency }}</td>
</ng-template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import { of } from 'rxjs';
import { TableLazyLoadEvent } from 'primeng/table';
import { ListRestResponse } from 'app/shared/models/rest-api.model';
import { ActivatedRoute } from '@angular/router';
import { Form24 } from 'app/shared/models/form-24.model';
import { ReportTypes } from 'app/shared/models/report.model';

describe('ContactDialogComponent', () => {
let component: ContactDialogComponent;
Expand Down Expand Up @@ -135,18 +137,59 @@ describe('ContactDialogComponent', () => {
transaction.reports = [testActiveReport];
});

it('should route to transaction', () => {
it('should route to transaction', async () => {
const spy = spyOn(component.router, 'navigate');
component.openTransaction(new TransactionData(transaction));
await component.openTransaction(new TransactionData(transaction));
expect(spy).toHaveBeenCalledWith([`reports/transactions/report/999/list/${transaction.id}`]);
});

it('should handle pagination', () => {
it('should handle pagination', async () => {
spyOn(transactionService, 'getTableData').and.returnValue(
of({ results: [], count: 5, pageNumber: 0, next: '', previous: '' } as ListRestResponse),
);
component.loadTransactions({ first: 1, rows: 5 } as TableLazyLoadEvent);
await component.loadTransactions({ first: 1, rows: 5 } as TableLazyLoadEvent);

expect(component.transactions).toEqual([]);
});

it('should not show Form 24s', async () => {
transaction.reports?.push(Form24.fromJSON({ id: '1', report_type: ReportTypes.F24 }));
spyOn(transactionService, 'getTableData').and.returnValue(
of({ results: [transaction], count: 1, pageNumber: 1, next: '', previous: '' } as ListRestResponse),
);
await component.loadTransactions({ first: 1, rows: 5 } as TableLazyLoadEvent);

expect(component.transactions[0].report_code_label).toBe('APRIL 15 QUARTERLY REPORT (Q1)');
});

describe('loadTransactions', () => {
it('should load even without first in event or pagerState', async () => {
component.pagerState = undefined;
spyOn(transactionService, 'getTableData').and.returnValue(
of({ results: [], count: 5, pageNumber: 0, next: '', previous: '' } as ListRestResponse),
);
await component.loadTransactions({ rows: 5 } as TableLazyLoadEvent);

expect(component.transactions).toEqual([]);
});

it('should load even without first in event', async () => {
component.pagerState = { rows: 5 } as TableLazyLoadEvent;
spyOn(transactionService, 'getTableData').and.returnValue(
of({ results: [], count: 5, pageNumber: 0, next: '', previous: '' } as ListRestResponse),
);
await component.loadTransactions({ rows: 5 } as TableLazyLoadEvent);

expect(component.transactions).toEqual([]);
});
});

it('should get params', () => {
component.rowsPerPage = 5;
component.contact.id = '123';
const params = component.getParams();
expect(params['page_size']).toBe(5);
expect(params['contact']).toBe('123');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ import { ActivatedRoute, Router } from '@angular/router';
import { TransactionService } from '../../services/transaction.service';
import { TableLazyLoadEvent } from 'primeng/table';
import { getReportFromJSON } from '../../services/report.service';
import { ReportTypes } from 'app/shared/models/report.model';
import { QueryParams } from 'app/shared/services/api.service';

export class TransactionData {
id: string;
report_ids: string[];
formType = '';
reportType = '';
form_type = '';
report_code_label = '';
transaction_type_identifier: string;
date: string;
amount: string;
Expand All @@ -48,10 +50,11 @@ export class TransactionData {
this.amount = transaction.amount;
this.transaction_type_identifier = transaction.transaction_type_identifier;

transaction.reports.map((r: JSON) => {
transaction.reports.forEach((r: JSON) => {
const report = getReportFromJSON(r);
this.formType = report.formLabel;
this.reportType = report.reportLabel;
if (report.report_type === ReportTypes.F24) return; // We will display the Form 3X version of the transaction #1977
this.form_type = report.formLabel;
this.report_code_label = report.reportLabel;
});
}
}
Expand Down Expand Up @@ -111,12 +114,14 @@ export class ContactDialogComponent extends DestroyerComponent implements OnInit

sortableHeaders: { field: string; label: string }[] = [
{ field: 'transaction_type_identifier', label: 'Transaction type' },
{ field: 'formType', label: 'Form Type' },
{ field: 'reportType', label: 'Report Type' },
{ field: 'form_type', label: 'Form Type' },
{ field: 'report_code_label', label: 'Report Type' },
{ field: 'date', label: 'Date' },
{ field: 'amount', label: 'Amount' },
];

pagerState?: TableLazyLoadEvent;

constructor(
private fb: FormBuilder,
private contactService: ContactService,
Expand All @@ -131,11 +136,25 @@ export class ContactDialogComponent extends DestroyerComponent implements OnInit
async loadTransactions(event: TableLazyLoadEvent) {
this.tableLoading = true;

// event is undefined when triggered from the detail page because
// the detail doesn't know what page we are on. We check the local
// pagerState variable to retrieve the page state.
if (!!event && 'first' in event) {
this.pagerState = event;
} else {
event = this.pagerState
? this.pagerState
: {
first: 0,
rows: this.rowsPerPage,
};
}

// Calculate the record page number to retrieve from the API.
const first: number = event.first ?? 0;
const rows: number = event.rows ?? this.rowsPerPage;
const pageNumber: number = Math.floor(first / rows) + 1;
const params = { contact: this.contact.id! }; // eslint-disable-line @typescript-eslint/no-non-null-assertion
const params = this.getParams();

// Determine query sort ordering
let ordering: string | string[] = event.sortField ? event.sortField : '';
Expand All @@ -144,6 +163,7 @@ export class ContactDialogComponent extends DestroyerComponent implements OnInit
} else {
ordering = `${ordering}`;
}

try {
const transactionsPage = await lastValueFrom(this.transactionService.getTableData(pageNumber, ordering, params));
this.transactions = transactionsPage.results.map((t) => new TransactionData(t));
Expand Down Expand Up @@ -360,10 +380,15 @@ export class ContactDialogComponent extends DestroyerComponent implements OnInit
await this.router.navigate([`reports/transactions/report/${reportId}/list/${transaction.id}`]);
}

onRowsPerPageChange() {
onRowsPerPageChange(rowsPerPage: number) {
this.rowsPerPage = rowsPerPage;
this.loadTransactions({
first: 0,
rows: this.rowsPerPage,
});
}

getParams(): QueryParams {
return { page_size: this.rowsPerPage, contact: this.contact.id ?? '' };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { TableListService } from '../../interfaces/table-list-service.interface'
import { forkJoin, Observable } from 'rxjs';
import { DestroyerComponent } from '../app-destroyer.component';
import { TableLazyLoadEvent, TableSelectAllChangeEvent } from 'primeng/table';
import { QueryParams } from 'app/shared/services/api.service';

@Component({
template: '',
Expand Down Expand Up @@ -83,7 +84,7 @@ export abstract class TableListBaseComponent<T> extends DestroyerComponent imple
const first: number = event.first ? event.first : 0;
const rows: number = event.rows ? event.rows : 10;
const pageNumber: number = Math.floor(first / rows) + 1;
const params = this.getGetParams();
const params = this.getParams();

// Determine query sort ordering
let ordering: string | string[] = event.sortField ? event.sortField : '';
Expand Down Expand Up @@ -189,16 +190,16 @@ export abstract class TableListBaseComponent<T> extends DestroyerComponent imple
}

/**
* getGetParams() is a method that provides optional parameters that the table-list-base component
* getParams() is a method that provides optional parameters that the table-list-base component
* will pass in the GET request that loads the table's items, passing the parameters through the
* itemService and to the api service. A component extending this component can override this
* method in order to control the parameters being sent in the GET request without overriding the
* entire loadTableItems() method.
*
* @return { [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean> }
* @return QueryParams
*/

public getGetParams(): { [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean> } {
public getParams(): QueryParams {
return { page_size: this.rowsPerPage };
}

Expand Down
19 changes: 6 additions & 13 deletions front-end/src/app/shared/services/api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ export class ApiService {
});
}
return this.http.get<T>(`${environment.apiUrl}${endpoint}`, {
headers: headers,
params: params,
headers,
params,
withCredentials: true,
});
}
Expand Down Expand Up @@ -87,26 +87,19 @@ export class ApiService {
const params = this.getQueryParams(queryParams);
if (allowedErrorCodes) {
return this.http.post<T>(`${environment.apiUrl}${endpoint}`, payload, {
headers: headers,
params: params,
headers,
params,
withCredentials: true,
observe: 'response',
context: new HttpContext().set(ALLOW_ERROR_CODES, allowedErrorCodes),
});
}
return this.http.post<T>(`${environment.apiUrl}${endpoint}`, payload, {
headers: headers,
params: params,
headers,
params,
withCredentials: true,
});
}
/* eslint-enable @typescript-eslint/no-explicit-any */

public postAbsoluteUrl<T>(endpoint: string, payload: unknown, queryParams: QueryParams = {}): Observable<T> {
const headers = this.getHeaders();
const params = this.getQueryParams(queryParams);
return this.http.post<T>(`${endpoint}`, payload, { headers: headers, params: params, withCredentials: true });
}

public put<T>(endpoint: string, payload: unknown, queryParams: QueryParams = {}): Observable<T> {
const headers = this.getHeaders();
Expand Down
8 changes: 2 additions & 6 deletions front-end/src/app/shared/services/committee-member.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { CommitteeMember, CommitteeMemberRoles } from '../models/committee-member.model';
import { TableListService } from '../interfaces/table-list-service.interface';
import { ApiService } from './api.service';
import { ApiService, QueryParams } from './api.service';
import { ListRestResponse } from '../models/rest-api.model';
import { firstValueFrom, map, Observable } from 'rxjs';

Expand All @@ -11,11 +11,7 @@ import { firstValueFrom, map, Observable } from 'rxjs';
export class CommitteeMemberService implements TableListService<CommitteeMember> {
constructor(private apiService: ApiService) {}

public getTableData(
pageNumber = 1,
ordering = '',
params: { [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean> } = {},
): Observable<ListRestResponse> {
public getTableData(pageNumber = 1, ordering = '', params: QueryParams = {}): Observable<ListRestResponse> {
let parameter_string = `?page=${pageNumber}`;
if (ordering?.length > 0) {
parameter_string += `&ordering=${ordering}`;
Expand Down
14 changes: 3 additions & 11 deletions front-end/src/app/shared/services/contact.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
OrganizationLookupResponse,
} from '../models/contact.model';
import { ListRestResponse } from '../models/rest-api.model';
import { ApiService } from './api.service';
import { ApiService, QueryParams } from './api.service';

@Injectable({
providedIn: 'root',
Expand All @@ -45,11 +45,7 @@ export class ContactService implements TableListService<Contact> {
return schema;
}

public getTableData(
pageNumber = 1,
ordering = '',
params: { [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean> } = {},
): Observable<ListRestResponse> {
public getTableData(pageNumber = 1, ordering = '', params: QueryParams = {}): Observable<ListRestResponse> {
if (!ordering) {
ordering = 'name';
}
Expand Down Expand Up @@ -181,11 +177,7 @@ export class ContactService implements TableListService<Contact> {
export class DeletedContactService implements TableListService<Contact> {
constructor(private apiService: ApiService) {}

public getTableData(
pageNumber = 1,
ordering = '',
params: { [param: string]: string | number | boolean | ReadonlyArray<string | number | boolean> } = {},
): Observable<ListRestResponse> {
public getTableData(pageNumber = 1, ordering = '', params: QueryParams = {}): Observable<ListRestResponse> {
if (!ordering) {
ordering = 'name';
}
Expand Down
Loading