Skip to content

Commit

Permalink
Merge pull request #28 from bcgov/feat/get-list-of-attachments
Browse files Browse the repository at this point in the history
GET list of attachments
  • Loading branch information
hannah-macdonald1 authored Nov 15, 2024
2 parents 9051617 + a25940d commit 8340318
Show file tree
Hide file tree
Showing 29 changed files with 1,355 additions and 9 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ CASE_ENDPOINT=/endpoint/path/here
INCIDENT_ENDPOINT=/endpoint/path/here
SR_ENDPOINT=/endpoint/path/here
MEMO_ENDPOINT=/endpoint/path/here
ATTACHMENTS_ENDPOINT=/endpoint/path/here
SKIP_AUTH_GUARD=false
5 changes: 5 additions & 0 deletions helm/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ spec:
secretKeyRef:
name: visitz-api
key: IN_PERSON_VISITS_ENDPOINT
- name: ATTACHMENTS_ENDPOINT
valueFrom:
secretKeyRef:
name: visitz-api
key: ATTACHMENTS_ENDPOINT
- name: VPI_APP_LABEL
value: {{ .Values.vpiAppBuildLabel.version }}
restartPolicy: Always
18 changes: 17 additions & 1 deletion src/common/constants/parameter-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,20 @@ const PAGINATION = 'N';
const idRegex = /[0-9\-A-Za-z]+/;
const idName = 'rowId';

export { VIEW_MODE, CHILD_LINKS, CONTENT_TYPE, PAGINATION, idRegex, idName };
const casesAttachmentsFieldName = 'No Intervention';
const incidentsAttachmentsFieldName = 'Incident No';
const srAttachmentsFieldName = 'Application No';
const memoAttachmentsFieldName = 'MemoNumber';

export {
VIEW_MODE,
CHILD_LINKS,
CONTENT_TYPE,
PAGINATION,
idRegex,
idName,
casesAttachmentsFieldName,
incidentsAttachmentsFieldName,
srAttachmentsFieldName,
memoAttachmentsFieldName,
};
2 changes: 2 additions & 0 deletions src/common/constants/upstream-constants.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
const baseUrlEnvVarName = 'UPSTREAM_BASE_URL';
const supportNetworkEndpointEnvVarName = 'SUPPORT_NETWORK_ENDPOINT';
const inPersonVisitsEndpointEnvVarName = 'IN_PERSON_VISITS_ENDPOINT';
const attachmentsEndpointEnvVarName = 'ATTACHMENTS_ENDPOINT';
const idirUsernameHeaderField = 'x-idir-username';

