feat: add taggedOrgs feature
This commit is contained in:
@@ -16,6 +16,7 @@ export const alertsModel = mongoose.model(
|
|||||||
county: { type: String, ref: "organization" },
|
county: { type: String, ref: "organization" },
|
||||||
permitType: String,
|
permitType: String,
|
||||||
address: String,
|
address: String,
|
||||||
|
createdBy: { type: String, ref: "user" },
|
||||||
},
|
},
|
||||||
recipientType: {
|
recipientType: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -28,7 +29,7 @@ export const alertsModel = mongoose.model(
|
|||||||
type: [String],
|
type: [String],
|
||||||
default: [],
|
default: [],
|
||||||
},
|
},
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
const alertResponse = z.object({
|
const alertResponse = z.object({
|
||||||
@@ -43,6 +44,7 @@ const alertResponse = z.object({
|
|||||||
county: z.any().optional(),
|
county: z.any().optional(),
|
||||||
permitType: z.string().optional(),
|
permitType: z.string().optional(),
|
||||||
address: z.string().optional(),
|
address: z.string().optional(),
|
||||||
|
createdBy: z.any().optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
recipientType: z.enum(["user", "team"]),
|
recipientType: z.enum(["user", "team"]),
|
||||||
@@ -64,5 +66,5 @@ export const { schemas: alertSchemas, $ref: $alert } = buildJsonSchemas(
|
|||||||
listAlertResponse,
|
listAlertResponse,
|
||||||
pageQueryParams,
|
pageQueryParams,
|
||||||
},
|
},
|
||||||
{ $id: "alert" }
|
{ $id: "alert" },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ export async function createAlert(
|
|||||||
county?: String;
|
county?: String;
|
||||||
permitType?: String;
|
permitType?: String;
|
||||||
address?: String;
|
address?: String;
|
||||||
}
|
createdBy?: String;
|
||||||
|
},
|
||||||
) {
|
) {
|
||||||
const newAlert = await alertsModel.create({
|
const newAlert = await alertsModel.create({
|
||||||
tenantId,
|
tenantId,
|
||||||
@@ -44,13 +45,13 @@ export async function createAlert(
|
|||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
["alert:read"]
|
["alert:read"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getUserAlerts(
|
export async function getUserAlerts(
|
||||||
user: AuthenticatedUser,
|
user: AuthenticatedUser,
|
||||||
params: PageQueryParams
|
params: PageQueryParams,
|
||||||
) {
|
) {
|
||||||
const page = params.page || 1;
|
const page = params.page || 1;
|
||||||
const pageSize = params.pageSize || 10;
|
const pageSize = params.pageSize || 10;
|
||||||
@@ -71,7 +72,8 @@ export async function getUserAlerts(
|
|||||||
.limit(pageSize)
|
.limit(pageSize)
|
||||||
.skip((page - 1) * pageSize)
|
.skip((page - 1) * pageSize)
|
||||||
.populate({ path: "metaFields.client", select: "pid name avatar" })
|
.populate({ path: "metaFields.client", select: "pid name avatar" })
|
||||||
.populate({ path: "metaFields.county", select: "pid name avatar" });
|
.populate({ path: "metaFields.county", select: "pid name avatar" })
|
||||||
|
.populate({ path: "metaFields.createdBy", select: "pid name avatar" });
|
||||||
|
|
||||||
const modifiedAlerts = alerts.map((alert) => {
|
const modifiedAlerts = alerts.map((alert) => {
|
||||||
return {
|
return {
|
||||||
@@ -89,7 +91,7 @@ export async function markAsRead(alertId: string, user: AuthenticatedUser) {
|
|||||||
const updatedAlert = await alertsModel.findOneAndUpdate(
|
const updatedAlert = await alertsModel.findOneAndUpdate(
|
||||||
{ tenantId: user.tenantId, pid: alertId },
|
{ tenantId: user.tenantId, pid: alertId },
|
||||||
{ $addToSet: { readBy: user.userId } },
|
{ $addToSet: { readBy: user.userId } },
|
||||||
{ new: true }
|
{ new: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!updatedAlert) return null;
|
if (!updatedAlert) return null;
|
||||||
@@ -116,7 +118,7 @@ export async function markAllRead(user: AuthenticatedUser) {
|
|||||||
|
|
||||||
const updatedResult = await alertsModel.updateMany(
|
const updatedResult = await alertsModel.updateMany(
|
||||||
{ $or: filters },
|
{ $or: filters },
|
||||||
{ $addToSet: { readBy: user.userId } }
|
{ $addToSet: { readBy: user.userId } },
|
||||||
);
|
);
|
||||||
|
|
||||||
return updatedResult;
|
return updatedResult;
|
||||||
|
|||||||
@@ -8,17 +8,10 @@ export async function createNote(
|
|||||||
input: CreateNoteInput,
|
input: CreateNoteInput,
|
||||||
resourceId: string,
|
resourceId: string,
|
||||||
resourceType: string,
|
resourceType: string,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
const userIds = extractExpressions(input.content);
|
const userIds = extractExpressions(input.content);
|
||||||
|
|
||||||
const taggedUsers = userIds.map((item) => {
|
|
||||||
return {
|
|
||||||
userId: item,
|
|
||||||
taggedAt: new Date(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const newNote = await noteModel.create({
|
const newNote = await noteModel.create({
|
||||||
tenantId: user.tenantId,
|
tenantId: user.tenantId,
|
||||||
pid: generateId(),
|
pid: generateId(),
|
||||||
@@ -43,44 +36,86 @@ export async function createNote(
|
|||||||
const model = modelMap[resourceType];
|
const model = modelMap[resourceType];
|
||||||
const obj = await model.findOne({ pid: resourceId });
|
const obj = await model.findOne({ pid: resourceId });
|
||||||
|
|
||||||
if (!obj.taggedUsers) {
|
const orgs = [];
|
||||||
await model.updateOne(
|
userIds.forEach((item) => {
|
||||||
{ pid: resourceId },
|
if (item == "client" && obj.client)
|
||||||
{
|
orgs.push({ orgId: obj.client.toString(), taggedAt: new Date() });
|
||||||
$set: { taggedUsers: taggedUsers },
|
if (item == "agent")
|
||||||
$addToSet: { assignedTo: userIds[0] },
|
orgs.push({ orgId: process.env.SUNCOAST_ID, taggedAt: new Date() });
|
||||||
}
|
});
|
||||||
|
|
||||||
|
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,
|
||||||
);
|
);
|
||||||
} else {
|
if (orgIndex != -1) obj.taggedOrgs[orgIndex].taggedAt = new Date();
|
||||||
for (const user of taggedUsers) {
|
else obj.taggedOrgs.push(org);
|
||||||
const userIndex = obj.taggedUsers.findIndex(
|
|
||||||
(item) => item.userId == user.userId
|
|
||||||
);
|
|
||||||
if (userIndex != -1) obj.taggedUsers[userIndex].taggedAt = new Date();
|
|
||||||
else obj.taggedUsers.push(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
const assignee = obj.assignedTo.find(
|
|
||||||
(item) => item.toString() == userIds[0]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!assignee) obj.assignedTo.push(userIds[0]);
|
|
||||||
|
|
||||||
obj.markModified("taggedUsers", "assignedTo");
|
|
||||||
await obj.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id of userIds) {
|
for (const user of taggedUsers) {
|
||||||
if (id == user.userId) continue;
|
if (!obj.taggedUsers) obj.taggedUsers = [];
|
||||||
|
|
||||||
await createAlert(
|
const userIndex = obj.taggedUsers.findIndex(
|
||||||
user.tenantId,
|
(item) => item.userId == user.userId,
|
||||||
"You are tagged in a note",
|
|
||||||
"user",
|
|
||||||
id,
|
|
||||||
resourceId,
|
|
||||||
resourceType
|
|
||||||
);
|
);
|
||||||
|
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();
|
||||||
|
|
||||||
|
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,
|
||||||
|
{
|
||||||
|
createdBy: user.userId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
{
|
||||||
|
createdBy: user.userId,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +126,7 @@ export async function updateNote(
|
|||||||
input: CreateNoteInput,
|
input: CreateNoteInput,
|
||||||
resourceId: string,
|
resourceId: string,
|
||||||
noteId: string,
|
noteId: string,
|
||||||
tenantId: string
|
tenantId: string,
|
||||||
) {
|
) {
|
||||||
return await noteModel
|
return await noteModel
|
||||||
.findOneAndUpdate(
|
.findOneAndUpdate(
|
||||||
@@ -103,7 +138,7 @@ export async function updateNote(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ ...input },
|
{ ...input },
|
||||||
{ new: true }
|
{ new: true },
|
||||||
)
|
)
|
||||||
.populate({ path: "createdBy", select: "pid name avatar" });
|
.populate({ path: "createdBy", select: "pid name avatar" });
|
||||||
}
|
}
|
||||||
@@ -147,7 +182,7 @@ export async function listNotes(resourceId: string, tenantId: string) {
|
|||||||
export async function deleteNote(
|
export async function deleteNote(
|
||||||
resourceId: string,
|
resourceId: string,
|
||||||
noteId: string,
|
noteId: string,
|
||||||
tenantId: string
|
tenantId: string,
|
||||||
) {
|
) {
|
||||||
return await noteModel.deleteOne({
|
return await noteModel.deleteOne({
|
||||||
$and: [{ pid: noteId }, { tenantId: tenantId }, { resourceId: resourceId }],
|
$and: [{ pid: noteId }, { tenantId: tenantId }, { resourceId: resourceId }],
|
||||||
|
|||||||
@@ -32,15 +32,16 @@ const notificationSchema = new mongoose.Schema({
|
|||||||
},
|
},
|
||||||
assignedToOrg: String,
|
assignedToOrg: String,
|
||||||
taggedUsers: Array,
|
taggedUsers: Array,
|
||||||
|
taggedOrgs: Array,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const notificationFields = Object.keys(notificationSchema.paths).filter(
|
export const notificationFields = Object.keys(notificationSchema.paths).filter(
|
||||||
(path) => path !== "__v"
|
(path) => path !== "__v",
|
||||||
);
|
);
|
||||||
|
|
||||||
export const notificationModel = mongoose.model(
|
export const notificationModel = mongoose.model(
|
||||||
"notification",
|
"notification",
|
||||||
notificationSchema
|
notificationSchema,
|
||||||
);
|
);
|
||||||
|
|
||||||
const createNotificationInput = z.object({
|
const createNotificationInput = z.object({
|
||||||
@@ -73,5 +74,5 @@ export const { schemas: notificationSchemas, $ref: $notification } =
|
|||||||
updateNotificationInput,
|
updateNotificationInput,
|
||||||
pageQueryParams,
|
pageQueryParams,
|
||||||
},
|
},
|
||||||
{ $id: "notification" }
|
{ $id: "notification" },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { orgModel } from "../organization/organization.schema";
|
|||||||
import {
|
import {
|
||||||
getFilterObject,
|
getFilterObject,
|
||||||
getSortObject,
|
getSortObject,
|
||||||
|
getTaggedOrgsFilter,
|
||||||
getTaggedUsersFilter,
|
getTaggedUsersFilter,
|
||||||
PageQueryParams,
|
PageQueryParams,
|
||||||
} from "../pagination";
|
} from "../pagination";
|
||||||
@@ -56,11 +57,7 @@ export async function updateNotification(
|
|||||||
user: AuthenticatedUser,
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
if (input.assignedToOrg && input.assignedTo) {
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
input.assignedTo = [];
|
delete input.assignedTo;
|
||||||
} else if (input.assignedToOrg) {
|
|
||||||
input.assignedTo = [];
|
|
||||||
} else if (input.assignedTo) {
|
|
||||||
input.assignedToOrg = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldNotification = await notificationModel.findOne(
|
const oldNotification = await notificationModel.findOne(
|
||||||
@@ -208,12 +205,18 @@ export async function listNotifications(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedUsersFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
|
filterObj,
|
||||||
|
sortObj,
|
||||||
|
);
|
||||||
|
|
||||||
|
let { taggedOrgsFilter, taggedOrgsFilterIndex } = getTaggedOrgsFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj,
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
|
if (taggedOrgsFilterIndex != -1) filterObj.splice(taggedOrgsFilterIndex, 1);
|
||||||
|
|
||||||
const pipeline: any = [
|
const pipeline: any = [
|
||||||
{
|
{
|
||||||
@@ -232,7 +235,8 @@ export async function listNotifications(
|
|||||||
|
|
||||||
pipeline.push(
|
pipeline.push(
|
||||||
...[
|
...[
|
||||||
...taggedFilter,
|
...taggedUsersFilter,
|
||||||
|
...taggedOrgsFilter,
|
||||||
{
|
{
|
||||||
$lookup: {
|
$lookup: {
|
||||||
from: "users",
|
from: "users",
|
||||||
@@ -259,6 +263,7 @@ export async function listNotifications(
|
|||||||
createdAt: 1,
|
createdAt: 1,
|
||||||
updatedAt: 1,
|
updatedAt: 1,
|
||||||
taggedUsers: 1,
|
taggedUsers: 1,
|
||||||
|
taggedOrgs: 1,
|
||||||
assignedToOrg: 1,
|
assignedToOrg: 1,
|
||||||
assignedTo: {
|
assignedTo: {
|
||||||
$map: {
|
$map: {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export type PageQueryParams = z.infer<typeof pageQueryParams>;
|
|||||||
|
|
||||||
export function getSortObject(
|
export function getSortObject(
|
||||||
params: PageQueryParams,
|
params: PageQueryParams,
|
||||||
validFields: Array<string>
|
validFields: Array<string>,
|
||||||
) {
|
) {
|
||||||
const sortObj: Record<string, 1 | -1> = {};
|
const sortObj: Record<string, 1 | -1> = {};
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ export function getSortObject(
|
|||||||
export function getFilterObject(params: PageQueryParams) {
|
export function getFilterObject(params: PageQueryParams) {
|
||||||
if (params.filter && params.filter != "") {
|
if (params.filter && params.filter != "") {
|
||||||
const parsedQuery = parse(params.filter.split("|")).filter(
|
const parsedQuery = parse(params.filter.split("|")).filter(
|
||||||
(query) => Object.keys(query).length > 0
|
(query) => Object.keys(query).length > 0,
|
||||||
);
|
);
|
||||||
return parsedQuery;
|
return parsedQuery;
|
||||||
}
|
}
|
||||||
@@ -49,13 +49,13 @@ export function getFilterObject(params: PageQueryParams) {
|
|||||||
|
|
||||||
export function getTaggedUsersFilter(
|
export function getTaggedUsersFilter(
|
||||||
filterObj: MongoFilter[],
|
filterObj: MongoFilter[],
|
||||||
sortObj: Record<string, 1 | -1>
|
sortObj: Record<string, 1 | -1>,
|
||||||
) {
|
) {
|
||||||
const taggedUserFilterIndex = filterObj.findIndex((item) =>
|
const taggedUserFilterIndex = filterObj.findIndex((item) =>
|
||||||
Object.keys(item).includes("taggedUsers")
|
Object.keys(item).includes("taggedUsers"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let taggedFilter = [];
|
let taggedUsersFilter = [];
|
||||||
if (taggedUserFilterIndex != -1) {
|
if (taggedUserFilterIndex != -1) {
|
||||||
const filterItem = filterObj[taggedUserFilterIndex].taggedUsers;
|
const filterItem = filterObj[taggedUserFilterIndex].taggedUsers;
|
||||||
let filterValues = null;
|
let filterValues = null;
|
||||||
@@ -75,7 +75,7 @@ export function getTaggedUsersFilter(
|
|||||||
|
|
||||||
const condition = notFlag ? { $exists: false } : { $exists: true };
|
const condition = notFlag ? { $exists: false } : { $exists: true };
|
||||||
|
|
||||||
taggedFilter = [
|
taggedUsersFilter = [
|
||||||
{
|
{
|
||||||
$addFields: {
|
$addFields: {
|
||||||
taggedUsersFilter: {
|
taggedUsersFilter: {
|
||||||
@@ -92,5 +92,53 @@ export function getTaggedUsersFilter(
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return { taggedFilter, taggedUserFilterIndex };
|
return { taggedUsersFilter, taggedUserFilterIndex };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getTaggedOrgsFilter(
|
||||||
|
filterObj: MongoFilter[],
|
||||||
|
sortObj: Record<string, 1 | -1>,
|
||||||
|
) {
|
||||||
|
const taggedOrgsFilterIndex = filterObj.findIndex((item) =>
|
||||||
|
Object.keys(item).includes("taggedOrgs"),
|
||||||
|
);
|
||||||
|
|
||||||
|
let taggedOrgsFilter = [];
|
||||||
|
if (taggedOrgsFilterIndex != -1) {
|
||||||
|
const filterItem = filterObj[taggedOrgsFilterIndex].taggedOrgs;
|
||||||
|
let filterValues = null;
|
||||||
|
|
||||||
|
let notFlag = false;
|
||||||
|
if (filterItem["$eq"]) {
|
||||||
|
filterValues = [filterItem["$eq"]];
|
||||||
|
} else if (filterItem["$ne"]) {
|
||||||
|
filterValues = [filterItem["$ne"]];
|
||||||
|
notFlag = true;
|
||||||
|
} else if (filterItem["$in"]) {
|
||||||
|
filterValues = filterItem["$in"];
|
||||||
|
} else {
|
||||||
|
filterValues = filterItem["$nin"];
|
||||||
|
notFlag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const condition = notFlag ? { $exists: false } : { $exists: true };
|
||||||
|
|
||||||
|
taggedOrgsFilter = [
|
||||||
|
{
|
||||||
|
$addFields: {
|
||||||
|
taggedOrgsFilter: {
|
||||||
|
$filter: {
|
||||||
|
input: "$taggedOrgs",
|
||||||
|
as: "org",
|
||||||
|
cond: { $in: ["$$org.orgId", filterValues] },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ $match: { "taggedOrgsFilter.0": condition } },
|
||||||
|
{ $sort: { "taggedOrgsFilter.taggedAt": sortObj.taggedOrgs ?? -1 } },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return { taggedOrgsFilter, taggedOrgsFilterIndex };
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const permitSchema = new mongoose.Schema({
|
|||||||
pipeline: Array,
|
pipeline: Array,
|
||||||
currentStage: Number,
|
currentStage: Number,
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false },
|
||||||
),
|
),
|
||||||
status: String,
|
status: String,
|
||||||
manualStatus: String,
|
manualStatus: String,
|
||||||
@@ -103,6 +103,7 @@ const permitSchema = new mongoose.Schema({
|
|||||||
startDate: Date,
|
startDate: Date,
|
||||||
history: Array,
|
history: Array,
|
||||||
taggedUsers: Array,
|
taggedUsers: Array,
|
||||||
|
taggedOrgs: Array,
|
||||||
noc: String,
|
noc: String,
|
||||||
deed: String,
|
deed: String,
|
||||||
requests: [String],
|
requests: [String],
|
||||||
@@ -118,7 +119,7 @@ permitSchema.index({ tenantId: 1, permitNumber: 1 }, { unique: true });
|
|||||||
permitSchema.index({ "address.full_address": "text" });
|
permitSchema.index({ "address.full_address": "text" });
|
||||||
|
|
||||||
export const permitFields = Object.keys(permitSchema.paths).filter(
|
export const permitFields = Object.keys(permitSchema.paths).filter(
|
||||||
(path) => path !== "__v"
|
(path) => path !== "__v",
|
||||||
);
|
);
|
||||||
export const permitModel = mongoose.model("permit", permitSchema);
|
export const permitModel = mongoose.model("permit", permitSchema);
|
||||||
|
|
||||||
@@ -150,7 +151,7 @@ const permitCore = {
|
|||||||
date: z.date().nullable().optional(),
|
date: z.date().nullable().optional(),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
comment: z.string().optional(),
|
comment: z.string().optional(),
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
currentStage: z.number(),
|
currentStage: z.number(),
|
||||||
})
|
})
|
||||||
@@ -182,7 +183,7 @@ const permitCore = {
|
|||||||
due_date: z.date().optional(),
|
due_date: z.date().optional(),
|
||||||
is_completed: z.string().optional(),
|
is_completed: z.string().optional(),
|
||||||
comment: z.string().optional(),
|
comment: z.string().optional(),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
newPayment: z
|
newPayment: z
|
||||||
@@ -194,7 +195,7 @@ const permitCore = {
|
|||||||
balance_due: z.number().optional(),
|
balance_due: z.number().optional(),
|
||||||
code_text: z.string().optional(),
|
code_text: z.string().optional(),
|
||||||
status: z.string().optional(),
|
status: z.string().optional(),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
newConditions: z
|
newConditions: z
|
||||||
@@ -204,7 +205,7 @@ const permitCore = {
|
|||||||
status_value: z.string().optional(),
|
status_value: z.string().optional(),
|
||||||
short_comments: z.string().optional(),
|
short_comments: z.string().optional(),
|
||||||
name: z.string().optional(),
|
name: z.string().optional(),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
professionals: z.record(z.any()).optional(),
|
professionals: z.record(z.any()).optional(),
|
||||||
@@ -297,5 +298,5 @@ export const { schemas: permitSchemas, $ref: $permit } = buildJsonSchemas(
|
|||||||
updatePermitInput,
|
updatePermitInput,
|
||||||
pageQueryParams,
|
pageQueryParams,
|
||||||
},
|
},
|
||||||
{ $id: "permit" }
|
{ $id: "permit" },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {
|
import {
|
||||||
getFilterObject,
|
getFilterObject,
|
||||||
getSortObject,
|
getSortObject,
|
||||||
|
getTaggedOrgsFilter,
|
||||||
getTaggedUsersFilter,
|
getTaggedUsersFilter,
|
||||||
PageQueryParams,
|
PageQueryParams,
|
||||||
} from "../pagination";
|
} from "../pagination";
|
||||||
@@ -153,18 +154,25 @@ export async function listPermits(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedUsersFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
|
filterObj,
|
||||||
|
sortObj,
|
||||||
|
);
|
||||||
|
|
||||||
|
let { taggedOrgsFilter, taggedOrgsFilterIndex } = getTaggedOrgsFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj,
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
|
if (taggedOrgsFilterIndex != -1) filterObj.splice(taggedOrgsFilterIndex, 1);
|
||||||
|
|
||||||
const permitsList = await permitModel.aggregate([
|
const permitsList = await permitModel.aggregate([
|
||||||
{
|
{
|
||||||
$match: { $and: [{ tenantId: user.tenantId }, ...filterObj] },
|
$match: { $and: [{ tenantId: user.tenantId }, ...filterObj] },
|
||||||
},
|
},
|
||||||
...taggedFilter,
|
...taggedUsersFilter,
|
||||||
|
...taggedOrgsFilter,
|
||||||
{
|
{
|
||||||
$lookup: {
|
$lookup: {
|
||||||
from: "users",
|
from: "users",
|
||||||
@@ -219,6 +227,7 @@ export async function listPermits(
|
|||||||
startDate: 1,
|
startDate: 1,
|
||||||
history: 1,
|
history: 1,
|
||||||
taggedUsers: 1,
|
taggedUsers: 1,
|
||||||
|
taggedOrgs: 1,
|
||||||
noc: 1,
|
noc: 1,
|
||||||
deed: 1,
|
deed: 1,
|
||||||
requests: 1,
|
requests: 1,
|
||||||
@@ -268,11 +277,7 @@ export async function updatePermit(
|
|||||||
user: AuthenticatedUser,
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
if (input.assignedToOrg && input.assignedTo) {
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
input.assignedTo = [];
|
delete input.assignedTo;
|
||||||
} else if (input.assignedToOrg) {
|
|
||||||
input.assignedTo = [];
|
|
||||||
} else if (input.assignedTo) {
|
|
||||||
input.assignedToOrg = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldPermitResult = await permitModel.findOne(
|
const oldPermitResult = await permitModel.findOne(
|
||||||
@@ -562,6 +567,7 @@ export async function searchPermit(
|
|||||||
startDate: 1,
|
startDate: 1,
|
||||||
history: 1,
|
history: 1,
|
||||||
taggedUsers: 1,
|
taggedUsers: 1,
|
||||||
|
taggedOrgs: 1,
|
||||||
noc: 1,
|
noc: 1,
|
||||||
deed: 1,
|
deed: 1,
|
||||||
requests: 1,
|
requests: 1,
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ const processedSchema = new mongoose.Schema({
|
|||||||
startDate: Date,
|
startDate: Date,
|
||||||
history: Array,
|
history: Array,
|
||||||
taggedUsers: Array,
|
taggedUsers: Array,
|
||||||
|
taggedOrgs: Array,
|
||||||
noc: String,
|
noc: String,
|
||||||
deed: String,
|
deed: String,
|
||||||
requests: [String],
|
requests: [String],
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { AuthenticatedUser } from "../auth";
|
|||||||
import {
|
import {
|
||||||
getFilterObject,
|
getFilterObject,
|
||||||
getSortObject,
|
getSortObject,
|
||||||
|
getTaggedOrgsFilter,
|
||||||
getTaggedUsersFilter,
|
getTaggedUsersFilter,
|
||||||
PageQueryParams,
|
PageQueryParams,
|
||||||
} from "../pagination";
|
} from "../pagination";
|
||||||
@@ -44,11 +45,7 @@ export async function updateProcessed(
|
|||||||
user: AuthenticatedUser,
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
if (input.assignedToOrg && input.assignedTo) {
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
input.assignedTo = [];
|
delete input.assignedTo;
|
||||||
} else if (input.assignedToOrg) {
|
|
||||||
input.assignedTo = [];
|
|
||||||
} else if (input.assignedTo) {
|
|
||||||
input.assignedToOrg = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldPermitResult = await processedModel.findOne(
|
const oldPermitResult = await processedModel.findOne(
|
||||||
@@ -205,12 +202,18 @@ export async function listProcessedPermits(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedUsersFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
|
filterObj,
|
||||||
|
sortObj,
|
||||||
|
);
|
||||||
|
|
||||||
|
let { taggedOrgsFilter, taggedOrgsFilterIndex } = getTaggedOrgsFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj,
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
|
if (taggedOrgsFilterIndex != -1) filterObj.splice(taggedOrgsFilterIndex, 1);
|
||||||
|
|
||||||
const pipeline: any = [
|
const pipeline: any = [
|
||||||
{
|
{
|
||||||
@@ -233,7 +236,8 @@ export async function listProcessedPermits(
|
|||||||
|
|
||||||
pipeline.push(
|
pipeline.push(
|
||||||
...[
|
...[
|
||||||
...taggedFilter,
|
...taggedUsersFilter,
|
||||||
|
...taggedOrgsFilter,
|
||||||
{
|
{
|
||||||
$lookup: {
|
$lookup: {
|
||||||
from: "users",
|
from: "users",
|
||||||
@@ -288,6 +292,7 @@ export async function listProcessedPermits(
|
|||||||
block: 1,
|
block: 1,
|
||||||
jobNumber: 1,
|
jobNumber: 1,
|
||||||
taggedUsers: 1,
|
taggedUsers: 1,
|
||||||
|
taggedOrgs: 1,
|
||||||
noc: 1,
|
noc: 1,
|
||||||
deed: 1,
|
deed: 1,
|
||||||
requests: 1,
|
requests: 1,
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ const rtsSchema = new mongoose.Schema({
|
|||||||
},
|
},
|
||||||
assignedToOrg: String,
|
assignedToOrg: String,
|
||||||
taggedUsers: Array,
|
taggedUsers: Array,
|
||||||
|
taggedOrgs: Array,
|
||||||
fileValidationStatus: String,
|
fileValidationStatus: String,
|
||||||
permitNumber: [String],
|
permitNumber: [String],
|
||||||
lot: [String],
|
lot: [String],
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { generateId } from "../utils/id";
|
|||||||
import {
|
import {
|
||||||
getFilterObject,
|
getFilterObject,
|
||||||
getSortObject,
|
getSortObject,
|
||||||
|
getTaggedOrgsFilter,
|
||||||
getTaggedUsersFilter,
|
getTaggedUsersFilter,
|
||||||
PageQueryParams,
|
PageQueryParams,
|
||||||
} from "../pagination";
|
} from "../pagination";
|
||||||
@@ -99,18 +100,25 @@ export async function listRts(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedUsersFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
|
filterObj,
|
||||||
|
sortObj,
|
||||||
|
);
|
||||||
|
|
||||||
|
let { taggedOrgsFilter, taggedOrgsFilterIndex } = getTaggedOrgsFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj,
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
|
if (taggedOrgsFilterIndex != -1) filterObj.splice(taggedOrgsFilterIndex, 1);
|
||||||
|
|
||||||
const rtsList = await rtsModel.aggregate([
|
const rtsList = await rtsModel.aggregate([
|
||||||
{
|
{
|
||||||
$match: { $and: [{ tenantId: user.tenantId }, ...filterObj] },
|
$match: { $and: [{ tenantId: user.tenantId }, ...filterObj] },
|
||||||
},
|
},
|
||||||
...taggedFilter,
|
...taggedUsersFilter,
|
||||||
|
...taggedOrgsFilter,
|
||||||
{
|
{
|
||||||
$lookup: {
|
$lookup: {
|
||||||
from: "organizations",
|
from: "organizations",
|
||||||
@@ -241,11 +249,7 @@ export async function updateRts(
|
|||||||
user: AuthenticatedUser,
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
if (input.assignedToOrg && input.assignedTo) {
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
input.assignedTo = [];
|
delete input.assignedTo;
|
||||||
} else if (input.assignedToOrg) {
|
|
||||||
input.assignedTo = [];
|
|
||||||
} else if (input.assignedTo) {
|
|
||||||
input.assignedToOrg = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldRts = await rtsModel.findOne(
|
const oldRts = await rtsModel.findOne(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { createNote } from "../note/note.service";
|
|||||||
import {
|
import {
|
||||||
getFilterObject,
|
getFilterObject,
|
||||||
getSortObject,
|
getSortObject,
|
||||||
|
getTaggedOrgsFilter,
|
||||||
getTaggedUsersFilter,
|
getTaggedUsersFilter,
|
||||||
PageQueryParams,
|
PageQueryParams,
|
||||||
} from "../pagination";
|
} from "../pagination";
|
||||||
@@ -20,7 +21,7 @@ import {
|
|||||||
|
|
||||||
export async function createTask(
|
export async function createTask(
|
||||||
input: CreateTaskInput,
|
input: CreateTaskInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
if (!input.stage) {
|
if (!input.stage) {
|
||||||
input.stage = {
|
input.stage = {
|
||||||
@@ -44,7 +45,7 @@ export async function createTask(
|
|||||||
},
|
},
|
||||||
task.pid,
|
task.pid,
|
||||||
"tasks",
|
"tasks",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ export async function createTask(
|
|||||||
export async function updateTask(
|
export async function updateTask(
|
||||||
taskId: string,
|
taskId: string,
|
||||||
input: UpdateTaskInput,
|
input: UpdateTaskInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
const oldTask = await taskModel.findOne({ pid: taskId }, { assignedTo: 1 });
|
const oldTask = await taskModel.findOne({ pid: taskId }, { assignedTo: 1 });
|
||||||
const updatedTask = await taskModel
|
const updatedTask = await taskModel
|
||||||
@@ -70,7 +71,7 @@ export async function updateTask(
|
|||||||
if (updatedTask && input.assignedTo) {
|
if (updatedTask && input.assignedTo) {
|
||||||
const newAssignees = arrayDiff(
|
const newAssignees = arrayDiff(
|
||||||
updatedTask.assignedTo.map((item) => item._id),
|
updatedTask.assignedTo.map((item) => item._id),
|
||||||
oldTask.assignedTo
|
oldTask.assignedTo,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newAssignees.length > 0) {
|
if (newAssignees.length > 0) {
|
||||||
@@ -81,7 +82,7 @@ export async function updateTask(
|
|||||||
"user",
|
"user",
|
||||||
assignee,
|
assignee,
|
||||||
updatedTask.pid,
|
updatedTask.pid,
|
||||||
"tasks"
|
"tasks",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,25 +100,32 @@ export async function getTask(taskId: string, tenantId: string) {
|
|||||||
|
|
||||||
export async function listTasks(
|
export async function listTasks(
|
||||||
params: PageQueryParams,
|
params: PageQueryParams,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
const page = params.page || 1;
|
const page = params.page || 1;
|
||||||
const pageSize = params.pageSize || 10;
|
const pageSize = params.pageSize || 10;
|
||||||
const sortObj = getSortObject(params, taskFields);
|
const sortObj = getSortObject(params, taskFields);
|
||||||
let filterObj = getFilterObject(params) || [];
|
let filterObj = getFilterObject(params) || [];
|
||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedUsersFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj
|
sortObj,
|
||||||
|
);
|
||||||
|
|
||||||
|
let { taggedOrgsFilter, taggedOrgsFilterIndex } = getTaggedOrgsFilter(
|
||||||
|
filterObj,
|
||||||
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
|
if (taggedOrgsFilterIndex != -1) filterObj.splice(taggedOrgsFilterIndex, 1);
|
||||||
|
|
||||||
const taskList = await taskModel.aggregate([
|
const taskList = await taskModel.aggregate([
|
||||||
{
|
{
|
||||||
$match: { $and: [{ tenantId: user.tenantId }, ...filterObj] },
|
$match: { $and: [{ tenantId: user.tenantId }, ...filterObj] },
|
||||||
},
|
},
|
||||||
...taggedFilter,
|
...taggedUsersFilter,
|
||||||
|
...taggedOrgsFilter,
|
||||||
{
|
{
|
||||||
$lookup: {
|
$lookup: {
|
||||||
from: "users",
|
from: "users",
|
||||||
@@ -146,6 +154,7 @@ export async function listTasks(
|
|||||||
stage: 1,
|
stage: 1,
|
||||||
createdAt: 1,
|
createdAt: 1,
|
||||||
taggedUsers: 1,
|
taggedUsers: 1,
|
||||||
|
taggedOrgs: 1,
|
||||||
createdBy: {
|
createdBy: {
|
||||||
$let: {
|
$let: {
|
||||||
vars: { createdBy: { $arrayElemAt: ["$createdBy", 0] } },
|
vars: { createdBy: { $arrayElemAt: ["$createdBy", 0] } },
|
||||||
@@ -244,6 +253,7 @@ export async function searchTasks(params: PageQueryParams, tenantId: string) {
|
|||||||
stage: 1,
|
stage: 1,
|
||||||
createdAt: 1,
|
createdAt: 1,
|
||||||
taggedUsers: 1,
|
taggedUsers: 1,
|
||||||
|
taggedOrgs: 1,
|
||||||
createdBy: {
|
createdBy: {
|
||||||
$let: {
|
$let: {
|
||||||
vars: { createdBy: { $arrayElemAt: ["$createdBy", 0] } },
|
vars: { createdBy: { $arrayElemAt: ["$createdBy", 0] } },
|
||||||
@@ -296,7 +306,7 @@ export async function searchTasks(params: PageQueryParams, tenantId: string) {
|
|||||||
export async function newUpload(
|
export async function newUpload(
|
||||||
id: string,
|
id: string,
|
||||||
newUpload: UploadTaskInput,
|
newUpload: UploadTaskInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
return await taskModel.findOneAndUpdate(
|
return await taskModel.findOneAndUpdate(
|
||||||
{ pid: id, tenantId: user.tenantId },
|
{ pid: id, tenantId: user.tenantId },
|
||||||
@@ -308,6 +318,6 @@ export async function newUpload(
|
|||||||
createdBy: user.userId,
|
createdBy: user.userId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import mongoose from "mongoose";
|
|||||||
|
|
||||||
export type MongoFilter = Record<string, any>;
|
export type MongoFilter = Record<string, any>;
|
||||||
|
|
||||||
const ignoreObjectIdConversion = ["taggedUsers"];
|
const ignoreObjectIdConversion = ["taggedUsers", "taggedOrgs"];
|
||||||
const ignoreNumberConversion = ["jobNumber"];
|
const ignoreNumberConversion = ["jobNumber"];
|
||||||
const ignoreDateConversion = ["permitNumber"];
|
const ignoreDateConversion = ["permitNumber"];
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ function formulaToMongoFilter(formula: string): MongoFilter {
|
|||||||
|
|
||||||
// Convert each value to appropriate type
|
// Convert each value to appropriate type
|
||||||
const parsedValues = valueArray.map((value) =>
|
const parsedValues = valueArray.map((value) =>
|
||||||
convertValue(trimmedField, value)
|
convertValue(trimmedField, value),
|
||||||
);
|
);
|
||||||
|
|
||||||
// If no operator or equals operator, use $in
|
// If no operator or equals operator, use $in
|
||||||
@@ -98,7 +98,7 @@ function formulaToMongoFilter(formula: string): MongoFilter {
|
|||||||
|
|
||||||
export function parse(formulas: string[]): Array<MongoFilter> {
|
export function parse(formulas: string[]): Array<MongoFilter> {
|
||||||
const parsedQuery: Array<MongoFilter> = formulas.map((formula) =>
|
const parsedQuery: Array<MongoFilter> = formulas.map((formula) =>
|
||||||
formulaToMongoFilter(formula)
|
formulaToMongoFilter(formula),
|
||||||
);
|
);
|
||||||
return parsedQuery;
|
return parsedQuery;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,11 @@ import { paymentModel } from "../payments/payment.schema";
|
|||||||
export function extractExpressions(input: string) {
|
export function extractExpressions(input: string) {
|
||||||
return [...input.matchAll(/{{(.*?)}}/g)]
|
return [...input.matchAll(/{{(.*?)}}/g)]
|
||||||
.map((match) => match[1].trim())
|
.map((match) => match[1].trim())
|
||||||
.filter((item) => mongoose.Types.ObjectId.isValid(item));
|
.filter(
|
||||||
|
(item) =>
|
||||||
|
mongoose.Types.ObjectId.isValid(item) ||
|
||||||
|
["client", "team"].includes(item),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const modelMap = {
|
export const modelMap = {
|
||||||
|
|||||||
Reference in New Issue
Block a user