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:
@@ -1,7 +1,10 @@
|
|||||||
import { Module } from "@/interfaces";
|
import { Module } from "@/interfaces";
|
||||||
import { getApprovalWorkflowByFormIntaker, createApprovalWorkflow } from "@/utils/approval.workflows.be";
|
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(
|
const results = await Promise.all(
|
||||||
examEntities.map(async (entity) => {
|
examEntities.map(async (entity) => {
|
||||||
const configuredWorkflow = await getApprovalWorkflowByFormIntaker(entity, examAuthor);
|
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 successCount = results.filter((r) => r.created).length;
|
||||||
const totalCount = examEntities.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 {
|
return {
|
||||||
successCount,
|
successCount,
|
||||||
totalCount,
|
totalCount,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||||
import { Module } from "@/interfaces";
|
import { Module } from "@/interfaces";
|
||||||
import { Exam, ExamBase, InstructorGender, Variant } from "@/interfaces/exam";
|
import { Exam, ExamBase, InstructorGender, Variant } from "@/interfaces/exam";
|
||||||
import { createApprovalWorkflowsOnExamCreation } from "@/lib/createWorkflowsOnExamCreation";
|
import { createApprovalWorkflowOnExamCreation } from "@/lib/createWorkflowsOnExamCreation";
|
||||||
import client from "@/lib/mongodb";
|
import client from "@/lib/mongodb";
|
||||||
import { sessionOptions } from "@/lib/session";
|
import { sessionOptions } from "@/lib/session";
|
||||||
import { mapBy } from "@/utils";
|
import { mapBy } from "@/utils";
|
||||||
@@ -48,7 +48,7 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
const { module } = req.query as { module: string };
|
const { module } = req.query as { module: string };
|
||||||
|
|
||||||
const session = client.startSession();
|
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 {
|
try {
|
||||||
const exam = {
|
const exam = {
|
||||||
@@ -76,6 +76,10 @@ async function POST(req: NextApiRequest, res: NextApiResponse) {
|
|||||||
throw new Error("Name already exists");
|
throw new Error("Name already exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAdmin(user)) {
|
||||||
|
exam.isDiagnostic = false;
|
||||||
|
}
|
||||||
|
|
||||||
await db.collection(module).updateOne(
|
await db.collection(module).updateOne(
|
||||||
{ id: req.body.id },
|
{ id: req.body.id },
|
||||||
{ $set: { id: req.body.id, ...exam } },
|
{ $set: { id: req.body.id, ...exam } },
|
||||||
@@ -88,36 +92,40 @@ 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.
|
// 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;
|
responseStatus = 200;
|
||||||
responseMessage = `Successfully updated exam with ID: "${exam.id}"`;
|
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
|
// create workflow only if exam is being created for the first time
|
||||||
if (docSnap === null) {
|
if (docSnap === null) {
|
||||||
try {
|
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;
|
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) {
|
} else if (successCount > 0) {
|
||||||
responseStatus = 207;
|
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 {
|
} else {
|
||||||
responseStatus = 207;
|
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) {
|
} catch (error) {
|
||||||
console.error("Workflow creation error:", error);
|
console.error("Workflow creation error:", error);
|
||||||
responseStatus = 207;
|
responseStatus = 207;
|
||||||
responseMessage = `Successfully created exam with ID: "${exam.id}" but something went wrong while creating the Approval Workflow(s).`;
|
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);
|
const approvalWorkflows = await getApprovalWorkflowsByExamId(exam.id);
|
||||||
|
|
||||||
if (approvalWorkflows) {
|
if (approvalWorkflows) {
|
||||||
const differences = generateExamDifferences(docSnap as Exam, exam as Exam);
|
const differences = generateExamDifferences(docSnap as Exam, exam as Exam);
|
||||||
if (differences) {
|
if (differences) {
|
||||||
approvalWorkflows.forEach((workflow) => {
|
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) {
|
if (workflow.steps[currentStepIndex].examChanges === undefined) {
|
||||||
workflow.steps[currentStepIndex].examChanges = [...differences];
|
workflow.steps[currentStepIndex].examChanges = [...differences];
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export const getApprovalWorkflowsByExamId = async (examId: string) => {
|
|||||||
.collection<ApprovalWorkflow>("active-workflows")
|
.collection<ApprovalWorkflow>("active-workflows")
|
||||||
.find({
|
.find({
|
||||||
examId,
|
examId,
|
||||||
status: { $in: ["pending"] }
|
status: { $in: ["pending"] },
|
||||||
})
|
})
|
||||||
.toArray();
|
.toArray();
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user