diff --git a/src/payments/payment.controller.ts b/src/payments/payment.controller.ts index eacabcf..b72aabf 100644 --- a/src/payments/payment.controller.ts +++ b/src/payments/payment.controller.ts @@ -1,6 +1,7 @@ import { FastifyReply, FastifyRequest } from "fastify"; -import { getPayment, listPayments } from "./payments.service"; +import { getPayment, listPayments, updatePayment } from "./payments.service"; import { PageQueryParams } from "../pagination"; +import { UpdatePaymentInput } from "./payment.schema"; export async function getPaymentHandler( req: FastifyRequest, @@ -32,3 +33,23 @@ export async function listPaymentHandler( return err; } } + +export async function updatePaymentHandler( + req: FastifyRequest, + res: FastifyReply +) { + const { paymentId } = req.params as { paymentId: string }; + const input = req.body as UpdatePaymentInput; + + console.log(input); + + try { + const updatedPayment = await updatePayment(paymentId, input, req.user); + if (!updatedPayment) + return res.code(404).send({ error: "resource not found" }); + + return res.code(200).send(updatedPayment); + } catch (err) { + return err; + } +} diff --git a/src/payments/payment.route.ts b/src/payments/payment.route.ts index ca77e26..a5222e4 100644 --- a/src/payments/payment.route.ts +++ b/src/payments/payment.route.ts @@ -1,5 +1,9 @@ import { FastifyInstance } from "fastify"; -import { getPaymentHandler, listPaymentHandler } from "./payment.controller"; +import { + getPaymentHandler, + listPaymentHandler, + updatePaymentHandler, +} from "./payment.controller"; import { $payment } from "./payment.schema"; import { getUniqueFields } from "../unique"; import { noteRoutes } from "../note/note.route"; @@ -34,6 +38,24 @@ export async function paymentRoutes(fastify: FastifyInstance) { listPaymentHandler ); + fastify.patch( + "/:paymentId", + { + schema: { + params: { + type: "object", + properties: { + paymentId: { type: "string" }, + }, + }, + body: $payment("updatePaymentInput"), + }, + config: { requiredClaims: ["payment:write"] }, + preHandler: [fastify.authorize], + }, + updatePaymentHandler + ); + fastify.get( "/search", { diff --git a/src/payments/payment.schema.ts b/src/payments/payment.schema.ts index 741daf6..bcb043e 100644 --- a/src/payments/payment.schema.ts +++ b/src/payments/payment.schema.ts @@ -1,6 +1,7 @@ import { buildJsonSchemas } from "fastify-zod"; import mongoose, { Schema } from "mongoose"; import { pageQueryParams } from "../pagination"; +import { z } from "zod"; const paymentSchema = new mongoose.Schema({ permitNumber: String, @@ -39,8 +40,15 @@ export const paymentFields = Object.keys(paymentSchema.paths).filter( (path) => path !== "__v" ); +const updatePaymentInput = z.object({ + assignedTo: z.array(z.string()).nullable().optional(), +}); + +export type UpdatePaymentInput = z.infer; + export const { schemas: paymentSchemas, $ref: $payment } = buildJsonSchemas( { + updatePaymentInput, pageQueryParams, }, { $id: "payment" } diff --git a/src/payments/payments.service.ts b/src/payments/payments.service.ts index a4f87b4..87a2704 100644 --- a/src/payments/payments.service.ts +++ b/src/payments/payments.service.ts @@ -1,7 +1,13 @@ import mongoose from "mongoose"; import { AuthenticatedUser } from "../auth"; import { getFilterObject, getSortObject, PageQueryParams } from "../pagination"; -import { paymentFields, paymentModel } from "./payment.schema"; +import { + paymentFields, + paymentModel, + UpdatePaymentInput, +} from "./payment.schema"; +import { arrayDiff } from "../utils/diff"; +import { createAlert } from "../alert/alert.service"; export async function getPayment(paymentId: string, user: AuthenticatedUser) { const paymentObj = await paymentModel.findOne({ @@ -121,3 +127,42 @@ export async function listPayments( }, }; } + +export async function updatePayment( + paymentId: string, + input: UpdatePaymentInput, + user: AuthenticatedUser +) { + const oldPayment = await paymentModel.findOne({ pid: paymentId }); + const updatedPayment = await paymentModel + .findOneAndUpdate( + { tenantId: user.tenantId, pid: paymentId }, + { ...input }, + { new: true } + ) + .populate({ path: "assignedTo", select: "pid name avatar" }); + + if (updatedPayment && input.assignedTo) { + const newAssignees = arrayDiff( + updatedPayment.assignedTo.map((item) => item._id), + oldPayment.assignedTo + ); + + if (newAssignees.length > 0) { + for (const assignee of newAssignees) { + if (assignee == user.userId) continue; + + await createAlert( + user.tenantId, + `You are assigned to ${updatedPayment.permitNumber}`, + "user", + assignee, + updatedPayment.pid, + "tasks" + ); + } + } + } + + return updatedPayment; +} diff --git a/src/utils/claims.ts b/src/utils/claims.ts index 293224d..f409be2 100644 --- a/src/utils/claims.ts +++ b/src/utils/claims.ts @@ -38,6 +38,7 @@ export type Claim = | "note:write" | "note:delete" | "payment:read" + | "payment:write" | "alert:read" | "alert:write" | "analytics:read"; diff --git a/src/utils/roles.ts b/src/utils/roles.ts index 42f1be6..75ff25e 100644 --- a/src/utils/roles.ts +++ b/src/utils/roles.ts @@ -39,6 +39,7 @@ export const rules: Record< "note:write", "note:delete", "payment:read", + "payment:write", "alert:read", "alert:write", "analytics:read", @@ -82,6 +83,7 @@ export const rules: Record< "note:write", "note:delete", "payment:read", + "payment:write", "alert:read", "alert:write", "analytics:read", @@ -119,6 +121,7 @@ export const rules: Record< "note:write", "note:delete", "payment:read", + "payment:write", "alert:read", "alert:write", "analytics:read", @@ -153,6 +156,7 @@ export const rules: Record< "note:read", "note:write", "payment:read", + "payment:write", "alert:read", "alert:write", "userConfig:read",