src/compliance/risk.service.ts
Methods |
|
constructor(prismaService: PrismaService, temporalProvider: TemporalProvider, notificationService: NotificationService, requestService: RequestService)
|
|||||||||||||||
|
Defined in src/compliance/risk.service.ts:33
|
|||||||||||||||
|
Parameters :
|
| Async assignRiskToUser | ||||||||||||||||
assignRiskToUser(riskId: number, userId: string, assignedBy: string)
|
||||||||||||||||
|
Defined in src/compliance/risk.service.ts:219
|
||||||||||||||||
|
Assign a compliance risk to a user
Parameters :
Returns :
unknown
assigned |
| Async attachRequestToRiskSubmission | ||||||||||||
attachRequestToRiskSubmission(id: number, requestId: number)
|
||||||||||||
|
Defined in src/compliance/risk.service.ts:387
|
||||||||||||
|
Attach a request to a compliance risk submission
Parameters :
Returns :
unknown
updated submission |
| Async createComplianceRisk | ||||||||
createComplianceRisk(complianceRisk: ComplianceRiskDto)
|
||||||||
|
Defined in src/compliance/risk.service.ts:46
|
||||||||
|
create a new compliance risk
Parameters :
Returns :
Promise<ComplianceRisk>
created risk |
| Async createComplianceRisks | ||||||||||||
createComplianceRisks(submissionId: number, complianceRisks: ComplianceRiskCreateInput[])
|
||||||||||||
|
Defined in src/compliance/risk.service.ts:74
|
||||||||||||
|
create multiple compliance risks
Parameters :
Returns :
Promise<ComplianceRisk[]>
list of created risks |
| Async createNotification | ||||||||||||||||||||
createNotification(event: ComplianceEvents, channel: NotificationChannel, risk: ComplianceRisk, assignedBy: string)
|
||||||||||||||||||||
|
Defined in src/compliance/risk.service.ts:272
|
||||||||||||||||||||
|
Create a notification for a given compliance risk and event
Parameters :
Returns :
unknown
notification |
| Async deleteComplianceRisk | ||||||||
deleteComplianceRisk(id: number)
|
||||||||
|
Defined in src/compliance/risk.service.ts:206
|
||||||||
|
Delete a compliance risk
Parameters :
Returns :
Promise<ComplianceRisk>
deleted risk |
| Async deleteDependentRisk | ||||||
deleteDependentRisk(riskToDelete: ComplianceRisk[])
|
||||||
|
Defined in src/compliance/risk.service.ts:501
|
||||||
|
Function to delete dependent risks deletes risks and declines requests for the risks that are submitted
Parameters :
Returns :
Promise<any>
|
| Async deletePolicyDependentRisk | ||||||
deletePolicyDependentRisk(policyId: number)
|
||||||
|
Defined in src/compliance/risk.service.ts:469
|
||||||
|
Function to delete policy dependent risks deletes risks and declines requests for the risks that are submitted
Parameters :
Returns :
unknown
|
| Async deleteRuleDependentRisk | ||||||
deleteRuleDependentRisk(ruleIds: number[])
|
||||||
|
Defined in src/compliance/risk.service.ts:448
|
||||||
|
Function to delete rule dependent risks deletes risks and declines requests for the risks that are submitted
Parameters :
Returns :
Promise<any>
Promise |
| Async findExisting | ||||||
findExisting(where?: Prisma.ComplianceRiskWhereInput)
|
||||||
|
Defined in src/compliance/risk.service.ts:135
|
||||||
|
Find compliance risks for a submission
Parameters :
Returns :
Promise<ComplianceRisk[]>
list of compliance risks |
| Async findForProject | ||||||||
findForProject(projectId: number)
|
||||||||
|
Defined in src/compliance/risk.service.ts:110
|
||||||||
|
Find compliance risks for a project
Parameters :
Returns :
Promise<ComplianceRisk[]>
list of compliance risks |
| Async findMany | ||||||||
findMany(query: literal type)
|
||||||||
|
Defined in src/compliance/risk.service.ts:155
|
||||||||
|
Find compliance risks based on query
Parameters :
Returns :
unknown
list of compliance risks |
| Async findOne | ||||||||
findOne(id: number)
|
||||||||
|
Defined in src/compliance/risk.service.ts:97
|
||||||||
|
Find a compliance risk by id
Parameters :
Returns :
Promise<ComplianceRisk>
compliance risk |
| Async findRiskSubmission | ||||||||
findRiskSubmission(id: number)
|
||||||||
|
Defined in src/compliance/risk.service.ts:359
|
||||||||
|
Find a compliance risk submission by id
Parameters :
Returns :
Promise<ComplianceRiskSubmission>
compliance risk submission |
| getDependentProjects | ||||||
getDependentProjects(ruleIds: number[])
|
||||||
|
Defined in src/compliance/risk.service.ts:424
|
||||||
|
Function to get dependent projects for a list of rule ids
Parameters :
Returns :
Promise<number[]>
Promise<number[]> list of project ids |
| Async submitComplianceRisk | |||||||||
submitComplianceRisk(submissionData: ComplianceRiskSubmissionDto, uploadedBy: string)
|
|||||||||
|
Defined in src/compliance/risk.service.ts:318
|
|||||||||
|
Submit a compliance risk
Parameters :
Returns :
unknown
|
| Async updateComplianceRisk | ||||||||||||
updateComplianceRisk(id: number, complianceRisk: UpdateComplianceRiskDto)
|
||||||||||||
|
Defined in src/compliance/risk.service.ts:187
|
||||||||||||
|
Update a compliance risk
Parameters :
Returns :
Promise<ComplianceRisk>
updated risk |
| Async updateRiskSubmission | ||||||||||||||||
updateRiskSubmission(id: number, status: ComplianceRiskSubmissionStatus, evaluatedBy?: string)
|
||||||||||||||||
|
Defined in src/compliance/risk.service.ts:405
|
||||||||||||||||
|
Update a compliance risk submission status
Parameters :
Returns :
unknown
updated submission |
import { Injectable } from "@nestjs/common";
import { PrismaService } from "../common/prisma/prisma.service";
import { ComplianceRisk } from "./entities/risk.entity";
import {
ComplianceRiskStatus,
ComplianceRiskSubmissionStatus,
} from "./entities/compliance.types";
import {
ComplianceRiskCreateInput,
ComplianceRiskDto,
UpdateComplianceRiskDto,
} from "./dto/risk.dto";
import { ComplianceEvents, complianceEventsConfig } from "./compliance.events";
import {
NotificationChannel,
NotificationEntityType,
} from "../notification/types/notification.enums";
import {
getNamesFromEmail,
getTextFromTemplate,
getUuidSlug,
} from "../common/helper";
import { EventType } from "../common/events";
import { NotificationService } from "../notification/notification.service";
import { TemporalProvider } from "../providers/temporal/temporal.provider";
import { ComplianceRiskSubmissionDto } from "./dto/risk.submission.dto";
import { ComplianceRiskSubmission } from "./entities/risk.submission.entity";
import { ProjectStages } from "../project/entities/project.entity";
import { RequestService } from "../request/request.service";
import { Prisma } from "@prisma/client";
@Injectable()
export class ComplianceRiskService {
constructor(
private readonly prismaService: PrismaService,
private readonly temporalProvider: TemporalProvider,
private readonly notificationService: NotificationService,
private readonly requestService: RequestService,
) {}
/**
* create a new compliance risk
* @param {ComplianceRiskDto} complianceRisk compliance risk to create
* @returns {Promise<ComplianceRisk>} created risk
*/
async createComplianceRisk(
complianceRisk: ComplianceRiskDto,
): Promise<ComplianceRisk> {
return new ComplianceRisk(
await this.prismaService.complianceRisk.create({
data: {
assignedTo: complianceRisk.assignedTo,
status: ComplianceRiskStatus.TODO,
project: {
connect: { id: complianceRisk.projectId },
},
complianceSubmission: {
connect: { id: complianceRisk.complianceSubmissionId },
},
rule: {
connect: { id: complianceRisk.ruleId },
},
},
}),
);
}
/**
* create multiple compliance risks
* @param {number} submissionId submission id
* @param {ComplianceRiskCreateInput[]} complianceRisks list of risks to create
* @returns {Promise<ComplianceRisk[]>} list of created risks
*/
async createComplianceRisks(
submissionId: number,
complianceRisks: ComplianceRiskCreateInput[],
): Promise<ComplianceRisk[]> {
await this.prismaService.complianceRisk.createMany({
data: complianceRisks,
});
return this.prismaService.complianceRisk.findMany({
where: {
complianceSubmissionId: submissionId,
},
include: {
submissions: true,
},
});
}
/**
* Find a compliance risk by id
* @param {number} id risk id
* @returns {Promise<ComplianceRisk>} compliance risk
*/
async findOne(id: number): Promise<ComplianceRisk> {
const complianceRisk = await this.prismaService.complianceRisk.findUnique({
where: { id: id },
include: { project: true },
});
return new ComplianceRisk(complianceRisk);
}
/**
* Find compliance risks for a project
* @param {number} projectId project id
* @returns {Promise<ComplianceRisk[]>} list of compliance risks
*/
async findForProject(projectId: number): Promise<ComplianceRisk[]> {
const complianceRisks = await this.prismaService.complianceRisk.findMany({
where: {
status: {
notIn: [ComplianceRiskStatus.DELETED, ComplianceRiskStatus.ARCHIVED],
},
AND: { projectId: { equals: projectId } },
},
include: {
submissions: true,
rule: true,
},
orderBy: [{ createdAt: "desc" }],
});
return complianceRisks.map(
(complianceRisk) => new ComplianceRisk(complianceRisk),
);
}
/**
* Find compliance risks for a submission
* @param {object} query query object
* @returns {Promise<ComplianceRisk[]>} list of compliance risks
*/
async findExisting(
where?: Prisma.ComplianceRiskWhereInput,
): Promise<ComplianceRisk[]> {
const existing = await this.prismaService.complianceRisk.findMany({
where: {
...where,
},
include: {
rule: true,
submissions: true,
},
});
return existing.map((risk) => new ComplianceRisk(risk));
}
/**
* Find compliance risks based on query
* @param {object} query query object
* @returns {Promise<ComplianceRisk[]>} list of compliance risks
*/
async findMany(query: {
assignedTo?: string | null;
status?: ComplianceRiskStatus;
projectId?: number;
complianceSubmissionId?: number;
approvers?: string[];
}) {
const whereInput = {
assignedTo: query.assignedTo,
status: query.status,
projectId: query.projectId,
complianceSubmissionId: query.complianceSubmissionId,
approvers: undefined,
};
if (query.approvers && query.approvers.length > 0) {
whereInput.approvers = {
hasSome: query.approvers || [],
};
}
return this.prismaService.complianceRisk.findMany({
where: whereInput,
});
}
/**
* Update a compliance risk
* @param {number} id risk id
* @param {UpdateComplianceRiskDto} complianceRisk risk to update
* @returns {Promise<ComplianceRisk>} updated risk
*/
async updateComplianceRisk(
id: number,
complianceRisk: UpdateComplianceRiskDto,
): Promise<ComplianceRisk> {
return new ComplianceRisk(
await this.prismaService.complianceRisk.update({
where: {
id: id,
},
data: complianceRisk,
}),
);
}
/**
* Delete a compliance risk
* @param {number} id risk id
* @returns {Promise<ComplianceRisk>} deleted risk
*/
async deleteComplianceRisk(id: number): Promise<ComplianceRisk> {
return this.updateComplianceRisk(id, {
status: ComplianceRiskStatus.DELETED,
});
}
/**
* Assign a compliance risk to a user
* @param {number} riskId risk id
* @param {string} userId user id
* @param {string} assignedBy user id
* @returns {Promise<ComplianceRisk>} assigned
*/
async assignRiskToUser(riskId: number, userId: string, assignedBy: string) {
const _risk = await this.prismaService.complianceRisk.update({
where: { id: riskId },
data: {
assignedTo: userId,
},
include: {
project: true,
rule: true,
},
});
const risk = new ComplianceRisk(_risk);
const notificationPromises = [];
notificationPromises.push(
this.createNotification(
ComplianceEvents.COMPLIANCE_ASSIGN_RISK,
NotificationChannel.APP,
risk,
assignedBy,
),
this.createNotification(
ComplianceEvents.COMPLIANCE_ASSIGN_RISK,
NotificationChannel.EMAIL,
risk,
assignedBy,
),
);
const notifications = (await Promise.all(notificationPromises)).flat();
notifications.map((notification) => {
if (notification.channel != NotificationChannel.APP) {
this.temporalProvider.runAsync(
"deliverNotificationWorkflow",
[notification.id],
process.env.DEFAULT_QUEUE_NAME,
`workflow-deliverNotificationWorkflow-${getUuidSlug()}`,
);
}
});
return risk;
}
/**
* Create a notification for a given compliance risk and event
* @param {ComplianceEvents} event event
* @param {NotificationChannel} channel channel
* @param {ComplianceRisk} risk compliance risk
* @param {string} assignedBy user id
* @returns {Promise<Notification>} notification
*/
async createNotification(
event: ComplianceEvents,
channel: NotificationChannel,
risk: ComplianceRisk,
assignedBy: string,
) {
const entityType = NotificationEntityType.COMPLIANCE_RISK;
const entityId = risk.id;
const templateVars = {
sendToName: getNamesFromEmail(risk.assignedTo),
sendToEmail: risk.assignedTo,
assigner: getNamesFromEmail(assignedBy),
project: risk.project,
risk: risk,
rule: risk.rule,
complianceUrl: `${process.env.TURO_BASE_URL}projects/${risk.project["id"]}?activeTab=compliance`,
};
const config = complianceEventsConfig[event];
const template = config.channelConfig[channel];
const subject = getTextFromTemplate(template.subject, templateVars);
const body = getTextFromTemplate(template.body, templateVars);
const notificationData = {
projectId: risk.project["id"],
subject,
body,
severity: config.severity,
channel,
userId: risk.assignedTo,
entityId,
entityType,
eventType: EventType.COMPLIANCE_RISK,
eventIdentifier: event,
// notifier: assignedBy,
};
return this.notificationService.create(notificationData);
}
/**
* Submit a compliance risk
* @param {ComplianceRiskSubmissionDto} submission risk submission
*/
async submitComplianceRisk(
submissionData: ComplianceRiskSubmissionDto,
uploadedBy: string,
) {
const submission = await this.prismaService.complianceRiskSubmission.create(
{
data: {
risk: {
connect: { id: submissionData.riskId },
},
evidence: {
connect: { id: submissionData.evidenceId },
},
metrics: {
connect: submissionData.metricIds.map((id) => ({ id })),
},
status: ComplianceRiskSubmissionStatus.SUBMITTED,
submittedBy: uploadedBy,
comment: submissionData.comment,
},
},
);
this.temporalProvider.runAsync(
"complianceRiskSubmissionWorkflow",
[submission.id],
process.env.DEFAULT_QUEUE_NAME,
`workflow-complianceRiskSubmissionWorkflow-${getUuidSlug()}`,
);
await this.updateComplianceRisk(submissionData.riskId, {
status: ComplianceRiskStatus.INPROGRESS,
});
return new ComplianceRiskSubmission(submission);
}
/**
* Find a compliance risk submission by id
* @param {number} id submission id
* @returns {Promise<ComplianceRiskSubmission>} compliance risk submission
*/
async findRiskSubmission(id: number): Promise<ComplianceRiskSubmission> {
const submission =
await this.prismaService.complianceRiskSubmission.findUnique({
where: { id },
include: {
metrics: true,
risk: {
include: {
project: true,
rule: true,
},
},
evidence: true,
},
});
return new ComplianceRiskSubmission({
...submission,
project: submission.risk.project,
});
}
/**
* Attach a request to a compliance risk submission
* @param {number} id submission id
* @param {number} requestId request id
* @returns {Promise<ComplianceRiskSubmission>} updated submission
*/
async attachRequestToRiskSubmission(id: number, requestId: number) {
return this.prismaService.complianceRiskSubmission.update({
where: { id },
data: {
request: {
connect: { id: requestId },
},
},
});
}
/**
* Update a compliance risk submission status
* @param {number} id submission id
* @param {ComplianceRiskSubmissionStatus} status status
* @param {string} evaluatedBy user id
* @returns {Promise<ComplianceRiskSubmission>} updated submission
*/
async updateRiskSubmission(
id: number,
status: ComplianceRiskSubmissionStatus,
evaluatedBy?: string,
) {
const submission = await this.prismaService.complianceRiskSubmission.update(
{
where: { id },
data: { status, evaluatedBy: evaluatedBy ? evaluatedBy : null },
},
);
return new ComplianceRiskSubmission(submission);
}
/**
* Function to get dependent projects for a list of rule ids
* @param ruleIds
* @returns Promise<number[]> list of project ids
*/
getDependentProjects(ruleIds: number[]): Promise<number[]> {
return this.prismaService.complianceRisk
.findMany({
distinct: ["projectId"],
where: {
ruleId: {
in: ruleIds,
},
project: {
stage: {
not: ProjectStages.DELETED,
},
},
},
})
.then((risk) => risk.map((risk) => risk.projectId));
}
/**
* Function to delete rule dependent risks
* deletes risks and declines requests for the risks that are submitted
* @param ruleIds
* @returns Promise<any>
*/
async deleteRuleDependentRisk(ruleIds: number[]): Promise<any> {
const riskToDelete = await this.prismaService.complianceRisk.findMany({
where: {
ruleId: {
in: ruleIds,
},
},
include: {
submissions: true,
},
});
return this.deleteDependentRisk(riskToDelete);
}
/**
* Function to delete policy dependent risks
* deletes risks and declines requests for the risks that are submitted
* @param policyId
* @returns
*/
async deletePolicyDependentRisk(policyId: number) {
const dependentRisks = await this.prismaService.complianceRisk.findMany({
where: {
policies: {
some: {
id: policyId,
},
},
},
include: {
submissions: true,
policies: true,
},
});
const riskToDelete = [];
dependentRisks.forEach((risk) => {
if (risk.policies.length == 1) {
riskToDelete.push(risk);
}
});
return this.deleteDependentRisk(riskToDelete);
}
/**
* Function to delete dependent risks
* deletes risks and declines requests for the risks that are submitted
* @param riskToDelete
* @returns
*/
async deleteDependentRisk(riskToDelete: ComplianceRisk[]): Promise<any> {
await Promise.all(
riskToDelete.map((risk) => {
Promise.all(
risk.submissions.map(async (submission) => {
if (
submission["status"] === ComplianceRiskSubmissionStatus.SUBMITTED
) {
await this.requestService.declineRequest(
submission["requestId"],
"system@turo.com",
);
}
}),
);
return this.deleteComplianceRisk(risk.id);
}),
);
return riskToDelete;
}
}