add payments routes
This commit is contained in:
34
src/payments/payment.controller.ts
Normal file
34
src/payments/payment.controller.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/payments/payment.route.ts
Normal file
46
src/payments/payment.route.ts
Normal 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
|
||||||
|
);
|
||||||
|
}
|
||||||
43
src/payments/payment.schema.ts
Normal file
43
src/payments/payment.schema.ts
Normal 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" }
|
||||||
|
);
|
||||||
94
src/payments/payments.service.ts
Normal file
94
src/payments/payments.service.ts
Normal 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,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -14,6 +14,7 @@ import { mailProxyRoutes } from "./mailProxy/mailProxy.route";
|
|||||||
import { viewRoutes } from "./view/view.route";
|
import { viewRoutes } from "./view/view.route";
|
||||||
import { processedRoutes } from "./processed/processed.route";
|
import { processedRoutes } from "./processed/processed.route";
|
||||||
import { ctaskRoutes } from "./ctask/ctask.route";
|
import { ctaskRoutes } from "./ctask/ctask.route";
|
||||||
|
import { paymentRoutes } from "./payments/payment.route";
|
||||||
|
|
||||||
export default async function routes(fastify: FastifyInstance) {
|
export default async function routes(fastify: FastifyInstance) {
|
||||||
fastify.addHook("preHandler", authHandler);
|
fastify.addHook("preHandler", authHandler);
|
||||||
@@ -30,5 +31,6 @@ export default async function routes(fastify: FastifyInstance) {
|
|||||||
fastify.register(configRoutes, { prefix: "/config" });
|
fastify.register(configRoutes, { prefix: "/config" });
|
||||||
fastify.register(viewRoutes, { prefix: "/views" });
|
fastify.register(viewRoutes, { prefix: "/views" });
|
||||||
fastify.register(processedRoutes, { prefix: "/processed" });
|
fastify.register(processedRoutes, { prefix: "/processed" });
|
||||||
|
fastify.register(paymentRoutes, { prefix: "/payments" });
|
||||||
fastify.register(realTimeRoutes);
|
fastify.register(realTimeRoutes);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { mailSchemas } from "./mailProxy/mailProxy.schema";
|
|||||||
import { viewSchemas } from "./view/view.schema";
|
import { viewSchemas } from "./view/view.schema";
|
||||||
import { processedSchemas } from "./processed/processed.schema";
|
import { processedSchemas } from "./processed/processed.schema";
|
||||||
import { cTaskSchemas } from "./ctask/ctask.schema";
|
import { cTaskSchemas } from "./ctask/ctask.schema";
|
||||||
|
import { paymentSchemas } from "./payments/payment.schema";
|
||||||
|
|
||||||
const app = fastify({ logger: true, trustProxy: true });
|
const app = fastify({ logger: true, trustProxy: true });
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ for (const schema of [
|
|||||||
...mailSchemas,
|
...mailSchemas,
|
||||||
...viewSchemas,
|
...viewSchemas,
|
||||||
...processedSchemas,
|
...processedSchemas,
|
||||||
|
...paymentSchemas,
|
||||||
]) {
|
]) {
|
||||||
app.addSchema(schema);
|
app.addSchema(schema);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,4 +34,5 @@ export type Claim =
|
|||||||
| "view:delete"
|
| "view:delete"
|
||||||
| "note:read"
|
| "note:read"
|
||||||
| "note:write"
|
| "note:write"
|
||||||
| "note:delete";
|
| "note:delete"
|
||||||
|
| "payment:read";
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export const rules: Record<
|
|||||||
"note:read",
|
"note:read",
|
||||||
"note:write",
|
"note:write",
|
||||||
"note:delete",
|
"note:delete",
|
||||||
|
"payment:read",
|
||||||
],
|
],
|
||||||
hiddenFields: {
|
hiddenFields: {
|
||||||
orgs: ["__v"],
|
orgs: ["__v"],
|
||||||
@@ -73,6 +74,7 @@ export const rules: Record<
|
|||||||
"note:read",
|
"note:read",
|
||||||
"note:write",
|
"note:write",
|
||||||
"note:delete",
|
"note:delete",
|
||||||
|
"payment:read",
|
||||||
],
|
],
|
||||||
hiddenFields: {
|
hiddenFields: {
|
||||||
orgs: ["__v"],
|
orgs: ["__v"],
|
||||||
|
|||||||
Reference in New Issue
Block a user