Skip to content

Commit

Permalink
feat(cb2-12694): Implement types-definition into scheduled-ops service (
Browse files Browse the repository at this point in the history
#78)

* feat(cb2-12694): used new imported definitions and removed old obsolete ones

* feat(cb2-12694): updated as per comments
  • Loading branch information
cb-cs authored Jul 25, 2024
1 parent 40b0d87 commit 4a665d5
Show file tree
Hide file tree
Showing 13 changed files with 403 additions and 124 deletions.
350 changes: 338 additions & 12 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"typescript": "4.4.4"
},
"dependencies": {
"@dvsa/cvs-type-definitions": "7.2.0",
"@aws-sdk/client-lambda": "^3.554.0",
"@aws-sdk/client-secrets-manager": "^3.554.0",
"@smithy/util-utf8": "^2.3.0",
Expand Down
57 changes: 0 additions & 57 deletions src/models/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,62 +10,6 @@ interface IActivityParams {
isOpen?: boolean;
}

interface IActivity {
id: string;
activityType: string;
testStationName?: string;
testStationPNumber?: string;
testStationEmail?: string;
testStationType?: string;
testerName: string;
testerEmail: string;
testerStaffId: string;
startTime: string;
endTime: string | null;
waitReason?: [string];
notes?: string;
}

export interface ITestResult {
testResultId: string;
systemNumber: string;
testerStaffId: string;
testStartTimestamp: string;
odometerReadingUnits: string;
testEndTimestamp: string;
testStatus: string;
testTypes: any[];
vehicleClass: IVehicleClass;
vin: string;
vehicleSize?: string; // Mandatory for PSV only & not applicable to HGV and TRL
testStationName: string;
vehicleId?: string; // Not sent from FE, calculated in the BE. When the test result is submitted, in BE, the VRM of the vehicle will be copied into vehicleId also.
vehicleType: string;
countryOfRegistration: string;
preparerId: string;
preparerName: string;
odometerReading: number;
vehicleConfiguration: string;
testStationType: string;
reasonForCancellation: string | null;
testerName: string;
vrm?: string; // Mandatory for PSV and HGV, not applicable to TRL
testStationPNumber: string;
numberOfSeats?: number; // mandatory for PSV only, not applicable for HGV and TRL
noOfAxles: number;
testerEmailAddress: string;
euVehicleCategory: string;
deletionFlag: boolean | null; // Not sent from FE, calculated in the BE.
regnDate?: Date; // Used only for PSV and HGV
trailerId?: string; // Mandatory for TRL, not applicable to PSV and HGV
firstUseDate?: Date; // Used only for TRL
}

export interface IVehicleClass {
code: string;
description: string;
}

interface IFunctionEvent {
name: string;
path: string;
Expand Down Expand Up @@ -126,7 +70,6 @@ export interface ISubSeg {

export {
IActivityParams,
IActivity,
IInvokeConfig,
IFunctionEvent,
INotifyConfig,
Expand Down
16 changes: 9 additions & 7 deletions src/services/ActivityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { InvocationRequest, InvokeCommandOutput } from '@aws-sdk/client-lambda';
import { toUint8Array } from '@smithy/util-utf8';
import { LambdaService } from './LambdaService';
import { Configuration } from '../utils/Configuration';
import { ACTIVITY_TYPE, ERRORS } from '../utils/Enums';
import { IActivity, IActivityParams, IInvokeConfig } from '../models';
import { ERRORS } from '../utils/Enums';
import { IActivityParams, IInvokeConfig } from '../models';
import { validateInvocationResponse } from '../utils/validateInvocationResponse';
import { ActivitySchema } from "@dvsa/cvs-type-definitions/types/v1/activity";
import { ActivityType } from "@dvsa/cvs-type-definitions/types/v1/enums/activityType.enum";
import HTTPError from '../models/HTTPError';

class ActivityService {
Expand All @@ -24,16 +26,16 @@ class ActivityService {
* @param testerStaffId Tester Staff Id
*/
public async getActivitiesList(
activityType: ACTIVITY_TYPE,
activityType: ActivityType,
visitStartTime: string,
testerStaffId?: string,
): Promise<IActivity[]> {
): Promise<ActivitySchema[]> {
const defaultStartTime: string = new Date(2020, 0, 1).toISOString();
const today: string = new Date().toISOString();
let params: IActivityParams;

// Get all open visits, from 2020-01-01
if (activityType === ACTIVITY_TYPE.VISIT) {
if (activityType === ActivityType.VISIT) {
params = {
fromStartTime: defaultStartTime,
toStartTime: today,
Expand All @@ -57,7 +59,7 @@ class ActivityService {
* Invoke the Activities service endpoint to get records based on the provided parameters
* @param params - getActivities query parameters
*/
public async getActivities(params: IActivityParams): Promise<IActivity[]> {
public async getActivities(params: IActivityParams): Promise<ActivitySchema[]> {
const config: IInvokeConfig = this.config.getInvokeConfig();
const invokeParams: InvocationRequest = {
FunctionName: config.functions.activities.name,
Expand All @@ -77,7 +79,7 @@ class ActivityService {
if (payload) {
console.log(`After validation - ${params.activityType}: `, payload);
} else {
params.activityType === ACTIVITY_TYPE.VISIT
params.activityType === ActivityType.VISIT
? console.log(`No ${params.activityType} activities returned`)
: console.log(`No ${params.activityType} activities returned for tester staff id - ${params.testerStaffId}`);
}
Expand Down
35 changes: 19 additions & 16 deletions src/services/CleanupService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ import { LambdaService } from './LambdaService';
import { ActivityService } from './ActivityService';
import { LambdaClient } from '@aws-sdk/client-lambda';
import { TestResultsService } from './TestResultsService';
import { IActivity, ILogVisit, ITestResult } from '../models';
import { ACTIVITY_TYPE, HTTPRESPONSE, LOG_ACTIONS, LOG_REASONS, LOG_STATUS, TIMES } from '../utils/Enums';
import { ILogVisit } from '../models';
import { HTTPRESPONSE, LOG_ACTIONS, LOG_REASONS, LOG_STATUS, TIMES } from '../utils/Enums';
import { NotificationService } from './NotificationService';
import HTTPResponse from '../models/HTTPResponse';
import { ActivitySchema } from "@dvsa/cvs-type-definitions/types/v1/activity";
import { TestResultSchema } from "@dvsa/cvs-type-definitions/types/v1/test";
import { ActivityType } from "@dvsa/cvs-type-definitions/types/v1/enums/activityType.enum";
import { subHours } from 'date-fns';
import HTTPResponse from '../models/HTTPResponse';
import moment from 'moment';

export class CleanupService {
Expand All @@ -30,10 +33,10 @@ export class CleanupService {

try {
// This goes to get all the open visits
const openVisits: IActivity[] = await this.activityService.getActivitiesList(ACTIVITY_TYPE.VISIT, '');
const actionVisits: IActivity[] = [];
let activities: IActivity[] = [];
let testResults: ITestResult[] = [];
const openVisits: ActivitySchema[] = await this.activityService.getActivitiesList(ActivityType.VISIT, '');
const actionVisits: ActivitySchema[] = [];
let activities: ActivitySchema[] = [];
let testResults: TestResultSchema[] = [];

// No open visits, log message, return and stop process
if (openVisits.length === 0) {
Expand All @@ -46,7 +49,7 @@ export class CleanupService {
if (moment(new Date(visit.startTime)).isAfter(recentActivityWindowTime)) {
// Visit open less than 3 hours, no action needed
this.addToLogVisits(
visit.id,
visit.id!,
visit.testerStaffId,
visit.startTime,
visit.startTime,
Expand All @@ -73,9 +76,9 @@ export class CleanupService {

// Get wait and unaccountable times for this visit
activities = [
...(await this.activityService.getActivitiesList(ACTIVITY_TYPE.WAIT, visit.startTime, visit.testerStaffId)),
...(await this.activityService.getActivitiesList(ActivityType.WAIT, visit.startTime, visit.testerStaffId)),
...(await this.activityService.getActivitiesList(
ACTIVITY_TYPE.UNACCOUNTABLE_TIME,
ActivityType.UNACCOUNTABLE_TIME,
visit.startTime,
visit.testerStaffId,
)),
Expand All @@ -98,9 +101,9 @@ export class CleanupService {
if (moment(new Date(lastActionTime)).isBefore(terminationWindowTime)) {
// last action time is more than 4 hours ago, close the visit
try {
await this.activityService.endVisit(visit.id, lastActionTime);
await this.activityService.endVisit(visit.id!, lastActionTime);
this.addToLogVisits(
visit.id,
visit.id!,
visit.testerStaffId,
visit.startTime,
lastActionTime,
Expand All @@ -110,7 +113,7 @@ export class CleanupService {
);
} catch (e) {
this.addToLogVisits(
visit.id,
visit.id!,
visit.testerStaffId,
visit.startTime,
lastActionTime,
Expand All @@ -125,7 +128,7 @@ export class CleanupService {
try {
await this.notificationService.sendVisitExpiryNotification(visit);
this.addToLogVisits(
visit.id,
visit.id!,
visit.testerStaffId,
visit.startTime,
lastActionTime,
Expand All @@ -135,7 +138,7 @@ export class CleanupService {
);
} catch (e) {
this.addToLogVisits(
visit.id,
visit.id!,
visit.testerStaffId,
visit.startTime,
lastActionTime,
Expand All @@ -148,7 +151,7 @@ export class CleanupService {
} else {
// last action time under 3 hours, no action required
this.addToLogVisits(
visit.id,
visit.id!,
visit.testerStaffId,
visit.startTime,
lastActionTime,
Expand Down
4 changes: 2 additions & 2 deletions src/services/NotificationService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @ts-ignore
import { NotifyClient } from 'notifications-node-client';
import { IActivity } from '../models';
import { Configuration } from '../utils/Configuration';
import { ActivitySchema } from "@dvsa/cvs-type-definitions/types/v1/activity";

/**
* Service class for Notifications
Expand All @@ -19,7 +19,7 @@ class NotificationService {
* Send email to the tester with the details of the visit
* @param visit
*/
async sendVisitExpiryNotification(visit: IActivity) {
async sendVisitExpiryNotification(visit: ActivitySchema) {
const templateId: string = await this.config.getTemplateIdFromEV();
return this.notifyClient.sendEmail(templateId, visit.testerEmail);
}
Expand Down
7 changes: 4 additions & 3 deletions src/services/TestResultsService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { IInvokeConfig, ITestResult } from '../models';
import { IInvokeConfig } from '../models';
import { ServiceException } from '@smithy/smithy-client';
import { InvocationRequest, InvokeCommandOutput } from '@aws-sdk/client-lambda';
import { toUint8Array } from '@smithy/util-utf8';
import { LambdaService } from './LambdaService';
import { Configuration } from '../utils/Configuration';
import { validateInvocationResponse } from '../utils/validateInvocationResponse';
import { TestResultSchema } from "@dvsa/cvs-type-definitions/types/v1/test";

class TestResultsService {
private readonly lambdaClient: LambdaService;
Expand All @@ -23,7 +24,7 @@ class TestResultsService {
public async getRecentTestResultsByTesterStaffId(
testerStaffId: string,
visitStartTime: string,
): Promise<ITestResult[]> {
): Promise<TestResultSchema[]> {
const params = {
testerStaffId,
fromDateTime: visitStartTime,
Expand All @@ -36,7 +37,7 @@ class TestResultsService {
* Invoke the Test Result service endpoint to get test results based on the provided parameters
* @param params - getTestResultsByTesterStaffId query parameters
*/
async getTestResults(params: any): Promise<ITestResult[]> {
async getTestResults(params: any): Promise<TestResultSchema[]> {
const config: IInvokeConfig = this.config.getInvokeConfig();
const invokeParams: InvocationRequest = {
FunctionName: config.functions.testResults.name,
Expand Down
6 changes: 0 additions & 6 deletions src/utils/Enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,3 @@ export enum LOG_ACTIONS {
NOTIFY = 'NOTIFY',
CLOSE = 'CLOSE',
}

export enum ACTIVITY_TYPE {
VISIT = 'visit',
WAIT = 'wait',
UNACCOUNTABLE_TIME = 'unaccountable time',
}
9 changes: 6 additions & 3 deletions tests/resources/testTestResults.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"noOfAxles": 5,
"testerEmailAddress": "test@test.com",
"euVehicleCategory": "m1",
"deletionFlag": null
"deletionFlag": null,
"numberOfWheelsDriven": 4
},
{
"testResultId": "abc124",
Expand Down Expand Up @@ -57,7 +58,8 @@
"noOfAxles": 5,
"testerEmailAddress": "test@test.com",
"euVehicleCategory": "m1",
"deletionFlag": null
"deletionFlag": null,
"numberOfWheelsDriven": 4
},
{
"testResultId": "abc125",
Expand Down Expand Up @@ -87,6 +89,7 @@
"noOfAxles": 5,
"testerEmailAddress": "test@test.com",
"euVehicleCategory": "m1",
"deletionFlag": null
"deletionFlag": null,
"numberOfWheelsDriven": 4
}
]
16 changes: 8 additions & 8 deletions tests/unit/CleanupService.unitTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import activities from '../resources/testActivities.json';
import testResults from '../resources/testTestResults.json';
import { TestResultsService } from '../../src/services/TestResultsService';
import { cloneDeep } from 'lodash';
import { IActivity } from '../../src/models';
import dateMock from '../util/dateMockUtils';
import { ERRORS, HTTPRESPONSE } from '../../src/utils/Enums';
import { subMinutes } from 'date-fns';
import { NotificationService } from '../../src/services/NotificationService';
import HTTPError from '../../src/models/HTTPError';
import {ActivitySchema} from "@dvsa/cvs-type-definitions/types/v1/activity";

jest.mock('../../src/services/ActivityService');

Expand All @@ -34,7 +34,7 @@ describe('Cleanup Service', () => {
describe('With a visit deserving of no action', () => {
it("returns 200 ok, with 'nothing to do' message", async () => {
expect.assertions(2);
const allActivities: IActivity[] = cloneDeep([activities[0]]);
const allActivities: ActivitySchema[] = cloneDeep([activities[0]] as ActivitySchema[]);
const freshActivities = allActivities.map((a) => {
a.startTime = new Date().toISOString();
a.endTime = null;
Expand All @@ -50,7 +50,7 @@ describe('Cleanup Service', () => {
it("returns 200 ok, with 'nothing to do' message after processing activities that required no action", async () => {
jest.resetAllMocks();
console.log = jest.fn();
const allActivities: IActivity[] = cloneDeep(activities);
const allActivities: ActivitySchema[] = cloneDeep(activities) as ActivitySchema[];
allActivities[0].startTime = new Date(subMinutes(new Date(), 240)).toISOString();
allActivities[3].endTime = null;
allActivities[4].endTime = new Date(subMinutes(new Date(), 30)).toISOString();
Expand Down Expand Up @@ -78,7 +78,7 @@ describe('Cleanup Service', () => {
sendVisitExpiryNotifications: sendNotifyMock,
};
});
const allActivities: IActivity[] = cloneDeep([activities[0]]);
const allActivities: ActivitySchema[] = cloneDeep([activities[0]] as ActivitySchema[]);
const staleActivities = allActivities.map((a) => {
a.endTime = null;
return a;
Expand All @@ -105,7 +105,7 @@ describe('Cleanup Service', () => {
sendVisitExpiryNotifications: sendNotifyMock,
};
});
const allActivities: IActivity[] = cloneDeep([activities[0]]);
const allActivities: ActivitySchema[] = cloneDeep([activities[0]] as ActivitySchema[]);
const staleActivities = allActivities.map((a) => {
a.endTime = null;
return a;
Expand All @@ -130,7 +130,7 @@ describe('Cleanup Service', () => {
sendVisitExpiryNotifications: sendNotifyMock,
};
});
const allActivities: IActivity[] = cloneDeep([activities[0]]);
const allActivities: ActivitySchema[] = cloneDeep([activities[0] as ActivitySchema]);
const staleActivities = allActivities.map((a) => {
a.endTime = null;
return a;
Expand All @@ -155,7 +155,7 @@ describe('Cleanup Service', () => {
it('correctly tries to send the notification', async () => {
jest.resetAllMocks();
console.log = jest.fn();
const allActivities: IActivity[] = cloneDeep(activities);
const allActivities: ActivitySchema[] = cloneDeep(activities) as ActivitySchema[];
allActivities[3].startTime = new Date(subMinutes(new Date(), 240)).toISOString();
allActivities[3].endTime = null;
allActivities[4].endTime = new Date(subMinutes(new Date(), 210)).toISOString();
Expand All @@ -182,7 +182,7 @@ describe('Cleanup Service', () => {
sendVisitExpiryNotifications: sendNotifyMock,
};
});
const allActivities: IActivity[] = cloneDeep(activities);
const allActivities: ActivitySchema[] = cloneDeep(activities) as ActivitySchema[];
allActivities[3].startTime = new Date(subMinutes(new Date(), 240)).toISOString();
allActivities[3].endTime = null;
allActivities[4].endTime = new Date(subMinutes(new Date(), 210)).toISOString();
Expand Down
Loading

0 comments on commit 4a665d5

Please sign in to comment.