Skip to content

Commit

Permalink
Merge pull request #1956 from bcgov/feature/ALCS-2134
Browse files Browse the repository at this point in the history
Add Tags to NOIs Once Submitted Instead of Subtypes
  • Loading branch information
Abradat authored Nov 6, 2024
2 parents 50be39c + de00ecc commit 877f8e2
Show file tree
Hide file tree
Showing 6 changed files with 244 additions and 392 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import { AutoMap } from 'automapper-classes';
import {
IsArray,
IsBoolean,
IsNumber,
IsOptional,
IsString,
IsUUID,
} from 'class-validator';
import { IsArray, IsBoolean, IsNumber, IsOptional, IsString, IsUUID } from 'class-validator';
import { BaseCodeDto } from '../../common/dtos/base.dto';
import { NoticeOfIntentOwnerDto } from '../../portal/notice-of-intent-submission/notice-of-intent-owner/notice-of-intent-owner.dto';
import { NoticeOfIntentSubmissionDetailedDto } from '../../portal/notice-of-intent-submission/notice-of-intent-submission.dto';
Expand Down Expand Up @@ -210,4 +203,5 @@ export class CreateNoticeOfIntentServiceDto {
localGovernmentUuid?: string;
source?: 'ALCS' | 'APPLICANT';
subtypes?: string[];
tags?: string[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { NoticeOfIntentSubtype } from './notice-of-intent-subtype.entity';
import { NoticeOfIntentType } from './notice-of-intent-type/notice-of-intent-type.entity';
import { NoticeOfIntent } from './notice-of-intent.entity';
import { NoticeOfIntentService } from './notice-of-intent.service';
import { NoticeOfIntentTagService } from './notice-of-intent-tag/notice-of-intent-tag.service';

describe('NoticeOfIntentService', () => {
let service: NoticeOfIntentService;
Expand All @@ -37,6 +38,7 @@ describe('NoticeOfIntentService', () => {
let mockCodeService: DeepMocked<CodeService>;
let mockSubmissionStatusService: DeepMocked<NoticeOfIntentSubmissionStatusService>;
let mockNoticeOfIntentSubmissionService: DeepMocked<NoticeOfIntentSubmissionService>;
let mockNoticeOfIntentTagService: DeepMocked<NoticeOfIntentTagService>;

beforeEach(async () => {
mockCardService = createMock();
Expand All @@ -48,6 +50,7 @@ describe('NoticeOfIntentService', () => {
mockCodeService = createMock();
mockSubmissionStatusService = createMock();
mockNoticeOfIntentSubmissionService = createMock();
mockNoticeOfIntentTagService = createMock();

const module: TestingModule = await Test.createTestingModule({
imports: [
Expand Down Expand Up @@ -94,6 +97,7 @@ describe('NoticeOfIntentService', () => {
provide: NoticeOfIntentSubmissionService,
useValue: mockNoticeOfIntentSubmissionService,
},
{ provide: NoticeOfIntentTagService, useValue: mockNoticeOfIntentTagService },
],
}).compile();

Expand All @@ -113,9 +117,7 @@ describe('NoticeOfIntentService', () => {
mockCardService.create.mockResolvedValue(mockCard);
mockFileNumberService.checkValidFileNumber.mockResolvedValue(true);
mockCodeService.fetchRegion.mockResolvedValue(new ApplicationRegion());
mockTypeRepository.findOneOrFail.mockResolvedValue(
new NoticeOfIntentType(),
);
mockTypeRepository.findOneOrFail.mockResolvedValue(new NoticeOfIntentType());

await service.create(
{
Expand Down Expand Up @@ -180,9 +182,7 @@ describe('NoticeOfIntentService', () => {
const promise = service.getOrFailByUuid('uuid');

await expect(promise).rejects.toMatchObject(
new ServiceNotFoundException(
`Failed to find notice of intent with uuid uuid`,
),
new ServiceNotFoundException(`Failed to find notice of intent with uuid uuid`),
);

expect(mockRepository.findOne).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -261,12 +261,8 @@ describe('NoticeOfIntentService', () => {
expect(res).toBeDefined();
expect(mockRepository.findOneOrFail).toHaveBeenCalledTimes(2);
expect(mockRepository.save).toHaveBeenCalledTimes(1);
expect(
mockSubmissionStatusService.setStatusDateByFileNumber,
).toHaveBeenCalledTimes(1);
expect(
mockSubmissionStatusService.setStatusDateByFileNumber,
).toHaveBeenCalledWith(
expect(mockSubmissionStatusService.setStatusDateByFileNumber).toHaveBeenCalledTimes(1);
expect(mockSubmissionStatusService.setStatusDateByFileNumber).toHaveBeenCalledWith(
undefined,
NOI_SUBMISSION_STATUS.SUBMITTED_TO_ALC_INCOMPLETE,
new Date(5),
Expand Down
156 changes: 41 additions & 115 deletions services/apps/alcs/src/alcs/notice-of-intent/notice-of-intent.service.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import {
ServiceNotFoundException,
ServiceValidationException,
} from '@app/common/exceptions/base.exception';
import { ServiceNotFoundException, ServiceValidationException } from '@app/common/exceptions/base.exception';
import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Mapper } from 'automapper-core';
import { InjectMapper } from 'automapper-nestjs';
import {
FindOptionsRelations,
FindOptionsWhere,
IsNull,
Like,
Not,
Repository,
} from 'typeorm';
import { FindOptionsRelations, FindOptionsWhere, IsNull, Like, Not, Repository } from 'typeorm';
import { FileNumberService } from '../../file-number/file-number.service';
import { PORTAL_TO_ALCS_STRUCTURE_MAP } from '../../portal/notice-of-intent-submission/notice-of-intent-submission.entity';
import { formatIncomingDate } from '../../utils/incoming-date.formatter';
Expand All @@ -30,12 +20,9 @@ import { NoticeOfIntentSubmissionStatusService } from './notice-of-intent-submis
import { NoticeOfIntentSubmissionService } from './notice-of-intent-submission/notice-of-intent-submission.service';
import { NoticeOfIntentSubtype } from './notice-of-intent-subtype.entity';
import { NoticeOfIntentType } from './notice-of-intent-type/notice-of-intent-type.entity';
import {
CreateNoticeOfIntentServiceDto,
NoticeOfIntentDto,
UpdateNoticeOfIntentDto,
} from './notice-of-intent.dto';
import { CreateNoticeOfIntentServiceDto, NoticeOfIntentDto, UpdateNoticeOfIntentDto } from './notice-of-intent.dto';
import { NoticeOfIntent } from './notice-of-intent.entity';
import { NoticeOfIntentTagService } from './notice-of-intent-tag/notice-of-intent-tag.service';

@Injectable()
export class NoticeOfIntentService {
Expand Down Expand Up @@ -70,13 +57,10 @@ export class NoticeOfIntentService {
private localGovernmentService: LocalGovernmentService,
private noticeOfIntentSubmissionStatusService: NoticeOfIntentSubmissionStatusService,
private noticeOfIntentSubmissionService: NoticeOfIntentSubmissionService,
private noticeOfIntentTagService: NoticeOfIntentTagService,
) {}

async create(
createDto: CreateNoticeOfIntentServiceDto,
board?: Board,
persist = true,
) {
async create(createDto: CreateNoticeOfIntentServiceDto, board?: Board, persist = true) {
await this.fileNumberService.checkValidFileNumber(createDto.fileNumber);

const type = await this.typeRepository.findOneOrFail({
Expand All @@ -96,11 +80,7 @@ export class NoticeOfIntentService {
});

if (board) {
noticeOfIntent.card = await this.cardService.create(
CARD_TYPE.NOI,
board,
false,
);
noticeOfIntent.card = await this.cardService.create(CARD_TYPE.NOI, board, false);
}

if (persist) {
Expand All @@ -114,9 +94,7 @@ export class NoticeOfIntentService {
async getOrFailByUuid(uuid: string) {
const noticeOfIntent = await this.get(uuid);
if (!noticeOfIntent) {
throw new ServiceNotFoundException(
`Failed to find notice of intent with uuid ${uuid}`,
);
throw new ServiceNotFoundException(`Failed to find notice of intent with uuid ${uuid}`);
}

return noticeOfIntent;
Expand All @@ -141,9 +119,7 @@ export class NoticeOfIntentService {
});

if (!noticeOfIntent) {
throw new ServiceNotFoundException(
`Failed to find notice of intent with card uuid ${cardUuid}`,
);
throw new ServiceNotFoundException(`Failed to find notice of intent with card uuid ${cardUuid}`);
}

return noticeOfIntent;
Expand Down Expand Up @@ -221,19 +197,14 @@ export class NoticeOfIntentService {
async update(fileNumber: string, updateDto: UpdateNoticeOfIntentDto) {
const noticeOfIntent = await this.getByFileNumber(fileNumber);

noticeOfIntent.summary = filterUndefined(
updateDto.summary,
noticeOfIntent.summary,
);
noticeOfIntent.summary = filterUndefined(updateDto.summary, noticeOfIntent.summary);
if (updateDto.localGovernmentUuid) {
noticeOfIntent.localGovernmentUuid = updateDto.localGovernmentUuid;
}

if (updateDto.subtype) {
const subtypes = await this.listSubtypes();
const selectedSubtypes = updateDto.subtype.map(
(code) => subtypes.find((subtype) => subtype.code === code)!,
);
const selectedSubtypes = updateDto.subtype.map((code) => subtypes.find((subtype) => subtype.code === code)!);

noticeOfIntent.subtype = selectedSubtypes;
}
Expand All @@ -253,65 +224,33 @@ export class NoticeOfIntentService {
noticeOfIntent.dateReceivedAllItems,
);

noticeOfIntent.feePaidDate = filterUndefined(
formatIncomingDate(updateDto.feePaidDate),
noticeOfIntent.feePaidDate,
);
noticeOfIntent.feePaidDate = filterUndefined(formatIncomingDate(updateDto.feePaidDate), noticeOfIntent.feePaidDate);

noticeOfIntent.feeWaived = filterUndefined(
updateDto.feeWaived,
noticeOfIntent.feeWaived,
);
noticeOfIntent.feeWaived = filterUndefined(updateDto.feeWaived, noticeOfIntent.feeWaived);

noticeOfIntent.feeSplitWithLg = filterUndefined(
updateDto.feeSplitWithLg,
noticeOfIntent.feeSplitWithLg,
);
noticeOfIntent.feeSplitWithLg = filterUndefined(updateDto.feeSplitWithLg, noticeOfIntent.feeSplitWithLg);

noticeOfIntent.feeAmount = filterUndefined(
updateDto.feeAmount,
noticeOfIntent.feeAmount,
);
noticeOfIntent.feeAmount = filterUndefined(updateDto.feeAmount, noticeOfIntent.feeAmount);

noticeOfIntent.dateSubmittedToAlc = filterUndefined(
formatIncomingDate(updateDto.dateSubmittedToAlc),
noticeOfIntent.dateSubmittedToAlc,
);

noticeOfIntent.retroactive =
updateDto.retroactive !== undefined
? updateDto.retroactive
: noticeOfIntent.retroactive;
updateDto.retroactive !== undefined ? updateDto.retroactive : noticeOfIntent.retroactive;

noticeOfIntent.alrArea = filterUndefined(
updateDto.alrArea,
noticeOfIntent.alrArea,
);
noticeOfIntent.alrArea = filterUndefined(updateDto.alrArea, noticeOfIntent.alrArea);

noticeOfIntent.agCap = filterUndefined(
updateDto.agCap,
noticeOfIntent.agCap,
);
noticeOfIntent.agCap = filterUndefined(updateDto.agCap, noticeOfIntent.agCap);

noticeOfIntent.agCapConsultant = filterUndefined(
updateDto.agCapConsultant,
noticeOfIntent.agCapConsultant,
);
noticeOfIntent.agCapConsultant = filterUndefined(updateDto.agCapConsultant, noticeOfIntent.agCapConsultant);

noticeOfIntent.agCapMap = filterUndefined(
updateDto.agCapMap,
noticeOfIntent.agCapMap,
);
noticeOfIntent.agCapMap = filterUndefined(updateDto.agCapMap, noticeOfIntent.agCapMap);

noticeOfIntent.agCapSource = filterUndefined(
updateDto.agCapSource,
noticeOfIntent.agCapSource,
);
noticeOfIntent.agCapSource = filterUndefined(updateDto.agCapSource, noticeOfIntent.agCapSource);

noticeOfIntent.staffObservations = filterUndefined(
updateDto.staffObservations,
noticeOfIntent.staffObservations,
);
noticeOfIntent.staffObservations = filterUndefined(updateDto.staffObservations, noticeOfIntent.staffObservations);

noticeOfIntent.proposalEndDate = filterUndefined(
formatIncomingDate(updateDto.proposalEndDate),
Expand All @@ -323,10 +262,7 @@ export class NoticeOfIntentService {
noticeOfIntent.proposalEndDate2,
);

noticeOfIntent.hideFromPortal = filterUndefined(
updateDto.hideFromPortal,
noticeOfIntent.hideFromPortal,
);
noticeOfIntent.hideFromPortal = filterUndefined(updateDto.hideFromPortal, noticeOfIntent.hideFromPortal);

if (updateDto.typeCode) {
noticeOfIntent.type = await this.typeRepository.findOneOrFail({
Expand All @@ -337,9 +273,7 @@ export class NoticeOfIntentService {
}

if (updateDto.regionCode) {
noticeOfIntent.region = await this.codeService.fetchRegion(
updateDto.regionCode,
);
noticeOfIntent.region = await this.codeService.fetchRegion(updateDto.regionCode);
}

await this.repository.save(noticeOfIntent);
Expand All @@ -349,10 +283,7 @@ export class NoticeOfIntentService {
return this.getByFileNumber(noticeOfIntent.fileNumber);
}

private async updateStatus(
updateDto: UpdateNoticeOfIntentDto,
noticeOfIntent: NoticeOfIntent,
) {
private async updateStatus(updateDto: UpdateNoticeOfIntentDto, noticeOfIntent: NoticeOfIntent) {
try {
if (updateDto.dateAcknowledgedIncomplete !== undefined) {
await this.noticeOfIntentSubmissionStatusService.setStatusDateByFileNumber(
Expand Down Expand Up @@ -469,48 +400,43 @@ export class NoticeOfIntentService {
});

if (!existingNoticeOfIntent) {
throw new ServiceValidationException(
`Notice of Intent with file number does not exist ${createDto.fileNumber}`,
);
throw new ServiceValidationException(`Notice of Intent with file number does not exist ${createDto.fileNumber}`);
}

if (!createDto.localGovernmentUuid) {
throw new ServiceValidationException(
`Local government is not set for notice of intent ${createDto.fileNumber}`,
);
throw new ServiceValidationException(`Local government is not set for notice of intent ${createDto.fileNumber}`);
}

let region = createDto.regionCode
? await this.codeService.fetchRegion(createDto.regionCode)
: undefined;
let region = createDto.regionCode ? await this.codeService.fetchRegion(createDto.regionCode) : undefined;

if (!region) {
const localGov = await this.localGovernmentService.getByUuid(
createDto.localGovernmentUuid,
);
const localGov = await this.localGovernmentService.getByUuid(createDto.localGovernmentUuid);
region = localGov?.preferredRegion;
}

existingNoticeOfIntent.fileNumber = createDto.fileNumber;
existingNoticeOfIntent.applicant = createDto.applicant;
existingNoticeOfIntent.dateSubmittedToAlc =
createDto.dateSubmittedToAlc || null;
existingNoticeOfIntent.dateSubmittedToAlc = createDto.dateSubmittedToAlc || null;
existingNoticeOfIntent.localGovernmentUuid = createDto.localGovernmentUuid;
existingNoticeOfIntent.typeCode = createDto.typeCode;
existingNoticeOfIntent.region = region;
existingNoticeOfIntent.card = new Card();
existingNoticeOfIntent.card.typeCode = CARD_TYPE.NOI;

if (createDto.subtypes && createDto.subtypes.length > 0) {
const subtypes = await this.listSubtypes();
const selectedSubtypes = subtypes.filter((subtype) =>
createDto.subtypes!.includes(subtype.code),
);
await this.repository.save(existingNoticeOfIntent);

existingNoticeOfIntent.subtype = selectedSubtypes;
if (createDto.tags && createDto.tags.length > 0) {
createDto.tags.map(async (tag) => {
try {
await this.noticeOfIntentTagService.addTagToNoticeOfIntent(createDto.fileNumber, tag);
} catch (e) {
this.logger.error(
`Could not add tag ${tag} to application number ${createDto.fileNumber} with error: ${e.error}`,
);
}
});
}

await this.repository.save(existingNoticeOfIntent);
return this.getByFileNumber(createDto.fileNumber);
}

Expand Down
Loading

0 comments on commit 877f8e2

Please sign in to comment.