229 lines
5.9 KiB
TypeScript
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 }],
|
|
});
|
|
}
|