Files
permit-api/src/note/note.service.ts
2026-02-03 11:02:59 +05:30

229 lines
5.9 KiB
TypeScript

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 }],
});
}