export {
baseUrlEnvVarName,
supportNetworkEndpointEnvVarName,
inPersonVisitsEndpointEnvVarName,
attachmentsEndpointEnvVarName,
idirUsernameHeaderField,
};
2 changes: 2 additions & 0 deletions src/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ export default () => ({
workspaces: {
supportNetwork: undefined,
inPersonVisits: undefined,
attachments: 'int_lab',
},
sinceFieldName: {
supportNetwork: 'Updated',
inPersonVisits: undefined,
attachments: undefined,
},
skipAuthGuard: process.env.SKIP_AUTH_GUARD === 'true',
buildInfo: {
Expand Down
33 changes: 33 additions & 0 deletions src/controllers/cases/cases.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ import {
InPersonVisitsSingleResponseCaseExample,
} from '../../entities/in-person-visits.entity';
import { idName } from '../../common/constants/parameter-constants';
import { AttachmentsService } from '../../helpers/attachments/attachments.service';
import {
AttachmentsSingleResponseCaseExample,
AttachmentsEntity,
} from '../../entities/attachments.entity';

describe('CasesController', () => {
let controller: CasesController;
Expand All @@ -33,6 +38,7 @@ describe('CasesController', () => {
CasesService,
AuthService,
SupportNetworkService,
AttachmentsService,
TokenRefresherService,
InPersonVisitsService,
RequestPreparerService,
Expand Down Expand Up @@ -106,4 +112,31 @@ describe('CasesController', () => {
},
);
});

describe('getSingleCaseAttachmentRecord tests', () => {
it.each([
[
AttachmentsSingleResponseCaseExample,
{ [idName]: 'test' } as IdPathParams,
{ since: '2020-02-02' } as SinceQueryParams,
],
])(
'should return single values given good input',
async (data, idPathParams, sinceQueryParams) => {
const caseServiceSpy = jest
.spyOn(casesService, 'getSingleCaseAttachmentRecord')
.mockReturnValueOnce(Promise.resolve(new AttachmentsEntity(data)));

const result = await controller.getSingleCaseAttachmentRecord(
idPathParams,
sinceQueryParams,
);
expect(caseServiceSpy).toHaveBeenCalledWith(
idPathParams,
sinceQueryParams,
);
expect(result).toEqual(new AttachmentsEntity(data));
},
);
});
});
56 changes: 56 additions & 0 deletions src/controllers/cases/cases.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ import {
InPersonVisitsSingleResponseCaseExample,
NestedInPersonVisitsEntity,
} from '../../entities/in-person-visits.entity';
import {
AttachmentsEntity,
AttachmentsListResponseCaseExample,
AttachmentsSingleResponseCaseExample,
NestedAttachmentsEntity,
} from '../../entities/attachments.entity';

@Controller('case')
@UseGuards(AuthGuard)
Expand Down Expand Up @@ -149,4 +155,54 @@ export class CasesController {
): Promise<InPersonVisitsEntity | NestedInPersonVisitsEntity> {
return await this.casesService.getSingleCaseInPersonVisitRecord(id, since);
}

@UseInterceptors(ClassSerializerInterceptor)
@Get(`:${idName}/attachments`)
@ApiOperation({
description:
'Find all Attachments metadata entries related to a given Case entity by Case id.',
})
@ApiQuery({ name: 'since', required: false })
@ApiExtraModels(AttachmentsEntity, NestedAttachmentsEntity)
@ApiOkResponse({
content: {
[CONTENT_TYPE]: {
schema: {
oneOf: [
{ $ref: getSchemaPath(AttachmentsEntity) },
{ $ref: getSchemaPath(NestedAttachmentsEntity) },
],
},
examples: {
AttachmentsSingleResponse: {
value: AttachmentsSingleResponseCaseExample,
},
AttachmentsListResponse: {
value: AttachmentsListResponseCaseExample,
},
},
},
},
})
async getSingleCaseAttachmentRecord(
@Param(
new ValidationPipe({
transform: true,
transformOptions: { enableImplicitConversion: true },
forbidNonWhitelisted: true,
}),
)
id: IdPathParams,
@Query(
new ValidationPipe({
transform: true,
transformOptions: { enableImplicitConversion: true },
forbidNonWhitelisted: true,
skipMissingProperties: true,
}),
)
since?: SinceQueryParams,
): Promise<AttachmentsEntity | NestedAttachmentsEntity> {
return await this.casesService.getSingleCaseAttachmentRecord(id, since);
}
}
43 changes: 42 additions & 1 deletion src/controllers/cases/cases.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,29 @@ import {
InPersonVisitsEntity,
InPersonVisitsSingleResponseCaseExample,
} from '../../entities/in-person-visits.entity';
import { idName } from '../../common/constants/parameter-constants';
import {
casesAttachmentsFieldName,
idName,
} from '../../common/constants/parameter-constants';
import { AttachmentsService } from '../../helpers/attachments/attachments.service';
import {
AttachmentsSingleResponseCaseExample,
AttachmentsEntity,
} from '../../entities/attachments.entity';

describe('CasesService', () => {
let service: CasesService;
let supportNetworkService: SupportNetworkService;
let inPersonVisitsService: InPersonVisitsService;
let attachmentsService: AttachmentsService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
imports: [HttpModule, ConfigModule.forRoot()],
providers: [
CasesService,
SupportNetworkService,
AttachmentsService,
UtilitiesService,
TokenRefresherService,
InPersonVisitsService,
Expand All @@ -53,6 +63,7 @@ describe('CasesService', () => {
inPersonVisitsService = module.get<InPersonVisitsService>(
InPersonVisitsService,
);
attachmentsService = module.get<AttachmentsService>(AttachmentsService);
});

it('should be defined', () => {
Expand Down Expand Up @@ -118,4 +129,34 @@ describe('CasesService', () => {
},
);
});

describe('getSingleCaseAttachmentRecord tests', () => {
it.each([
[
AttachmentsSingleResponseCaseExample,
{ [idName]: 'test' } as IdPathParams,
{ since: '2024-12-01' } as SinceQueryParams,
casesAttachmentsFieldName,
],
])(
'should return single values given good input',
async (data, idPathParams, sinceQueryParams, typeFieldName) => {
const attachmentsSpy = jest
.spyOn(attachmentsService, 'getSingleAttachmentRecord')
.mockReturnValueOnce(Promise.resolve(new AttachmentsEntity(data)));

const result = await service.getSingleCaseAttachmentRecord(
idPathParams,
sinceQueryParams,
);
expect(attachmentsSpy).toHaveBeenCalledWith(
RecordType.Case,
idPathParams,
typeFieldName,
sinceQueryParams,
);
expect(result).toEqual(new AttachmentsEntity(data));
},
);
});
});
19 changes: 19 additions & 0 deletions src/controllers/cases/cases.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,19 @@ import {
InPersonVisitsEntity,
NestedInPersonVisitsEntity,
} from '../../entities/in-person-visits.entity';
import { AttachmentsService } from '../../helpers/attachments/attachments.service';
import {
AttachmentsEntity,
NestedAttachmentsEntity,
} from '../../entities/attachments.entity';
import { casesAttachmentsFieldName } from '../../common/constants/parameter-constants';

@Injectable()
export class CasesService {
constructor(
private readonly supportNetworkService: SupportNetworkService,
private readonly inPersonVisitsService: InPersonVisitsService,
private readonly attachmentsService: AttachmentsService,
) {}

async getSingleCaseSupportNetworkInformationRecord(
Expand All @@ -41,4 +48,16 @@ export class CasesService {
since,
);
}

async getSingleCaseAttachmentRecord(
id: IdPathParams,
since?: SinceQueryParams,
): Promise<AttachmentsEntity | NestedAttachmentsEntity> {
return await this.attachmentsService.getSingleAttachmentRecord(
RecordType.Case,
id,
casesAttachmentsFieldName,
since,
);
}
}
3 changes: 2 additions & 1 deletion src/controllers/controllers.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { Module } from '@nestjs/common';
import { CasesModule } from './cases/cases.module';
import { IncidentsModule } from './incidents/incidents.module';
import { ServiceRequestsModule } from './service-requests/service-requests.module';
import { MemosModule } from './memos/memos.module';

@Module({
imports: [CasesModule, IncidentsModule, ServiceRequestsModule],
imports: [CasesModule, IncidentsModule, ServiceRequestsModule, MemosModule],
})
export class ControllersModule {}
33 changes: 33 additions & 0 deletions src/controllers/incidents/incidents.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import { TokenRefresherService } from '../../external-api/token-refresher/token-
import { UtilitiesService } from '../../helpers/utilities/utilities.service';
import { RequestPreparerService } from '../../external-api/request-preparer/request-preparer.service';
import { idName } from '../../common/constants/parameter-constants';
import { AttachmentsService } from '../../helpers/attachments/attachments.service';
import {
AttachmentsSingleResponseIncidentExample,
AttachmentsEntity,
} from '../../entities/attachments.entity';

describe('IncidentsController', () => {
let controller: IncidentsController;
Expand All @@ -27,6 +32,7 @@ describe('IncidentsController', () => {
providers: [
IncidentsService,
SupportNetworkService,
AttachmentsService,
AuthService,
TokenRefresherService,
RequestPreparerService,
Expand Down Expand Up @@ -76,4 +82,31 @@ describe('IncidentsController', () => {
},
);
});

describe('getSingleIncidentAttachmentRecord tests', () => {
it.each([
[
AttachmentsSingleResponseIncidentExample,
{ [idName]: 'test' } as IdPathParams,
{ since: '2020-02-02' } as SinceQueryParams,
],
])(
'should return single values given good input',
async (data, idPathParams, sinceQueryParams) => {
const incidentServiceSpy = jest
.spyOn(incidentsService, 'getSingleIncidentAttachmentRecord')
.mockReturnValueOnce(Promise.resolve(new AttachmentsEntity(data)));

const result = await controller.getSingleIncidentAttachmentRecord(
idPathParams,
sinceQueryParams,
);
expect(incidentServiceSpy).toHaveBeenCalledWith(
idPathParams,
sinceQueryParams,
);
expect(result).toEqual(new AttachmentsEntity(data));
},
);
});
});
Loading

0 comments on commit 8340318

Please sign in to comment.