Merged in approval-workflows (pull request #148)

temporary fix for same exam instance being used for all entities and implement approval process skip edge cases

Approved-by: Tiago Ribeiro
This commit is contained in:
João Correia
2025-02-08 18:03:43 +00:00
committed by Tiago Ribeiro
3 changed files with 72 additions and 17 deletions

View File

@@ -1,7 +1,10 @@
import { Module } from "@/interfaces";
import { getApprovalWorkflowByFormIntaker, createApprovalWorkflow } from "@/utils/approval.workflows.be";
import client from "@/lib/mongodb";
export async function createApprovalWorkflowsOnExamCreation(examAuthor: string, examEntities: string[], examId: string, examModule: string) {
const db = client.db(process.env.MONGODB_DB);
/* export async function createApprovalWorkflowsOnExamCreation(examAuthor: string, examEntities: string[], examId: string, examModule: string) {
const results = await Promise.all(
examEntities.map(async (entity) => {
const configuredWorkflow = await getApprovalWorkflowByFormIntaker(entity, examAuthor);
@@ -27,6 +30,50 @@ export async function createApprovalWorkflowsOnExamCreation(examAuthor: string,
const successCount = results.filter((r) => r.created).length;
const totalCount = examEntities.length;
return {
successCount,
totalCount,
};
} */
// TEMPORARY BEHAVIOUR! ONLY THE FIRST CONFIGURED WORKFLOW FOUND IS STARTED
export async function createApprovalWorkflowOnExamCreation(examAuthor: string, examEntities: string[], examId: string, examModule: string) {
let successCount = 0;
let totalCount = 0;
for (const entity of examEntities) {
const configuredWorkflow = await getApprovalWorkflowByFormIntaker(entity, examAuthor);
if (!configuredWorkflow) {
continue;
}
totalCount = 1; // a workflow was found
configuredWorkflow.modules.push(examModule as Module);
configuredWorkflow.name = examId;
configuredWorkflow.examId = examId;
configuredWorkflow.entityId = entity;
configuredWorkflow.startDate = Date.now();
try {
await createApprovalWorkflow("active-workflows", configuredWorkflow);
successCount = 1;
break; // Stop after the first success
} catch (error: any) {
break;
}
}
// prettier-ignore
if (totalCount === 0) { // current behaviour: if no workflow was found skip approval process
await db.collection(examModule).updateOne(
{ id: examId },
{ $set: { id: examId, isDiagnostic: false }},
{ upsert: true }
);
}
return {
successCount,
totalCount,

View File

@@ -1,7 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { Module } from "@/interfaces";
import { Exam, ExamBase, InstructorGender, Variant } from "@/interfaces/exam";
import { createApprovalWorkflowsOnExamCreation } from "@/lib/createWorkflowsOnExamCreation";
import { createApprovalWorkflowOnExamCreation } from "@/lib/createWorkflowsOnExamCreation";
import client from "@/lib/mongodb";
import { sessionOptions } from "@/lib/session";
import { mapBy } from "@/utils";
@@ -48,7 +48,7 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
const { module } = req.query as { module: string };
const session = client.startSession();
const entities = isAdmin(user) ? [] : mapBy(user.entities, "id"); // might need to change this with new approval workflows logic.. if an admin creates an exam no workflow is started because workflows must have entities configured.
const entities = isAdmin(user) ? [] : mapBy(user.entities, "id");
try {
const exam = {
@@ -76,6 +76,10 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
throw new Error("Name already exists");
}
if (isAdmin(user)) {
exam.isDiagnostic = false;
}
await db.collection(module).updateOne(
{ id: req.body.id },
{ $set: { id: req.body.id, ...exam } },
@@ -88,37 +92,41 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
// if it doesn't enter the next if condition it means the exam was updated and not created, so we can send this response.
responseStatus = 200;
responseMessage = `Successfully updated exam with ID: "${exam.id}"`;
// TODO maybe find a way to start missing approval workflows in case they were only configured after exam creation.
// create workflow only if exam is being created for the first time
if (docSnap === null) {
try {
const { successCount, totalCount } = await createApprovalWorkflowsOnExamCreation(exam.createdBy, exam.entities, exam.id, module);
const { successCount, totalCount } = await createApprovalWorkflowOnExamCreation(exam.createdBy, exam.entities, exam.id, module);
if (successCount === totalCount) {
if (isAdmin(user)) {
responseStatus = 200;
responseMessage = `Successfully created exam "${exam.id}" and started its Approval Workflow(s)`;
responseMessage = `Successfully created exam "${exam.id}" and skipped Approval Workflow due to admin rights.`;
} else if (successCount === totalCount) {
responseStatus = 200;
responseMessage = `Successfully created exam "${exam.id}" and started its Approval Workflow.`;
/* responseMessage = `Successfully created exam "${exam.id}" and started its Approval Workflow(s).`; */
} else if (successCount > 0) {
responseStatus = 207;
responseMessage = `Successfully created exam with ID: "${exam.id}" but was not able to start/find an Approval Workflow for all the author's entities`;
responseMessage = `Successfully created exam with ID: "${exam.id}" but was not able to start/find an Approval Workflow for all the author's entities.`;
} else {
responseStatus = 207;
responseMessage = `Successfully created exam with ID: "${exam.id}" but was not able to find any configured Approval Workflow for the author.`;
responseMessage = `Successfully created exam with ID: "${exam.id}" but skipping approval process because no approval workflow was found configured for the exam author.`;
}
} catch (error) {
console.error("Workflow creation error:", error);
responseStatus = 207;
responseMessage = `Successfully created exam with ID: "${exam.id}" but something went wrong while creating the Approval Workflow(s).`;
}
} else { // if exam was updated, log the updates
} else {
// if exam was updated, log the updates
const approvalWorkflows = await getApprovalWorkflowsByExamId(exam.id);
if (approvalWorkflows) {
const differences = generateExamDifferences(docSnap as Exam, exam as Exam);
if (differences) {
approvalWorkflows.forEach((workflow) => {
const currentStepIndex = workflow.steps.findIndex(step => !step.completed || step.rejected);
const currentStepIndex = workflow.steps.findIndex((step) => !step.completed || step.rejected);
if (workflow.steps[currentStepIndex].examChanges === undefined) {
workflow.steps[currentStepIndex].examChanges = [...differences];
} else {
@@ -129,7 +137,7 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
}
}
}
res.status(responseStatus).json({
message: responseMessage,
});

View File

@@ -37,9 +37,9 @@ export const getApprovalWorkflowByFormIntaker = async (entityId: string, formInt
export const getApprovalWorkflowsByExamId = async (examId: string) => {
return await db
.collection<ApprovalWorkflow>("active-workflows")
.find({
examId,
status: { $in: ["pending"] }
.find({
examId,
status: { $in: ["pending"] },
})
.toArray();
};