import { ApprovalWorkflow } from "@/interfaces/approval.workflow"; import client from "@/lib/mongodb"; import { ObjectId } from "mongodb"; const db = client.db(process.env.MONGODB_DB); export const getApprovalWorkflows = async (collection: string, ids?: string[]) => { return await db .collection(collection) .find(ids ? { _id: { $in: ids.map((id) => new ObjectId(id)) } } : {}) .toArray(); }; export const getApprovalWorkflow = async (collection: string, id: string) => { return await db.collection(collection).findOne({ _id: new ObjectId(id) }); }; export const getApprovalWorkflowsByEntities = async (collection: string, ids: string[]) => { return await db .collection(collection) .find({ entityId: { $in: ids } }) .toArray(); }; export const getApprovalWorkflowByFormIntaker = async (entityId: string, formIntakerId: string) => { return await db.collection("configured-workflows").findOne({ entityId, steps: { $elemMatch: { stepNumber: 1, assignees: formIntakerId, }, }, }); }; export const getApprovalWorkflowsByExamId = async (examId: string) => { return await db .collection("active-workflows") .find({ examId, status: { $in: ["pending"] }, }) .toArray(); }; export const getFormIntakersByEntity = async (entityId: string) => { const results = await db .collection("configured-workflows") .aggregate([ // 1. Match workflows with the provided entityId { $match: { entityId } }, // 2. Unwind the steps array to process each step individually { $unwind: "$steps" }, // 3. Filter for the first step (you could also check for a "firstStep" flag if you prefer) { $match: { "steps.stepNumber": 1 } }, // 4. Unwind the assignees array so that each assignee is handled separately { $unwind: "$steps.assignees" }, // 5. Group by null (i.e. all documents) and add each assignee to a set to remove duplicates { $group: { _id: null, assignees: { $addToSet: "$steps.assignees" } } }, ]) .toArray(); // Return the assignees if the aggregation found any; otherwise return an empty array return results.length > 0 ? results[0].assignees : []; }; export const createApprovalWorkflow = async (collection: string, workflow: ApprovalWorkflow) => { const { _id, ...workflowWithoutId } = workflow as ApprovalWorkflow; return await db.collection(collection).insertOne(workflowWithoutId); }; export const createApprovalWorkflows = async (collection: string, workflows: ApprovalWorkflow[]) => { if (workflows.length === 0) return; const workflowsWithoutIds: ApprovalWorkflow[] = workflows.map(({ _id, ...wfs }) => wfs); return await db.collection(collection).insertMany(workflowsWithoutIds); }; export const updateApprovalWorkflow = async (collection: string, workflow: ApprovalWorkflow) => { const { _id, ...workflowWithoutId } = workflow as ApprovalWorkflow; return await db.collection(collection).replaceOne({ _id: new ObjectId(_id) }, workflowWithoutId); }; export const updateApprovalWorkflows = async (collection: string, workflows: ApprovalWorkflow[]) => { const bulkOperations = workflows.map((workflow) => { const { _id, ...workflowWithoutId } = workflow; return { replaceOne: { filter: { _id: new ObjectId(_id) }, replacement: workflowWithoutId, }, }; }); return await db.collection(collection).bulkWrite(bulkOperations); }; export const deleteApprovalWorkflow = async (collection: string, id: string) => { return await db.collection(collection).deleteOne({ _id: new ObjectId(id) }); }; export const replaceApprovalWorkflowsByEntities = async (workflows: ApprovalWorkflow[], entityIds: string[]) => { // 1. Keep track of the _id values of all workflows we want to end up with const finalIds = new Set(); // 2. Process incoming workflows for (const workflow of workflows) { if (workflow._id) { // Replace the existing ones await updateApprovalWorkflow("configured-workflows", workflow); finalIds.add(workflow._id.toString()); } else { // Insert if no _id const insertResult = await createApprovalWorkflow("configured-workflows", workflow); finalIds.add(insertResult.insertedId.toString()); } } // 3. Delete any existing workflow (within these entityIds) that wasn't in the final list await db.collection("configured-workflows").deleteMany({ _id: { $nin: Array.from(finalIds).map((id) => new ObjectId(id)), }, entityId: { $in: entityIds }, }); };