feat: add team alerts
This commit is contained in:
@@ -57,14 +57,11 @@ export async function getUserAlerts(
|
|||||||
|
|
||||||
const filters: Array<object> = [
|
const filters: Array<object> = [
|
||||||
{ recipientType: "user", recipientId: user.userId },
|
{ recipientType: "user", recipientId: user.userId },
|
||||||
];
|
{
|
||||||
|
|
||||||
if (user.role == "client")
|
|
||||||
filters.push({
|
|
||||||
recipientType: "team",
|
recipientType: "team",
|
||||||
recipientId: { $in: [...user.orgId] },
|
recipientId: { $in: [...user.orgId] },
|
||||||
});
|
},
|
||||||
else filters.push({ recipientType: "team" });
|
];
|
||||||
|
|
||||||
const alerts = await alertsModel
|
const alerts = await alertsModel
|
||||||
.find({
|
.find({
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ const notificationSchema = new mongoose.Schema({
|
|||||||
type: [Schema.Types.ObjectId],
|
type: [Schema.Types.ObjectId],
|
||||||
ref: "user",
|
ref: "user",
|
||||||
},
|
},
|
||||||
|
assignedToOrg: String,
|
||||||
taggedUsers: Array,
|
taggedUsers: Array,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -53,11 +54,13 @@ const createNotificationInput = z.object({
|
|||||||
client: z.string(),
|
client: z.string(),
|
||||||
clientData: z.object({}).passthrough(),
|
clientData: z.object({}).passthrough(),
|
||||||
assignedTo: z.array(z.string()).optional(),
|
assignedTo: z.array(z.string()).optional(),
|
||||||
|
assignedToOrg: z.enum(["client", "agent"]).nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateNotificationInput = z.object({
|
const updateNotificationInput = z.object({
|
||||||
status: z.string().optional(),
|
status: z.string().optional(),
|
||||||
assignedTo: z.array(z.string()).optional(),
|
assignedTo: z.array(z.string()).optional(),
|
||||||
|
assignedToOrg: z.enum(["client", "agent"]).nullable().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type CreateNotificationInput = z.infer<typeof createNotificationInput>;
|
export type CreateNotificationInput = z.infer<typeof createNotificationInput>;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import { arrayDiff } from "../utils/diff";
|
|||||||
|
|
||||||
export async function createNotification(
|
export async function createNotification(
|
||||||
input: CreateNotificationInput,
|
input: CreateNotificationInput,
|
||||||
tenantId: string
|
tenantId: string,
|
||||||
) {
|
) {
|
||||||
const notification = await notificationModel.create({
|
const notification = await notificationModel.create({
|
||||||
...input,
|
...input,
|
||||||
@@ -30,6 +30,9 @@ export async function createNotification(
|
|||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (input.assignedToOrg) {
|
||||||
|
}
|
||||||
|
|
||||||
return await notificationModel
|
return await notificationModel
|
||||||
.findOne({ pid: notification.pid })
|
.findOne({ pid: notification.pid })
|
||||||
.populate({ path: "assignedTo", select: "pid name avatar" });
|
.populate({ path: "assignedTo", select: "pid name avatar" });
|
||||||
@@ -37,7 +40,7 @@ export async function createNotification(
|
|||||||
|
|
||||||
export async function getNotification(
|
export async function getNotification(
|
||||||
notifId: string,
|
notifId: string,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
return await notificationModel
|
return await notificationModel
|
||||||
.findOne({
|
.findOne({
|
||||||
@@ -50,11 +53,19 @@ export async function getNotification(
|
|||||||
export async function updateNotification(
|
export async function updateNotification(
|
||||||
notifId: string,
|
notifId: string,
|
||||||
input: UpdateNotificationInput,
|
input: UpdateNotificationInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
|
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(
|
||||||
{ pid: notifId },
|
{ pid: notifId },
|
||||||
{ assignedTo: 1 }
|
{ assignedTo: 1, assignedToOrg: 1 },
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateNotificationResult = await notificationModel
|
const updateNotificationResult = await notificationModel
|
||||||
@@ -64,7 +75,7 @@ export async function updateNotification(
|
|||||||
...input,
|
...input,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
},
|
},
|
||||||
{ new: true }
|
{ new: true },
|
||||||
)
|
)
|
||||||
.populate({ path: "assignedTo", select: "pid name avatar" });
|
.populate({ path: "assignedTo", select: "pid name avatar" });
|
||||||
|
|
||||||
@@ -85,12 +96,12 @@ export async function updateNotification(
|
|||||||
},
|
},
|
||||||
notifId,
|
notifId,
|
||||||
"notifications",
|
"notifications",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
} else if (key == "assignedTo") {
|
} else if (key == "assignedTo") {
|
||||||
const newAssignees = arrayDiff(
|
const newAssignees = arrayDiff(
|
||||||
updateNotificationResult.assignedTo.map((item) => item._id),
|
updateNotificationResult.assignedTo.map((item) => item._id),
|
||||||
oldNotification.assignedTo
|
oldNotification.assignedTo,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newAssignees.length > 0) {
|
if (newAssignees.length > 0) {
|
||||||
@@ -112,7 +123,7 @@ export async function updateNotification(
|
|||||||
{
|
{
|
||||||
client: updateNotificationResult.client.toString(),
|
client: updateNotificationResult.client.toString(),
|
||||||
county: updateNotificationResult.county.id.toString(),
|
county: updateNotificationResult.county.id.toString(),
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,9 +133,35 @@ export async function updateNotification(
|
|||||||
},
|
},
|
||||||
notifId,
|
notifId,
|
||||||
"notifications",
|
"notifications",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (key == "assignedToOrg") {
|
||||||
|
if (
|
||||||
|
oldNotification.assignedToOrg ==
|
||||||
|
updateNotificationResult.assignedToOrg
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const orgName =
|
||||||
|
input.assignedToOrg == "agent"
|
||||||
|
? "Suncoast"
|
||||||
|
: updateNotificationResult.clientData.name;
|
||||||
|
|
||||||
|
await createAlert(
|
||||||
|
user.tenantId,
|
||||||
|
`${orgName} assigned to ${updateNotificationResult.permitNumber}`,
|
||||||
|
"team",
|
||||||
|
input.assignedToOrg == "client"
|
||||||
|
? updateNotificationResult.client.toString()
|
||||||
|
: process.env.SUNCOAST_ID,
|
||||||
|
updateNotificationResult.pid,
|
||||||
|
"permits",
|
||||||
|
{
|
||||||
|
client: updateNotificationResult.client.toString(),
|
||||||
|
county: updateNotificationResult.county.id.toString(),
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +171,7 @@ export async function updateNotification(
|
|||||||
|
|
||||||
export async function listNotifications(
|
export async function listNotifications(
|
||||||
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;
|
||||||
@@ -173,7 +210,7 @@ export async function listNotifications(
|
|||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
@@ -246,7 +283,7 @@ export async function listNotifications(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const notifications = await notificationModel.aggregate(pipeline);
|
const notifications = await notificationModel.aggregate(pipeline);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ const permitSchema = new mongoose.Schema({
|
|||||||
type: [Schema.Types.ObjectId],
|
type: [Schema.Types.ObjectId],
|
||||||
ref: "user",
|
ref: "user",
|
||||||
},
|
},
|
||||||
|
assignedToOrg: String,
|
||||||
link: String,
|
link: String,
|
||||||
address: Object,
|
address: Object,
|
||||||
recordType: String,
|
recordType: String,
|
||||||
@@ -160,6 +161,7 @@ const permitCore = {
|
|||||||
permitType: z.string().optional(),
|
permitType: z.string().optional(),
|
||||||
utility: z.string().nullable().optional(),
|
utility: z.string().nullable().optional(),
|
||||||
assignedTo: z.array(z.string()).nullable().optional(),
|
assignedTo: z.array(z.string()).nullable().optional(),
|
||||||
|
assignedToOrg: z.enum(["client", "agent"]).nullable().optional(),
|
||||||
link: z.string().optional(),
|
link: z.string().optional(),
|
||||||
address: z
|
address: z
|
||||||
.object({
|
.object({
|
||||||
@@ -272,6 +274,7 @@ const updatePermitInput = z.object({
|
|||||||
manualStatus: z.string().nullable().optional(),
|
manualStatus: z.string().nullable().optional(),
|
||||||
utility: z.string().nullable().optional(),
|
utility: z.string().nullable().optional(),
|
||||||
assignedTo: z.string().nullable().optional(),
|
assignedTo: z.string().nullable().optional(),
|
||||||
|
assignedToOrg: z.enum(["client", "agent"]).nullable().optional(),
|
||||||
newPayment: z.array(z.any()).optional(),
|
newPayment: z.array(z.any()).optional(),
|
||||||
communityName: z.string().nullable().optional(),
|
communityName: z.string().nullable().optional(),
|
||||||
lot: z.string().nullable().optional(),
|
lot: z.string().nullable().optional(),
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import { arrayDiff } from "../utils/diff";
|
|||||||
|
|
||||||
export async function createPermit(
|
export async function createPermit(
|
||||||
input: CreatePermitInput,
|
input: CreatePermitInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
if (!input.stage) {
|
if (!input.stage) {
|
||||||
input.stage = {
|
input.stage = {
|
||||||
@@ -63,7 +63,7 @@ export async function createPermit(
|
|||||||
orgId: permit.client.toString(),
|
orgId: permit.client.toString(),
|
||||||
document: permit,
|
document: permit,
|
||||||
} as ChangeEvent,
|
} as ChangeEvent,
|
||||||
["permit:read"]
|
["permit:read"],
|
||||||
);
|
);
|
||||||
|
|
||||||
return await permit.populate({
|
return await permit.populate({
|
||||||
@@ -88,7 +88,7 @@ export async function createPermit(
|
|||||||
orgId: permit.client.toString(),
|
orgId: permit.client.toString(),
|
||||||
document: permit,
|
document: permit,
|
||||||
} as ChangeEvent,
|
} as ChangeEvent,
|
||||||
["permit:read"]
|
["permit:read"],
|
||||||
);
|
);
|
||||||
|
|
||||||
return await permit.populate({
|
return await permit.populate({
|
||||||
@@ -130,7 +130,7 @@ export async function getPermit(permitId: string, user: AuthenticatedUser) {
|
|||||||
|
|
||||||
export async function listPermits(
|
export async function listPermits(
|
||||||
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;
|
||||||
@@ -155,7 +155,7 @@ export async function listPermits(
|
|||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
@@ -264,11 +264,19 @@ export async function listPermits(
|
|||||||
export async function updatePermit(
|
export async function updatePermit(
|
||||||
input: CreatePermitInput,
|
input: CreatePermitInput,
|
||||||
permitId: string,
|
permitId: string,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
|
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(
|
||||||
{ pid: permitId },
|
{ pid: permitId },
|
||||||
{ assignedTo: 1 }
|
{ assignedTo: 1, assignedToOrg: 1 },
|
||||||
);
|
);
|
||||||
const updatePermitResult = await permitModel
|
const updatePermitResult = await permitModel
|
||||||
.findOneAndUpdate(
|
.findOneAndUpdate(
|
||||||
@@ -276,7 +284,7 @@ export async function updatePermit(
|
|||||||
$and: [{ tenantId: user.tenantId }, { pid: permitId }],
|
$and: [{ tenantId: user.tenantId }, { pid: permitId }],
|
||||||
},
|
},
|
||||||
{ ...input, lastUpdateDate: new Date() },
|
{ ...input, lastUpdateDate: new Date() },
|
||||||
{ new: true }
|
{ new: true },
|
||||||
)
|
)
|
||||||
.populate({ path: "assignedTo", select: "pid name avatar" })
|
.populate({ path: "assignedTo", select: "pid name avatar" })
|
||||||
.populate({ path: "createdBy", select: "pid name avatar" });
|
.populate({ path: "createdBy", select: "pid name avatar" });
|
||||||
@@ -300,7 +308,7 @@ export async function updatePermit(
|
|||||||
},
|
},
|
||||||
permitId,
|
permitId,
|
||||||
"permits",
|
"permits",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (key == "requests" && input[key] != null) {
|
if (key == "requests" && input[key] != null) {
|
||||||
@@ -323,7 +331,7 @@ export async function updatePermit(
|
|||||||
client: updatePermitResult.client.toString(),
|
client: updatePermitResult.client.toString(),
|
||||||
county: updatePermitResult.county.id.toString(),
|
county: updatePermitResult.county.id.toString(),
|
||||||
address: updatePermitResult.address,
|
address: updatePermitResult.address,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,13 +354,13 @@ export async function updatePermit(
|
|||||||
},
|
},
|
||||||
permitId,
|
permitId,
|
||||||
"permits",
|
"permits",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (key == "assignedTo") {
|
} else if (key == "assignedTo") {
|
||||||
const newAssignees = arrayDiff(
|
const newAssignees = arrayDiff(
|
||||||
updatePermitResult.assignedTo.map((item) => item._id),
|
updatePermitResult.assignedTo.map((item) => item._id),
|
||||||
oldPermitResult.assignedTo
|
oldPermitResult.assignedTo,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newAssignees.length == 0) continue;
|
if (newAssignees.length == 0) continue;
|
||||||
@@ -376,7 +384,7 @@ export async function updatePermit(
|
|||||||
client: updatePermitResult.client.toString(),
|
client: updatePermitResult.client.toString(),
|
||||||
county: updatePermitResult.county.id.toString(),
|
county: updatePermitResult.county.id.toString(),
|
||||||
address: updatePermitResult.address.full_address,
|
address: updatePermitResult.address.full_address,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,7 +394,34 @@ export async function updatePermit(
|
|||||||
},
|
},
|
||||||
permitId,
|
permitId,
|
||||||
"permits",
|
"permits",
|
||||||
user
|
user,
|
||||||
|
);
|
||||||
|
} else if (key == "assignedToOrg") {
|
||||||
|
if (oldPermitResult.assignedToOrg == updatePermitResult.assignedToOrg)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
console.log(oldPermitResult.assignedToOrg);
|
||||||
|
console.log(updatePermitResult.assignedToOrg);
|
||||||
|
|
||||||
|
const orgName =
|
||||||
|
input.assignedToOrg == "agent"
|
||||||
|
? "Suncoast"
|
||||||
|
: updatePermitResult.clientData.name;
|
||||||
|
|
||||||
|
await createAlert(
|
||||||
|
user.tenantId,
|
||||||
|
`${orgName} assigned to ${updatePermitResult.permitNumber}`,
|
||||||
|
"team",
|
||||||
|
input.assignedToOrg == "client"
|
||||||
|
? updatePermitResult.client.toString()
|
||||||
|
: process.env.SUNCOAST_ID,
|
||||||
|
updatePermitResult.pid,
|
||||||
|
"permits",
|
||||||
|
{
|
||||||
|
client: updatePermitResult.client.toString(),
|
||||||
|
county: updatePermitResult.county.id.toString(),
|
||||||
|
address: updatePermitResult.address.full_address,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,7 +436,7 @@ export async function updatePermit(
|
|||||||
orgId: updatePermitResult.client._id.toString(),
|
orgId: updatePermitResult.client._id.toString(),
|
||||||
document: updatePermitResult,
|
document: updatePermitResult,
|
||||||
} as ChangeEvent,
|
} as ChangeEvent,
|
||||||
["permit:read"]
|
["permit:read"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,7 +458,7 @@ export async function deletePermit(permitId: string, tenantId: string) {
|
|||||||
pid: permitId,
|
pid: permitId,
|
||||||
},
|
},
|
||||||
} as ChangeEvent,
|
} as ChangeEvent,
|
||||||
["permit:read"]
|
["permit:read"],
|
||||||
);
|
);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
@@ -431,7 +466,7 @@ export async function deletePermit(permitId: string, tenantId: string) {
|
|||||||
|
|
||||||
export async function searchPermit(
|
export async function searchPermit(
|
||||||
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;
|
||||||
@@ -629,7 +664,7 @@ export async function bulkImport(csvData: any[], user: AuthenticatedUser) {
|
|||||||
clientCache[clientName] = clientData;
|
clientCache[clientName] = clientData;
|
||||||
} else {
|
} else {
|
||||||
errors.push(
|
errors.push(
|
||||||
"Client not found. The value in Client column must exactly match the client name in Quicker Permits"
|
"Client not found. The value in Client column must exactly match the client name in Quicker Permits",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -650,7 +685,7 @@ export async function bulkImport(csvData: any[], user: AuthenticatedUser) {
|
|||||||
countyCache[countyName] = countyData;
|
countyCache[countyName] = countyData;
|
||||||
} else {
|
} else {
|
||||||
errors.push(
|
errors.push(
|
||||||
"County not found. The value in County column must exactly match the county name in Quicker Permits"
|
"County not found. The value in County column must exactly match the county name in Quicker Permits",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const processedSchema = new mongoose.Schema({
|
|||||||
pipeline: Array,
|
pipeline: Array,
|
||||||
currentStage: Number,
|
currentStage: Number,
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false },
|
||||||
),
|
),
|
||||||
status: String,
|
status: String,
|
||||||
manualStatus: String,
|
manualStatus: String,
|
||||||
@@ -41,6 +41,7 @@ const processedSchema = new mongoose.Schema({
|
|||||||
type: [Schema.Types.ObjectId],
|
type: [Schema.Types.ObjectId],
|
||||||
ref: "user",
|
ref: "user",
|
||||||
},
|
},
|
||||||
|
assignedToOrg: String,
|
||||||
link: String,
|
link: String,
|
||||||
address: Object,
|
address: Object,
|
||||||
recordType: String,
|
recordType: String,
|
||||||
@@ -113,13 +114,13 @@ const processedSchema = new mongoose.Schema({
|
|||||||
}).index({ tenantId: 1, permitNumber: 1 }, { unique: true });
|
}).index({ tenantId: 1, permitNumber: 1 }, { unique: true });
|
||||||
|
|
||||||
export const processedFields = Object.keys(processedSchema.paths).filter(
|
export const processedFields = Object.keys(processedSchema.paths).filter(
|
||||||
(path) => path !== "__v"
|
(path) => path !== "__v",
|
||||||
);
|
);
|
||||||
|
|
||||||
export const processedModel = mongoose.model(
|
export const processedModel = mongoose.model(
|
||||||
"processed",
|
"processed",
|
||||||
processedSchema,
|
processedSchema,
|
||||||
"processed"
|
"processed",
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateProcessedInput = z.object({
|
const updateProcessedInput = z.object({
|
||||||
@@ -133,6 +134,7 @@ const updateProcessedInput = z.object({
|
|||||||
jobNumber: z.string().nullable().optional(),
|
jobNumber: z.string().nullable().optional(),
|
||||||
startDate: z.date().nullable().optional(),
|
startDate: z.date().nullable().optional(),
|
||||||
assignedTo: z.array(z.string()).nullable().optional(),
|
assignedTo: z.array(z.string()).nullable().optional(),
|
||||||
|
assignedToOrg: z.enum(["client", "agent"]).nullable().optional(),
|
||||||
noc: z.string().optional(),
|
noc: z.string().optional(),
|
||||||
deed: z.string().optional(),
|
deed: z.string().optional(),
|
||||||
requests: z.array(z.string()).optional(),
|
requests: z.array(z.string()).optional(),
|
||||||
@@ -152,5 +154,5 @@ export const { schemas: processedSchemas, $ref: $processed } = buildJsonSchemas(
|
|||||||
pageQueryParams,
|
pageQueryParams,
|
||||||
updateProcessedInput,
|
updateProcessedInput,
|
||||||
},
|
},
|
||||||
{ $id: "processed" }
|
{ $id: "processed" },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { arrayDiff } from "../utils/diff";
|
|||||||
|
|
||||||
export async function getProcessedPermit(
|
export async function getProcessedPermit(
|
||||||
permitId: String,
|
permitId: String,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
const permit = await processedModel
|
const permit = await processedModel
|
||||||
.findOne({
|
.findOne({
|
||||||
@@ -41,11 +41,19 @@ export async function getProcessedPermit(
|
|||||||
export async function updateProcessed(
|
export async function updateProcessed(
|
||||||
input: UpdateProcessedInput,
|
input: UpdateProcessedInput,
|
||||||
permitId: string,
|
permitId: string,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
|
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(
|
||||||
{ pid: permitId },
|
{ pid: permitId },
|
||||||
{ assignedTo: 1 }
|
{ assignedTo: 1, assignedToOrg: 1 },
|
||||||
);
|
);
|
||||||
const updateProcessedResult = await processedModel
|
const updateProcessedResult = await processedModel
|
||||||
.findOneAndUpdate(
|
.findOneAndUpdate(
|
||||||
@@ -53,7 +61,7 @@ export async function updateProcessed(
|
|||||||
$and: [{ tenantId: user.tenantId }, { pid: permitId }],
|
$and: [{ tenantId: user.tenantId }, { pid: permitId }],
|
||||||
},
|
},
|
||||||
{ ...input, lastUpdateDate: new Date() },
|
{ ...input, lastUpdateDate: new Date() },
|
||||||
{ new: true }
|
{ new: true },
|
||||||
)
|
)
|
||||||
.populate({ path: "county", select: "pid name avatar" })
|
.populate({ path: "county", select: "pid name avatar" })
|
||||||
.populate({ path: "assignedTo", select: "pid name avatar" })
|
.populate({ path: "assignedTo", select: "pid name avatar" })
|
||||||
@@ -76,7 +84,7 @@ export async function updateProcessed(
|
|||||||
},
|
},
|
||||||
permitId,
|
permitId,
|
||||||
"processed",
|
"processed",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
} else if (key == "client") {
|
} else if (key == "client") {
|
||||||
const orgInDb = await orgModel.findById(input.client);
|
const orgInDb = await orgModel.findById(input.client);
|
||||||
@@ -97,13 +105,13 @@ export async function updateProcessed(
|
|||||||
},
|
},
|
||||||
permitId,
|
permitId,
|
||||||
"permits",
|
"permits",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (key == "assignedTo") {
|
} else if (key == "assignedTo") {
|
||||||
const newAssignees = arrayDiff(
|
const newAssignees = arrayDiff(
|
||||||
updateProcessedResult.assignedTo.map((item) => item._id),
|
updateProcessedResult.assignedTo.map((item) => item._id),
|
||||||
oldPermitResult.assignedTo
|
oldPermitResult.assignedTo,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newAssignees.length == 0) continue;
|
if (newAssignees.length == 0) continue;
|
||||||
@@ -127,7 +135,7 @@ export async function updateProcessed(
|
|||||||
client: updateProcessedResult.client.toString(),
|
client: updateProcessedResult.client.toString(),
|
||||||
county: updateProcessedResult.county.id.toString(),
|
county: updateProcessedResult.county.id.toString(),
|
||||||
address: updateProcessedResult.address.full_address,
|
address: updateProcessedResult.address.full_address,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +145,33 @@ export async function updateProcessed(
|
|||||||
},
|
},
|
||||||
permitId,
|
permitId,
|
||||||
"processed",
|
"processed",
|
||||||
user
|
user,
|
||||||
|
);
|
||||||
|
} else if (key == "assignedToOrg") {
|
||||||
|
if (
|
||||||
|
oldPermitResult.assignedToOrg == updateProcessedResult.assignedToOrg
|
||||||
|
)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const orgName =
|
||||||
|
input.assignedToOrg == "agent"
|
||||||
|
? "Suncoast"
|
||||||
|
: updateProcessedResult.clientData.name;
|
||||||
|
|
||||||
|
await createAlert(
|
||||||
|
user.tenantId,
|
||||||
|
`${orgName} assigned to ${updateProcessedResult.permitNumber}`,
|
||||||
|
"team",
|
||||||
|
input.assignedToOrg == "client"
|
||||||
|
? updateProcessedResult.client.toString()
|
||||||
|
: process.env.SUNCOAST_ID,
|
||||||
|
updateProcessedResult.pid,
|
||||||
|
"permits",
|
||||||
|
{
|
||||||
|
client: updateProcessedResult.client.toString(),
|
||||||
|
county: updateProcessedResult.county.id.toString(),
|
||||||
|
address: updateProcessedResult.address.full_address,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,7 +182,7 @@ export async function updateProcessed(
|
|||||||
|
|
||||||
export async function listProcessedPermits(
|
export async function listProcessedPermits(
|
||||||
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;
|
||||||
@@ -173,7 +207,7 @@ export async function listProcessedPermits(
|
|||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
@@ -281,7 +315,7 @@ export async function listProcessedPermits(
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const permitsList = await processedModel.aggregate(pipeline);
|
const permitsList = await processedModel.aggregate(pipeline);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const rtsSchema = new mongoose.Schema({
|
|||||||
ref: "user",
|
ref: "user",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false },
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
county: {
|
county: {
|
||||||
@@ -39,7 +39,7 @@ const rtsSchema = new mongoose.Schema({
|
|||||||
pipeline: Array,
|
pipeline: Array,
|
||||||
currentStage: Number,
|
currentStage: Number,
|
||||||
},
|
},
|
||||||
{ _id: false }
|
{ _id: false },
|
||||||
),
|
),
|
||||||
status: String,
|
status: String,
|
||||||
labels: [String],
|
labels: [String],
|
||||||
@@ -54,6 +54,7 @@ const rtsSchema = new mongoose.Schema({
|
|||||||
type: [Schema.Types.ObjectId],
|
type: [Schema.Types.ObjectId],
|
||||||
ref: "user",
|
ref: "user",
|
||||||
},
|
},
|
||||||
|
assignedToOrg: String,
|
||||||
taggedUsers: Array,
|
taggedUsers: Array,
|
||||||
fileValidationStatus: String,
|
fileValidationStatus: String,
|
||||||
permitNumber: [String],
|
permitNumber: [String],
|
||||||
@@ -61,7 +62,7 @@ const rtsSchema = new mongoose.Schema({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const rtsFields = Object.keys(rtsSchema.paths).filter(
|
export const rtsFields = Object.keys(rtsSchema.paths).filter(
|
||||||
(path) => path !== "__v"
|
(path) => path !== "__v",
|
||||||
);
|
);
|
||||||
|
|
||||||
export const rtsModel = mongoose.model("rts", rtsSchema, "rts");
|
export const rtsModel = mongoose.model("rts", rtsSchema, "rts");
|
||||||
@@ -82,12 +83,13 @@ const rtsCreateInput = z.object({
|
|||||||
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(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
assignedTo: z.array(z.string()).optional(),
|
assignedTo: z.array(z.string()).optional(),
|
||||||
|
assignedToOrg: z.enum(["client", "agent"]).nullable().optional(),
|
||||||
status: z.string().optional(),
|
status: z.string().optional(),
|
||||||
permitNumber: z.array(z.string()).optional(),
|
permitNumber: z.array(z.string()).optional(),
|
||||||
lot: z.array(z.string()).optional(),
|
lot: z.array(z.string()).optional(),
|
||||||
@@ -108,12 +110,13 @@ const rtsUpdateInput = z.object({
|
|||||||
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(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
assignedTo: z.array(z.string()).optional(),
|
assignedTo: z.array(z.string()).optional(),
|
||||||
|
assignedToOrg: z.enum(["client", "agent"]).nullable().optional(),
|
||||||
status: z.string().optional(),
|
status: z.string().optional(),
|
||||||
fileValidationStatus: z.string().optional(),
|
fileValidationStatus: z.string().optional(),
|
||||||
permitNumber: z.array(z.string()).optional(),
|
permitNumber: z.array(z.string()).optional(),
|
||||||
@@ -135,5 +138,5 @@ export const { schemas: rtsSchemas, $ref: $rts } = buildJsonSchemas(
|
|||||||
rtsNewUpload,
|
rtsNewUpload,
|
||||||
pageQueryParams,
|
pageQueryParams,
|
||||||
},
|
},
|
||||||
{ $id: "rts" }
|
{ $id: "rts" },
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ import { rtsPipeline } from "../utils/pipeline";
|
|||||||
import { createAlert } from "../alert/alert.service";
|
import { createAlert } from "../alert/alert.service";
|
||||||
import { createNote } from "../note/note.service";
|
import { createNote } from "../note/note.service";
|
||||||
import { arrayDiff } from "../utils/diff";
|
import { arrayDiff } from "../utils/diff";
|
||||||
|
import { getOrg } from "../organization/organization.service";
|
||||||
|
|
||||||
export async function createRts(
|
export async function createRts(
|
||||||
input: CreateRtsInput,
|
input: CreateRtsInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
let defaultClient = input.client;
|
let defaultClient = input.client;
|
||||||
const userInDb = await getUserWithoutPopulate(user.userId);
|
const userInDb = await getUserWithoutPopulate(user.userId);
|
||||||
@@ -75,7 +76,7 @@ export async function getRts(id: string, tenantId: string) {
|
|||||||
|
|
||||||
export async function listRts(
|
export async function listRts(
|
||||||
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;
|
||||||
@@ -100,7 +101,7 @@ export async function listRts(
|
|||||||
|
|
||||||
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter(
|
||||||
filterObj,
|
filterObj,
|
||||||
sortObj
|
sortObj,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1);
|
||||||
@@ -236,9 +237,21 @@ export async function listRts(
|
|||||||
export async function updateRts(
|
export async function updateRts(
|
||||||
id: string,
|
id: string,
|
||||||
input: UpdateRtsInput,
|
input: UpdateRtsInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
const oldRts = await rtsModel.findOne({ pid: id }, { assignedTo: 1 });
|
if (input.assignedToOrg && input.assignedTo) {
|
||||||
|
input.assignedTo = [];
|
||||||
|
} else if (input.assignedToOrg) {
|
||||||
|
input.assignedTo = [];
|
||||||
|
} else if (input.assignedTo) {
|
||||||
|
input.assignedToOrg = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldRts = await rtsModel.findOne(
|
||||||
|
{ pid: id },
|
||||||
|
{ assignedTo: 1, assignedToOrg: 1 },
|
||||||
|
);
|
||||||
|
|
||||||
const updatedRts = await rtsModel
|
const updatedRts = await rtsModel
|
||||||
.findOneAndUpdate({ pid: id, tenantId: user.tenantId }, input, {
|
.findOneAndUpdate({ pid: id, tenantId: user.tenantId }, input, {
|
||||||
new: true,
|
new: true,
|
||||||
@@ -253,14 +266,14 @@ export async function updateRts(
|
|||||||
{ content: `Updated type to '${input.permitType}'` },
|
{ content: `Updated type to '${input.permitType}'` },
|
||||||
id,
|
id,
|
||||||
"rts",
|
"rts",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updatedRts && input.assignedTo) {
|
if (updatedRts && input.assignedTo) {
|
||||||
const newAssignees = arrayDiff(
|
const newAssignees = arrayDiff(
|
||||||
updatedRts.assignedTo.map((item) => item._id),
|
updatedRts.assignedTo.map((item) => item._id),
|
||||||
oldRts.assignedTo
|
oldRts.assignedTo,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (newAssignees.length > 0) {
|
if (newAssignees.length > 0) {
|
||||||
@@ -285,7 +298,7 @@ export async function updateRts(
|
|||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
county: updatedRts.county._id.toString(),
|
county: updatedRts.county._id.toString(),
|
||||||
permitType: updatedRts.permitType,
|
permitType: updatedRts.permitType,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,11 +308,40 @@ export async function updateRts(
|
|||||||
},
|
},
|
||||||
id,
|
id,
|
||||||
"rts",
|
"rts",
|
||||||
user
|
user,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
updatedRts &&
|
||||||
|
input.assignedToOrg &&
|
||||||
|
oldRts.assignedToOrg != updatedRts.assignedToOrg
|
||||||
|
) {
|
||||||
|
const orgName =
|
||||||
|
//@ts-ignore
|
||||||
|
input.assignedToOrg == "agent" ? "Suncoast" : updatedRts.client.name;
|
||||||
|
|
||||||
|
await createAlert(
|
||||||
|
user.tenantId,
|
||||||
|
`${orgName} assigned to RTS`,
|
||||||
|
"team",
|
||||||
|
input.assignedToOrg == "client"
|
||||||
|
? //@ts-ignore
|
||||||
|
updatedRts.client._id.toString()
|
||||||
|
: process.env.SUNCOAST_ID,
|
||||||
|
updatedRts.pid,
|
||||||
|
"permits",
|
||||||
|
{
|
||||||
|
//@ts-ignore
|
||||||
|
client: updatedRts.client._id.toString(),
|
||||||
|
//@ts-ignore
|
||||||
|
county: updatedRts.county._id.toString(),
|
||||||
|
permitType: updatedRts.permitType,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return updatedRts;
|
return updatedRts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,7 +352,7 @@ export async function deleteRts(id: string, tenantId: string) {
|
|||||||
export async function newUpload(
|
export async function newUpload(
|
||||||
id: string,
|
id: string,
|
||||||
newUpload: UploadRtsInput,
|
newUpload: UploadRtsInput,
|
||||||
user: AuthenticatedUser
|
user: AuthenticatedUser,
|
||||||
) {
|
) {
|
||||||
return await rtsModel.findOneAndUpdate(
|
return await rtsModel.findOneAndUpdate(
|
||||||
{ pid: id, tenantId: user.tenantId },
|
{ pid: id, tenantId: user.tenantId },
|
||||||
@@ -322,6 +364,6 @@ export async function newUpload(
|
|||||||
createdBy: user.userId,
|
createdBy: user.userId,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user