import mongoose from "mongoose"; import { AuthenticatedUser } from "../auth"; import { orgModel } from "../organization/organization.schema"; import { getFilterObject, getSortObject, PageQueryParams } from "../pagination"; import { userModel } from "../user/user.schema"; import { generateId } from "../utils/id"; import { CreateNotificationInput, notificationFields, notificationModel, UpdateNotificationInput, } from "./notification.schema"; import { getUser } from "../user/user.service"; import { createNote } from "../note/note.service"; import { createAlert } from "../alert/alert.service"; export async function createNotification( input: CreateNotificationInput, tenantId: string ) { const notification = await notificationModel.create({ ...input, pid: generateId(), tenantId: tenantId, createdAt: new Date(), }); return await notificationModel .findOne({ pid: notification.pid }) .populate({ path: "assignedTo", select: "pid name avatar" }); } export async function getNotification( notifId: string, user: AuthenticatedUser ) { return await notificationModel.findOne({ tenantId: user.tenantId, pid: notifId, }); } export async function updateNotification( notifId: string, input: UpdateNotificationInput, user: AuthenticatedUser ) { const updateNotificationResult = await notificationModel .findOneAndUpdate( { $and: [{ tenantId: user.tenantId }, { pid: notifId }] }, { ...input, updatedAt: new Date(), }, { new: true } ) .populate({ path: "assignedTo", select: "pid name avatar" }); if (updateNotificationResult) { for (const key in input) { if (["status", "assignedTo"].includes(key)) { let msg = ""; if (input[key] === null) { msg = `Cleared ${key}`; } else if (key == "assignedTo") { const user = await getUser(input.assignedTo); if (!user) continue; msg = `Assigned to ${user.firstName + " " + user.lastName}`; } else { msg = `Updated ${key} to '${input[key]}'`; } await createNote( { content: msg, }, notifId, "notifications", user ); if (key === "assignedTo") { await createNote( { content: msg }, updateNotificationResult.permitId, "notifications", user ); await createAlert( user.tenantId, `You are assigned to ${updateNotificationResult.permitNumber}`, "user", input.assignedTo, updateNotificationResult.permitId, "permits" ); } } } } return updateNotificationResult; } export async function listNotifications( params: PageQueryParams, user: AuthenticatedUser ) { const page = params.page || 1; const pageSize = params.pageSize || 10; const sortObj = getSortObject(params, notificationFields); const filterObj = getFilterObject(params) || []; filterObj.forEach((item) => { if (item.changes) { item[`changes.${item.changes.$eq}`] = { $exists: true }; delete item["changes"]; } }); if (user.role == "client") { filterObj.push({ client: new mongoose.Types.ObjectId(user.orgId) }); } let taggedFilter = []; if (sortObj.taggedUsers) { taggedFilter = [ { $addFields: { taggedUsers: { $filter: { input: "$taggedUsers", as: "user", cond: { $eq: ["$$user.userId", user.userId] }, }, }, }, }, { $match: { "taggedUsers.0": { $exists: true } } }, { $sort: { "taggedUsers.taggedAt": sortObj.taggedUsers } }, ]; } const pipeline: any = [ { $match: { $and: [{ tenantId: user.tenantId }, ...filterObj] }, }, ]; if (params.searchToken && params.searchToken != "") { const regex = new RegExp(params.searchToken, "i"); pipeline.push({ $match: { $or: [{ permitNumber: { $regex: regex } }, { link: { $regex: regex } }], }, }); } pipeline.push( ...[ ...taggedFilter, { $lookup: { from: "users", localField: "assignedTo", foreignField: "_id", as: "assignedTo", }, }, { $project: { _id: 1, pid: 1, permitId: 1, tenantId: 1, permitNumber: 1, link: 1, status: 1, permitType: 1, accelaStatus: 1, changes: 1, county: 1, client: 1, clientData: 1, createdAt: 1, updatedAt: 1, taggedUsers: 1, assignedTo: { $let: { vars: { assignedTo: { $arrayElemAt: ["$assignedTo", 0] } }, in: { _id: "$$assignedTo._id", pid: "$$assignedTo.pid", name: "$$assignedTo.name", avatar: "$$assignedTo.avatar", }, }, }, }, }, { $facet: { metadata: [{ $count: "count" }], data: [ { $sort: sortObj }, { $skip: (page - 1) * pageSize }, { $limit: pageSize }, ], }, }, ] ); const notifications = await notificationModel.aggregate(pipeline); if (notifications[0].data.length === 0) return { notifications: [], metadata: { count: 0, page, pageSize } }; return { notifications: notifications[0].data, metadata: { count: notifications[0].metadata[0].count, page, pageSize, }, }; } export async function deleteNotification(notifId: string, tenantId: string) { return await notificationModel.deleteOne({ $and: [{ tenantId: tenantId }, { pid: notifId }], }); }