import { app } from "@/firebase"; import { WithEntity } from "@/interfaces/entity"; import { Assignment } from "@/interfaces/results"; import { CorporateUser, Group, GroupWithUsers, MasterCorporateUser, StudentUser, TeacherUser, Type, User } from "@/interfaces/user"; import client from "@/lib/mongodb"; import moment from "moment"; import { getLinkedUsers, getUser } from "./users.be"; import { getSpecificUsers } from "./users.be"; const db = client.db(process.env.MONGODB_DB); const addEntityToGroupPipeline = [ { $lookup: { from: "entities", localField: "entity", foreignField: "id", as: "entity" } }, { $addFields: { entity: { $arrayElemAt: ["$entity", 0] } } }, { $addFields: { entity: { $cond: { if: { $isArray: "$entity" }, then: undefined, else: "$entity" } } } } ] export const updateExpiryDateOnGroup = async (participantID: string, corporateID: string) => { const corporate = await db.collection("users").findOne({ id: corporateID }); const participant = await db.collection("users").findOne({ id: participantID }); if (!corporate || !participant) return; if (corporate.type !== "corporate" || (participant.type !== "student" && participant.type !== "teacher")) return; if (!corporate.subscriptionExpirationDate || !participant.subscriptionExpirationDate) return await db.collection("users").updateOne({ id: participant.id }, { $set: { subscriptionExpirationDate: null } }); const corporateDate = moment(corporate.subscriptionExpirationDate); const participantDate = moment(participant.subscriptionExpirationDate); if (corporateDate.isAfter(participantDate)) return await db.collection("users").updateOne({ id: participant.id }, { $set: { subscriptionExpirationDate: corporateDate.toISOString() } }); return; }; export const getUserCorporate = async (id: string) => { const user = await getUser(id); if (!user) return undefined; if (["admin", "developer"].includes(user.type)) return undefined; if (user.type === "mastercorporate") return user; const groups = await getParticipantGroups(id); const admins = await Promise.all(groups.map((x) => x.admin).map(getUser)); const corporates = admins .filter((x) => (user.type === "corporate" ? x?.type === "mastercorporate" : x?.type === "corporate")) .filter((x) => !!x) as User[]; if (corporates.length === 0) return undefined; return corporates.shift() as CorporateUser | MasterCorporateUser; }; export const getGroup = async (id: string) => { return await db.collection("groups").findOne({ id }); }; export const getGroups = async (): Promise[]> => { return await db.collection("groups") .aggregate>(addEntityToGroupPipeline).toArray() }; export const getParticipantGroups = async (id: string) => { return await db.collection("groups").find({ participants: id }).toArray(); }; export const getParticipantsGroups = async (ids: string[]) => { return await db.collection("groups").find({ participants: { $in: ids } }).toArray(); }; export const getUserGroups = async (id: string): Promise => { return await db.collection("groups").find({ admin: id }).toArray(); }; export const getUserNamedGroup = async (id: string, name: string) => { return await db.collection("groups").findOne({ admin: id, name }); }; export const removeParticipantFromGroup = async (id: string, user: string) => { return await db.collection("groups").updateOne({ id }, { // @ts-expect-error $pull: { participants: user } }) } export const getUsersGroups = async (ids: string[]) => { return await db .collection("groups") .find({ admin: { $in: ids } }) .toArray(); }; export const convertToUsers = (group: Group, users: User[]): GroupWithUsers => Object.assign(group, { admin: users.find((u) => u.id === group.admin), participants: group.participants.map((p) => users.find((u) => u.id === p)).filter((x) => !!x) as User[], }); export const getAllAssignersByCorporate = async (corporateID: string, type: Type): Promise => { const linkedTeachers = await getLinkedUsers(corporateID, type, "teacher"); const linkedCorporates = await getLinkedUsers(corporateID, type, "corporate"); return [...linkedTeachers.users.map((x) => x.id), ...linkedCorporates.users.map((x) => x.id)]; }; export const getGroupsForEntities = async (ids: string[]) => await db .collection("groups") .find({ entity: { $in: ids } }) .toArray(); export const getGroupsForUser = async (admin?: string, participant?: string) => { if (admin && participant) return await db.collection("groups").find({ admin, participant }).toArray(); if (admin) return await getUserGroups(admin); if (participant) return await getParticipantGroups(participant); return await getGroups(); }; export const getStudentGroupsForUsersWithoutAdmin = async (admin: string, participants: string[]) => { return await db .collection("groups") .find({ ...(admin ? { admin: { $ne: admin } } : {}), ...(participants ? { participants } : {}) }) .toArray(); }; export const getCorporateNameForStudent = async (studentID: string) => { const groups = await getStudentGroupsForUsersWithoutAdmin("", [studentID]); if (groups.length === 0) return ""; const adminUserIds = [...new Set(groups.map((g) => g.admin))]; const adminUsersData = (await getSpecificUsers(adminUserIds)).filter((x) => !!x) as User[]; if (adminUsersData.length === 0) return ""; const admins = adminUsersData.filter((x) => x.type === "corporate"); if (admins.length > 0) { return (admins[0] as CorporateUser).name; } return ""; }; export const getGroupsByEntity = async (id: string) => await db.collection("groups").find({ entity: id }).toArray(); export const getGroupsByEntities = async (ids: string[]): Promise[]> => await db.collection("groups") .aggregate>([ { $match: { entity: { $in: ids } } }, ...addEntityToGroupPipeline ]).toArray() export const countGroups = async () => await db.collection("groups").countDocuments({}) export const countGroupsByEntities = async (ids: string[]) => await db.collection("groups").countDocuments({ entity: { $in: ids } })