bex-twn/src/industry-change-application/industry-change-application.service.ts

179 lines
5.4 KiB
TypeScript
Raw Normal View History

2022-12-06 15:47:52 +00:00
import {
BadRequestException,
Injectable,
NotFoundException,
} from '@nestjs/common';
2022-12-06 12:26:39 +00:00
import { InjectModel } from '@nestjs/mongoose';
2022-12-08 18:08:31 +00:00
import { instanceToPlain, plainToInstance } from 'class-transformer';
2022-12-06 12:26:39 +00:00
import { Model } from 'mongoose';
2022-12-06 15:47:52 +00:00
import {
ApplicationStatus,
ObjectStatus,
ResidentStatus,
} from 'src/enums/status.enum';
import { TypeOfRegistration } from 'src/enums/type-of-registration.enums';
import { ResidentService } from 'src/resident/resident.service';
import { takeMongoObject, equate, take } from 'src/utility';
import { ListQueryDto } from './dtos/list-query.dto';
import { RegisterIndustryChangeApplicationDto } from './dtos/register-industry-change-application.dto';
2022-12-06 12:26:39 +00:00
import {
IndustryChangeApplication,
IndustryChangeApplicationDocument,
} from './schemas/IndustryChangeApplication.schema';
2022-12-06 15:47:52 +00:00
const requestedFields = [
'industry',
'willWorkInPhysicalJurisdiction',
'regulatoryElection',
'regulatoryElectionSub',
];
2022-12-06 12:26:39 +00:00
@Injectable()
export class IndustryChangeApplicationService {
constructor(
@InjectModel(IndustryChangeApplication.name)
private applicationModel: Model<IndustryChangeApplicationDocument>,
2022-12-06 15:47:52 +00:00
private resident: ResidentService,
2022-12-06 12:26:39 +00:00
) {}
2022-12-06 15:47:52 +00:00
async getAll(options: ListQueryDto) {
const getResident = await this.resident.getResidentBySub(
options.residentSub,
);
if (!getResident) {
throw new NotFoundException('Resident not found');
}
2022-12-07 07:10:04 +00:00
return this.applicationModel
.find({
residentSub: options.residentSub,
status: {
$in: options.statuses || Object.values(ApplicationStatus),
},
objectStatus: ObjectStatus.CURRENT,
})
.exec();
2022-12-06 15:47:52 +00:00
}
async getById(id: string) {
2022-12-07 07:10:04 +00:00
const find = await this.applicationModel.findById(id).exec();
2022-12-07 06:54:34 +00:00
if (!find) {
throw new NotFoundException('The application was not found');
}
if (find.objectStatus !== ObjectStatus.CURRENT) {
throw new BadRequestException('This application has been deleted.');
}
return find;
2022-12-06 15:47:52 +00:00
}
async create(data: RegisterIndustryChangeApplicationDto, token: string) {
// This might be possible to turn into a custom validator for class-validator
if (
data.willWorkInPhysicalJurisdiction === false &&
(!!data.industry ||
!!data.regulatoryElection ||
!!data.regulatoryElectionSub)
) {
throw new BadRequestException(
'industry, regulatoryElection and regulatoryElectionSub are not allowed when willWorkInPhysicalJurisdiction is false',
);
}
const getResident = await this.resident.getResidentBySub(data.residentSub);
if (!getResident) {
throw new BadRequestException('Resident not found');
}
if (getResident.status !== ResidentStatus.ACTIVE) {
throw new BadRequestException('Resident must be active!');
}
if (
![TypeOfRegistration.E_RESIDENCY, TypeOfRegistration.RESIDENCY].includes(
getResident.typeOfRegistration,
)
) {
throw new BadRequestException(
'Resident must be either an E-resident or a resident',
);
}
if (
equate(data, getResident, requestedFields).length ===
requestedFields.length
) {
throw new BadRequestException('Cannot request what is already the case.');
}
const status =
data.willWorkInPhysicalJurisdiction === true
? ApplicationStatus.IN_REVIEW
: ApplicationStatus.APPROVED;
const newApplication = new this.applicationModel({
residentSub: getResident.sub,
current: take(takeMongoObject(getResident), requestedFields),
requested: take(data, requestedFields),
status,
2022-12-07 06:54:34 +00:00
decision:
status === ApplicationStatus.APPROVED
? {
decidedAt: new Date(),
decidedBy: 'Automatic',
rejectionReason: null,
}
: undefined,
2022-12-06 15:47:52 +00:00
submittedAt: new Date(),
createdBy: token ?? 'no token provided for testing',
});
2022-12-06 16:29:27 +00:00
if (status === ApplicationStatus.APPROVED) {
getResident.willWorkInPhysicalJurisdiction =
data.willWorkInPhysicalJurisdiction;
getResident.industry = data.industry ?? null;
getResident.regulatoryElection = data.regulatoryElection ?? null;
getResident.regulatoryElectionSub = data.regulatoryElectionSub ?? null;
await this.resident.save(getResident);
}
2022-12-06 15:47:52 +00:00
return newApplication.save();
}
async markDeleted(id: string, token: string) {
2022-12-07 07:10:04 +00:00
const findApplication = await this.applicationModel.findById(id).exec();
2022-12-06 15:47:52 +00:00
if (!findApplication) {
throw new NotFoundException('Application was not found');
}
if (findApplication.status !== ApplicationStatus.IN_REVIEW) {
throw new BadRequestException(
'Only applications which are currently in review can be deleted.',
);
}
if (findApplication.objectStatus === ObjectStatus.DELETED) {
throw new BadRequestException('The object has already been deleted.');
}
findApplication.objectStatus = ObjectStatus.DELETED;
findApplication.updatedBy = token || 'no token provided for testing';
return findApplication.save();
}
makeReadable(input: IndustryChangeApplication | IndustryChangeApplication[]) {
2022-12-08 18:08:31 +00:00
if (Array.isArray(input)) {
return input.map((item) => this.makeReadable(item));
}
const response = plainToInstance(
IndustryChangeApplication,
(input as IndustryChangeApplicationDocument).toJSON(),
);
return instanceToPlain(response);
2022-12-06 12:26:39 +00:00
}
}