import { CreateRtsInput, rtsFields, rtsModel, UpdateRtsInput, UploadRtsInput, } from "./rts.schema"; import { AuthenticatedUser } from "../auth"; import { generateId } from "../utils/id"; import { getFilterObject, getSortObject, getTaggedUsersFilter, PageQueryParams, } from "../pagination"; import { getUser, getUserWithoutPopulate } from "../user/user.service"; import mongoose from "mongoose"; import { rtsPipeline } from "../utils/pipeline"; import { createAlert } from "../alert/alert.service"; import { createNote } from "../note/note.service"; import { arrayDiff } from "../utils/diff"; export async function createRts( input: CreateRtsInput, user: AuthenticatedUser ) { let defaultClient = input.client; const userInDb = await getUserWithoutPopulate(user.userId); if (userInDb && userInDb.orgId) { defaultClient = userInDb.orgId[0]?.toString(); } if (!input.stage) { input.stage = { pipeline: rtsPipeline, currentStage: 0, }; } const newRts = await rtsModel.create({ ...input, tenantId: user.tenantId, pid: generateId(), client: user.role == "client" ? defaultClient : input.client, createdAt: new Date(), createdBy: user.userId ?? null, fileValidationStatus: "pending", }); /* await createAlert( user.tenantId, `New Ready to Submit added`, "team", newRts.client?.toString(), newRts.pid, "rts" ); */ return rtsModel .findById(newRts.id) .populate({ path: "county", select: "pid name avatar" }) .populate({ path: "client", select: "pid name avatar" }) .populate({ path: "createdBy", select: "pid name avatar" }) .populate({ path: "assignedTo", select: "pid name avatar" }); } export async function getRts(id: string, tenantId: string) { return await rtsModel .findOne({ pid: id, tenantId: tenantId }) .populate({ path: "county", select: "pid name avatar" }) .populate({ path: "client", select: "pid name avatar" }) .populate({ path: "createdBy", select: "pid name avatar" }) .populate({ path: "assignedTo", select: "pid name avatar" }); } export async function listRts( params: PageQueryParams, user: AuthenticatedUser ) { const page = params.page || 1; const pageSize = params.pageSize || 10; const sortObj = getSortObject(params, rtsFields); let filterObj = getFilterObject(params) || []; if (user.role === "client") { filterObj.push({ client: { $in: user.orgId.map((item) => new mongoose.Types.ObjectId(item)), }, }); } if (user.counties && user.counties.length > 0) { filterObj.push({ county: { $in: user.counties.map((item) => new mongoose.Types.ObjectId(item)), }, }); } let { taggedFilter, taggedUserFilterIndex } = getTaggedUsersFilter( filterObj, sortObj ); if (taggedUserFilterIndex != -1) filterObj.splice(taggedUserFilterIndex, 1); const rtsList = await rtsModel.aggregate([ { $match: { $and: [{ tenantId: user.tenantId }, ...filterObj] }, }, ...taggedFilter, { $lookup: { from: "organizations", localField: "county", foreignField: "_id", as: "countyRec", }, }, { $lookup: { from: "organizations", localField: "client", foreignField: "_id", as: "clientRec", }, }, { $lookup: { from: "users", localField: "createdBy", foreignField: "_id", as: "createdRec", }, }, { $lookup: { from: "users", localField: "assignedTo", foreignField: "_id", as: "assignedTo", }, }, { $project: { _id: 1, pid: 1, permitType: 1, documents: 1, statusPipeline: 1, createdAt: 1, stage: 1, status: 1, labels: 1, priority: 1, dueDate: 1, taggedUsers: 1, fileValidationStatus: 1, permitNumber: 1, lot: 1, county: { $let: { vars: { county: { $arrayElemAt: ["$countyRec", 0] } }, in: { _id: "$$county._id", pid: "$$county.pid", name: "$$county.name", type: "$$county.type", avatar: "$$county.avatar", }, }, }, client: { $let: { vars: { client: { $arrayElemAt: ["$clientRec", 0] } }, in: { _id: "$$client._id", pid: "$$client.pid", name: "$$client.name", type: "$$client.type", avatar: "$$client.avatar", }, }, }, createdBy: { $let: { vars: { created: { $arrayElemAt: ["$createdRec", 0] } }, in: { _id: "$$created._id", pid: "$$created.pid", name: "$$created.name", avatar: "$$created.avatar", }, }, }, assignedTo: { $map: { input: "$assignedTo", as: "user", in: { _id: "$$user._id", pid: "$$user.pid", name: "$$user.name", avatar: "$$user.avatar", }, }, }, }, }, { $facet: { metadata: [{ $count: "count" }], data: [ { $sort: sortObj }, { $skip: (page - 1) * pageSize }, { $limit: pageSize }, ], }, }, ]); if (rtsList[0].data.length === 0) return { rts: [], metadata: { count: 0, page, pageSize } }; return { rts: rtsList[0]?.data, metadata: { count: rtsList[0].metadata[0].count, page, pageSize, }, }; } export async function updateRts( id: string, input: UpdateRtsInput, user: AuthenticatedUser ) { const oldRts = await rtsModel.findOne({ pid: id }, { assignedTo: 1 }); const updatedRts = await rtsModel .findOneAndUpdate({ pid: id, tenantId: user.tenantId }, input, { new: true, }) .populate({ path: "createdBy", select: "pid name avatar" }) .populate({ path: "county", select: "_id pid name avatar" }) .populate({ path: "client", select: "_id pid name avatar" }) .populate({ path: "assignedTo", select: "pid name avatar" }); if (updateRts && input.permitType) { await createNote( { content: `Updated type to '${input.permitType}'` }, id, "rts", user ); } if (updatedRts && input.assignedTo) { const newAssignees = arrayDiff( updatedRts.assignedTo.map((item) => item._id), oldRts.assignedTo ); if (newAssignees.length > 0) { let msg = "Assigned to:\n\n"; for (const assignee of newAssignees) { const user = await getUser(assignee); if (!user) continue; msg += `${user.firstName + " " + user.lastName}\n`; await createAlert( user.tenantId, `You are assigned to RTS`, "user", assignee, updatedRts.pid, "rts", { //@ts-ignore client: updatedRts.client._id.toString(), //@ts-ignore county: updatedRts.county._id.toString(), permitType: updatedRts.permitType, } ); } await createNote( { content: msg, }, id, "rts", user ); } } return updatedRts; } export async function deleteRts(id: string, tenantId: string) { return await rtsModel.deleteOne({ pid: id, tenantId: tenantId }); } export async function newUpload( id: string, newUpload: UploadRtsInput, user: AuthenticatedUser ) { return await rtsModel.findOneAndUpdate( { pid: id, tenantId: user.tenantId }, { $push: { documents: { files: newUpload.files, createdAt: new Date(), createdBy: user.userId, }, }, } ); }