Skip to content

Commit

Permalink
feat: add methods to get reports - spender and approver (#2895)
Browse files Browse the repository at this point in the history
  • Loading branch information
bistaastha committed May 8, 2024
1 parent 77b48a0 commit 26058ec
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface PlatformStatsRequestParams {
state: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export interface ReportsQueryParams {
offset?: number;
limit?: number;
order?: string;
id?: string;
}
140 changes: 138 additions & 2 deletions src/app/core/services/platform/v1/approver/reports.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,35 @@ import { TestBed } from '@angular/core/testing';
import { ApproverReportsService } from './reports.service';
import { ApproverPlatformApiService } from '../../../approver-platform-api.service';
import { of } from 'rxjs';
import { PAGINATION_SIZE } from 'src/app/constants';
import {
allReportsPaginated1,
allReportsPaginated2,
expectedReportsPaginated,
expectedReportsSinglePage,
mockQueryParams,
platformReportCountData,
} from 'src/app/core/mock-data/platform-report.data';
import { ReportsQueryParams } from 'src/app/core/models/platform/v1/reports-query-params.model';
import { StatsResponse } from 'src/app/core/models/platform/v1/stats-response.model';

describe('ApproverReportsService', () => {
let approverReportsService: ApproverReportsService;
const approverPlatformApiService = jasmine.createSpyObj('ApproverPlatformApiService', ['post']);
let approverPlatformApiService: jasmine.SpyObj<ApproverPlatformApiService>;

beforeEach(() => {
const approverPlatformApiServiceSpy = jasmine.createSpyObj('ApproverPlatformApiService', ['post', 'get']);
TestBed.configureTestingModule({
providers: [
ApproverReportsService,
{ provide: ApproverPlatformApiService, useValue: approverPlatformApiService },
{ provide: PAGINATION_SIZE, useValue: 2 },
{ provide: ApproverPlatformApiService, useValue: approverPlatformApiServiceSpy },
],
});
approverReportsService = TestBed.inject(ApproverReportsService);
approverPlatformApiService = TestBed.inject(
ApproverPlatformApiService
) as jasmine.SpyObj<ApproverPlatformApiService>;
});

it('should be created', () => {
Expand All @@ -39,4 +55,124 @@ describe('ApproverReportsService', () => {
done();
});
});

it('getReportsCount(): should get a count of reports', (done) => {
// Mock the response of getReportsByParams
spyOn(approverReportsService, 'getReportsByParams').and.returnValue(of(platformReportCountData));

const expectedParams: ReportsQueryParams = {
...mockQueryParams,
limit: 1,
offset: 0,
};

approverReportsService.getReportsCount(mockQueryParams).subscribe((res) => {
// Verify
expect(res).toEqual(4); // Check if the count is as expected
expect(approverReportsService.getReportsByParams).toHaveBeenCalledWith(expectedParams); // Check if the method is called with the expected params
done(); // Call 'done' to indicate the end of the asynchronous test
});
});

it('getAllReportsByParams(): should get all reports multiple pages', (done) => {
const getReportsByParams = spyOn(approverReportsService, 'getReportsByParams');
spyOn(approverReportsService, 'getReportsCount').and.returnValue(of(4));

const expectedParams1: ReportsQueryParams = {
...mockQueryParams,
limit: 2,
offset: 0,
};
const expectedParams2: ReportsQueryParams = {
...mockQueryParams,
limit: 2,
offset: 2,
};

getReportsByParams.withArgs(expectedParams1).and.returnValue(of(allReportsPaginated1));
getReportsByParams.withArgs(expectedParams2).and.returnValue(of(allReportsPaginated2));

approverReportsService.getAllReportsByParams(mockQueryParams).subscribe((res) => {
expect(res).toEqual(expectedReportsPaginated);
expect(approverReportsService.getReportsCount).toHaveBeenCalledOnceWith({
state: 'in.(DRAFT,APPROVER_PENDING,APPROVER_INQUIRY)',
});
expect(getReportsByParams).toHaveBeenCalledWith(expectedParams1);
expect(getReportsByParams).toHaveBeenCalledWith(expectedParams2);
expect(getReportsByParams).toHaveBeenCalledTimes(2);
done();
});
});

it('getAllReportsByParams(): should get all reports single page', (done) => {
const getReportsByParams = spyOn(approverReportsService, 'getReportsByParams');
spyOn(approverReportsService, 'getReportsCount').and.returnValue(of(1));

const expectedParams: ReportsQueryParams = {
...mockQueryParams,
offset: 0,
limit: 2,
};

getReportsByParams.withArgs(expectedParams).and.returnValue(of(allReportsPaginated1));

approverReportsService.getAllReportsByParams(mockQueryParams).subscribe((res) => {
expect(res).toEqual(expectedReportsSinglePage);
expect(approverReportsService.getReportsCount).toHaveBeenCalledOnceWith(mockQueryParams);
expect(getReportsByParams).toHaveBeenCalledOnceWith(expectedParams);
done();
});
});

it('should get reports with specified parameters', (done) => {
const queryParams = {
state: 'DRAFT',
offset: 0,
limit: 2,
};
const expectedConfig = {
params: {
...queryParams,
},
};
approverPlatformApiService.get.and.returnValue(of(allReportsPaginated1));
approverReportsService.getReportsByParams(queryParams).subscribe((response) => {
expect(response).toEqual(allReportsPaginated1);
expect(approverPlatformApiService.get).toHaveBeenCalledOnceWith('/reports', expectedConfig);
done();
});
});

it('getReportById(): should get a report by id', () => {
spyOn(approverReportsService, 'getReportsByParams').and.returnValue(of(allReportsPaginated1));
const queryParams = {
id: 'eq.rpvcIMRMyM3A',
};
approverReportsService.getReportById('rpvcIMRMyM3A').subscribe((res) => {
expect(res).toEqual(allReportsPaginated1.data[0]);
expect(approverReportsService.getReportsByParams).toHaveBeenCalledOnceWith(queryParams);
});
});

it('getReportsStats(): should get advance request stats', (done) => {
const statsResponse: StatsResponse = {
count: 2,
total_amount: 1200,
};
approverPlatformApiService.post.and.returnValue(of({ data: statsResponse }));

const params = {
state: 'eq.DRAFT',
};

approverReportsService.getReportsStats(params).subscribe((res) => {
expect(res).toEqual(statsResponse);
expect(approverPlatformApiService.post).toHaveBeenCalledOnceWith('/reports/stats', {
data: {
query_params: `state=${params.state}`,
},
});
done();
});
});
});
67 changes: 64 additions & 3 deletions src/app/core/services/platform/v1/approver/reports.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,73 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Inject, Injectable } from '@angular/core';
import { Observable, concatMap, map, range, reduce, switchMap } from 'rxjs';
import { ApproverPlatformApiService } from '../../../approver-platform-api.service';
import { PlatformApiResponse } from 'src/app/core/models/platform/platform-api-response.model';
import { ReportsQueryParams } from 'src/app/core/models/platform/v1/reports-query-params.model';
import { PAGINATION_SIZE } from 'src/app/constants';
import { Report } from 'src/app/core/models/platform/v1/report.model';
import { PlatformStatsRequestParams } from 'src/app/core/models/platform/v1/platform-stats-request-param.model';
import { StatsResponse } from 'src/app/core/models/platform/v1/stats-response.model';

@Injectable({
providedIn: 'root',
})
export class ApproverReportsService {
constructor(private approverPlatformApiService: ApproverPlatformApiService) {}
constructor(
@Inject(PAGINATION_SIZE) private paginationSize: number,
private approverPlatformApiService: ApproverPlatformApiService
) {}

getAllReportsByParams(queryParams: ReportsQueryParams): Observable<Report[]> {
return this.getReportsCount(queryParams).pipe(
switchMap((count) => {
count = count > this.paginationSize ? count / this.paginationSize : 1;
return range(0, count);
}),
concatMap((page) => {
const params = {
...queryParams,
offset: this.paginationSize * page,
limit: this.paginationSize,
};
return this.getReportsByParams(params);
}),
reduce((acc, curr) => acc.concat(curr.data), [] as Report[])
);
}

getReportsCount(queryParams: ReportsQueryParams): Observable<number> {
const params = {
state: queryParams.state,
limit: 1,
offset: 0,
};
return this.getReportsByParams(params).pipe(map((res) => res.count));
}

getReportsByParams(queryParams: ReportsQueryParams = {}): Observable<PlatformApiResponse<Report[]>> {
const config = {
params: {
...queryParams,
},
};
return this.approverPlatformApiService.get<PlatformApiResponse<Report[]>>('/reports', config);
}

getReportsStats(params: PlatformStatsRequestParams): Observable<StatsResponse> {
const queryParams = {
data: {
query_params: `state=${params.state}`,
},
};
return this.approverPlatformApiService
.post<{ data: StatsResponse }>('/reports/stats', queryParams)
.pipe(map((res) => res.data));
}

getReportById(id: string): Observable<Report> {
const queryParams = { id: `eq.${id}` };
return this.getReportsByParams(queryParams).pipe(map((res: PlatformApiResponse<Report[]>) => res.data[0]));
}

ejectExpenses(rptId: string, expenseId: string, comment?: string[]): Observable<void> {
const payload = {
Expand Down
33 changes: 33 additions & 0 deletions src/app/core/services/platform/v1/spender/reports.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,39 @@ describe('SpenderReportsService', () => {
});
});

it('getReportById(): should get a report by id', () => {
spyOn(spenderReportsService, 'getReportsByParams').and.returnValue(of(allReportsPaginated1));
const queryParams = {
id: 'eq.rpvcIMRMyM3A',
};
spenderReportsService.getReportById('rpvcIMRMyM3A').subscribe((res) => {
expect(res).toEqual(allReportsPaginated1.data[0]);
expect(spenderReportsService.getReportsByParams).toHaveBeenCalledOnceWith(queryParams);
});
});

it('getReportsStats(): should get advance request stats', (done) => {
const statsResponse = {
count: 2,
total_amount: 1200,
};
spenderPlatformV1ApiService.post.and.returnValue(of({ data: statsResponse }));

const params = {
state: 'eq.DRAFT',
};

spenderReportsService.getReportsStats(params).subscribe((res) => {
expect(res).toEqual(statsResponse);
expect(spenderPlatformV1ApiService.post).toHaveBeenCalledOnceWith('/reports/stats', {
data: {
query_params: `state=${params.state}`,
},
});
done();
});
});

it('ejectExpenses(): should remove an expense from a report', (done) => {
spenderPlatformV1ApiService.post.and.returnValue(of(null));
spyOn(spenderReportsService, 'clearTransactionCache').and.returnValue(of(null));
Expand Down
21 changes: 20 additions & 1 deletion src/app/core/services/platform/v1/spender/reports.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { ReportsQueryParams } from 'src/app/core/models/platform/v1/reports-quer
import { PAGINATION_SIZE } from 'src/app/constants';
import { CreateDraftParams } from 'src/app/core/models/platform/v1/create-draft-params.model';
import { PlatformApiPayload } from 'src/app/core/models/platform/platform-api-payload.model';
import { StatsResponse } from 'src/app/core/models/platform/v1/stats-response.model';
import { PlatformStatsRequestParams } from 'src/app/core/models/platform/v1/platform-stats-request-param.model';
import { CacheBuster } from 'ts-cacheable';
import { UserEventService } from '../../../user-event.service';
import { TransactionService } from '../../../transaction.service';
Expand Down Expand Up @@ -79,10 +81,11 @@ export class SpenderReportsService {
}),
concatMap((page) => {
const params = {
state: queryParams.state,
...queryParams,
offset: this.paginationSize * page,
limit: this.paginationSize,
};

return this.getReportsByParams(params);
}),
reduce((acc, curr) => acc.concat(curr.data), [] as Report[])
Expand All @@ -107,9 +110,25 @@ export class SpenderReportsService {
return this.spenderPlatformV1ApiService.get<PlatformApiResponse<Report[]>>('/reports', config);
}

getReportById(id: string): Observable<Report> {
const queryParams = { id: `eq.${id}` };
return this.getReportsByParams(queryParams).pipe(map((res: PlatformApiResponse<Report[]>) => res.data[0]));
}

createDraft(data: CreateDraftParams): Observable<Report> {
return this.spenderPlatformV1ApiService
.post<PlatformApiPayload<Report>>('/reports', data)
.pipe(map((res) => res.data));
}

getReportsStats(params: PlatformStatsRequestParams): Observable<StatsResponse> {
const queryParams = {
data: {
query_params: `state=${params.state}`,
},
};
return this.spenderPlatformV1ApiService
.post<{ data: StatsResponse }>('/reports/stats', queryParams)
.pipe(map((res) => res.data));
}
}

0 comments on commit 26058ec

Please sign in to comment.