add payments routes

This commit is contained in:
2025-06-09 16:45:05 +05:30
parent bec293193f
commit 6dea12bb45
8 changed files with 225 additions and 1 deletions

View File

@@ -0,0 +1,34 @@
import { FastifyReply, FastifyRequest } from "fastify";
import { getPayment, listPayments } from "./payments.service";
import { PageQueryParams } from "../pagination";
export async function getPaymentHandler(
req: FastifyRequest,
res: FastifyReply
) {
const { paymentId } = req.params as { paymentId: string };
try {
const payment = await getPayment(paymentId, req.user);
if (payment === null)
return res.code(404).send({ error: "resource not found" });
return res.code(200).send(payment);
} catch (err) {
return err;
}
}
export async function listPaymentHandler(
req: FastifyRequest,
res: FastifyReply
) {
const queryParams = req.query as PageQueryParams;
try {
const paymentList = await listPayments(queryParams, req.user);
return res.code(200).send(paymentList);
} catch (err) {
return err;
}
}

View File

@@ -0,0 +1,46 @@
import { FastifyInstance } from "fastify";
import { getPaymentHandler, listPaymentHandler } from "./payment.controller";
import { $payment } from "./payment.schema";
export async function paymentRoutes(fastify: FastifyInstance) {
fastify.get(
"/:paymentId",
{
schema: {
params: {
type: "object",
properties: {
paymentId: { type: "string" },
},
},
},
config: { requiredClaims: ["payment:read"] },
preHandler: [fastify.authorize],
},
getPaymentHandler
);
fastify.get(
"/",
{
schema: {
params: $payment("pageQueryParams"),
},
config: { requiredClaims: ["payment:read"] },
preHandler: [fastify.authorize],
},
listPaymentHandler
);
fastify.get(
"/search",
{
schema: {
params: $payment("pageQueryParams"),
},
config: { requiredClaims: ["payment:read"] },
preHandler: [fastify.authorize],
},
listPaymentHandler
);
}

View File

@@ -0,0 +1,43 @@
import { buildJsonSchemas } from "fastify-zod";
import mongoose from "mongoose";
import { pageQueryParams } from "../pagination";
const paymentSchema = new mongoose.Schema({
permitNumber: String,
recordId: String,
tenantId: {
type: String,
required: true,
},
pid: {
type: String,
unique: true,
},
permitPid: String,
county: Object,
client: {
type: mongoose.Types.ObjectId,
ref: "organization",
},
clientData: Object,
address: Object,
permitLink: String,
cardEnding: String,
totalPaid: Number,
receiptNo: String,
fileId: String,
paymentDate: Date,
});
export const paymentModel = mongoose.model("payment", paymentSchema);
export const paymentFields = Object.keys(paymentSchema.paths).filter(
(path) => path !== "__v"
);
export const { schemas: paymentSchemas, $ref: $payment } = buildJsonSchemas(
{
pageQueryParams,
},
{ $id: "payment" }
);

View File

@@ -0,0 +1,94 @@
import mongoose from "mongoose";
import { AuthenticatedUser } from "../auth";
import { getFilterObject, getSortObject, PageQueryParams } from "../pagination";
import { paymentFields, paymentModel } from "./payment.schema";
export async function getPayment(paymentId: string, user: AuthenticatedUser) {
const paymentObj = await paymentModel.findOne({
tenantId: user.tenantId,
pid: paymentId,
});
if (user.role === "client" && paymentObj.client.toString() !== user.orgId)
return null;
return paymentObj;
}
export async function listPayments(
params: PageQueryParams,
user: AuthenticatedUser
) {
const page = params.page || 1;
const pageSize = params.pageSize || 10;
const sortObj = getSortObject(params, paymentFields);
const filterObj = getFilterObject(params) || [];
if (user.role == "client") {
filterObj.push({ client: new mongoose.Types.ObjectId(user.orgId) });
}
const pipeline: Array<any> = [
{ $match: { $and: [{ tenantId: user.tenantId }, ...filterObj] } },
];
if (params.searchToken) {
const regex = new RegExp(params.searchToken, "i");
pipeline.push({
$match: {
$or: [
{ permitNumber: { $regex: regex } },
{ "address.full_address": { $regex: regex } },
],
},
});
}
pipeline.push(
{
$project: {
_id: 1,
permitNumber: 1,
recordId: 1,
tenantId: 1,
pid: 1,
permitPid: 1,
county: 1,
client: 1,
clientData: 1,
address: 1,
permitLink: 1,
cardEnding: 1,
totalPaid: 1,
receiptNo: 1,
fileId: 1,
paymentDate: 1,
},
},
{
$facet: {
metadata: [{ $count: "count" }],
data: [
{ $sort: sortObj },
{ $skip: (page - 1) * pageSize },
{ $limit: pageSize },
],
},
}
);
const paymentsList = await paymentModel.aggregate(pipeline);
if (paymentsList[0].data.length === 0)
return { permits: [], metadata: { count: 0, page, pageSize } };
return {
payments: paymentsList[0]?.data,
metadata: {
count: paymentsList[0].metadata[0].count,
page,
pageSize,
},
};
}

View File

@@ -14,6 +14,7 @@ import { mailProxyRoutes } from "./mailProxy/mailProxy.route";
import { viewRoutes } from "./view/view.route";
import { processedRoutes } from "./processed/processed.route";
import { ctaskRoutes } from "./ctask/ctask.route";
import { paymentRoutes } from "./payments/payment.route";
export default async function routes(fastify: FastifyInstance) {
fastify.addHook("preHandler", authHandler);
@@ -30,5 +31,6 @@ export default async function routes(fastify: FastifyInstance) {
fastify.register(configRoutes, { prefix: "/config" });
fastify.register(viewRoutes, { prefix: "/views" });
fastify.register(processedRoutes, { prefix: "/processed" });
fastify.register(paymentRoutes, { prefix: "/payments" });
fastify.register(realTimeRoutes);
}

View File

@@ -22,6 +22,7 @@ import { mailSchemas } from "./mailProxy/mailProxy.schema";
import { viewSchemas } from "./view/view.schema";
import { processedSchemas } from "./processed/processed.schema";
import { cTaskSchemas } from "./ctask/ctask.schema";
import { paymentSchemas } from "./payments/payment.schema";
const app = fastify({ logger: true, trustProxy: true });
@@ -57,6 +58,7 @@ for (const schema of [
...mailSchemas,
...viewSchemas,
...processedSchemas,
...paymentSchemas,
]) {
app.addSchema(schema);
}

View File

@@ -34,4 +34,5 @@ export type Claim =
| "view:delete"
| "note:read"
| "note:write"
| "note:delete";
| "note:delete"
| "payment:read";

View File

@@ -36,6 +36,7 @@ export const rules: Record<
"note:read",
"note:write",
"note:delete",
"payment:read",
],
hiddenFields: {
orgs: ["__v"],
@@ -73,6 +74,7 @@ export const rules: Record<
"note:read",
"note:write",
"note:delete",
"payment:read",
],
hiddenFields: {
orgs: ["__v"],