import { createAlert } from "../alert/alert.service"; import { AuthenticatedUser } from "../auth"; import { generateId } from "../utils/id"; import { extractExpressions, modelMap } from "../utils/tags"; import { CreateNoteInput, noteModel } from "./note.schema"; export async function createNote( input: CreateNoteInput, resourceId: string, resourceType: string, user: AuthenticatedUser ) { const userIds = extractExpressions(input.content); const newNote = await noteModel.create({ tenantId: user.tenantId, pid: generateId(), resourceId: resourceId, content: input.content, createdAt: new Date(), createdBy: user.userId, }); if ( userIds.length > 0 && [ "permits", "processed", "rts", "tasks", "ctasks", "payments", "notifications", ].includes(resourceType) ) { const model = modelMap[resourceType]; const obj = await model.findOne({ pid: resourceId }); let noteContent = newNote.content; const orgs = []; userIds.forEach((item) => { if (item == "client" && obj.client) { orgs.push({ orgId: obj.client.toString(), taggedAt: new Date() }); noteContent = noteContent.replaceAll( "{{client}}", `{{org-${obj.client.toString()}}}` ); } if (item == "agent") { orgs.push({ orgId: process.env.SUNCOAST_ID, taggedAt: new Date() }); noteContent = noteContent.replaceAll( "{{agent}}", `{{org-${process.env.SUNCOAST_ID}}}` ); } }); if (noteContent != newNote.content) { newNote.content = noteContent; await newNote.save(); } const taggedUsers = userIds .filter((item) => !["client", "agent"].includes(item)) .map((item) => { return { userId: item, taggedAt: new Date(), }; }); for (const org of orgs) { if (!obj.taggedOrgs) obj.taggedOrgs = []; const orgIndex = obj.taggedOrgs.findIndex( (item) => item.orgId == org.orgId ); if (orgIndex != -1) obj.taggedOrgs[orgIndex].taggedAt = new Date(); else obj.taggedOrgs.push(org); } for (const user of taggedUsers) { if (!obj.taggedUsers) obj.taggedUsers = []; const userIndex = obj.taggedUsers.findIndex( (item) => item.userId == user.userId ); if (userIndex != -1) obj.taggedUsers[userIndex].taggedAt = new Date(); else obj.taggedUsers.push(user); } if (taggedUsers.length > 0) { const assignee = obj.assignedTo.find( (item) => item.toString() == taggedUsers[0].userId ); if (!assignee) obj.assignedTo.push(taggedUsers[0].userId); } obj.markModified("taggedUsers", "assignedTo", "taggedOrgs"); await obj.save(); const metaFields: any = {}; if (obj.client) metaFields.client = obj.client.toString(); if (obj.county) { if (resourceType == "rts") metaFields.county = obj.county.toString(); else metaFields.county = obj.county.id.toString(); } if (obj.changes) metaFields.changes = obj.changes; if (obj.permitNumber) metaFields.permitNumber = obj.permitNumber; if (obj.cleanStatus) metaFields.standardStatus = obj.cleanStatus; if (obj.address) metaFields.address = obj.address.full_address; if (obj.lot) metaFields.lot = obj.lot; if (obj.block) metaFields.block = obj.block; if (obj.jobNumber) metaFields.jobNumber = obj.jobNumber; if (obj.permitType) metaFields.permitType = obj.permitType; if (obj.stage) metaFields.stage = obj.stage; if (obj.dueDate) metaFields.dueDate = obj.dueDate; if (obj.updatedAt) metaFields.updatedAt = obj.updatedAt; metaFields.createdBy = user.userId; if (taggedUsers.length > 0) { for (const taggedUser of taggedUsers) { if (taggedUser.userId == user.userId) continue; await createAlert( user.tenantId, "You are tagged in a note", "user", taggedUser.userId, resourceId, resourceType, { ...metaFields, } ); } } if (orgs.length > 0) { for (const org of orgs) { await createAlert( user.tenantId, `Your organization is tagged in a note`, "team", org.orgId, resourceId, resourceType, { ...metaFields, } ); } } } return newNote.populate({ path: "createdBy", select: "pid name avatar" }); } export async function updateNote( input: CreateNoteInput, resourceId: string, noteId: string, tenantId: string ) { return await noteModel .findOneAndUpdate( { $and: [ { pid: noteId }, { tenantId: tenantId }, { resourceId: resourceId }, ], }, { ...input }, { new: true } ) .populate({ path: "createdBy", select: "pid name avatar" }); } export async function listNotes(resourceId: string, tenantId: string) { return await noteModel.aggregate([ { $match: { $and: [{ resourceId: resourceId }, { tenantId: tenantId }] }, }, { $lookup: { from: "users", localField: "createdBy", foreignField: "_id", as: "user", }, }, { $project: { _id: 1, pid: 1, resourceId: 1, content: 1, createdAt: 1, createdBy: { $let: { vars: { user: { $arrayElemAt: ["$user", 0] } }, in: { _id: "$$user._id", pid: "$$user.pid", name: "$$user.name", avatar: "$$user.avatar", }, }, }, }, }, ]); } export async function deleteNote( resourceId: string, noteId: string, tenantId: string ) { return await noteModel.deleteOne({ $and: [{ pid: noteId }, { tenantId: tenantId }, { resourceId: resourceId }], }); }