♻️ refactor(account, order, plan, profile, support, email): restructure application modules and enhance error handling
Updated Docker configuration, refactored middleware for improved error handling, and restructured account, order, plan, profile, and support modules, including their routes, services, and validations. Enhanced email processing queues and utilities for token generation, pagination, and response management to streamline the application architecture and enhance maintainability.
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
import catchAsync from "../../utils/catch_async.js";
|
||||
import manageResponse from "../../utils/manage_response.js";
|
||||
import { order_service } from "./order.service.js";
|
||||
const get_all_order = catchAsync(async (req, res) => {
|
||||
const result = await order_service.get_all_order_from_db(req);
|
||||
manageResponse(res, {
|
||||
success: true,
|
||||
statusCode: 200,
|
||||
message: "All order fetched successfully.",
|
||||
data: result,
|
||||
meta: {},
|
||||
});
|
||||
});
|
||||
const get_single_order = catchAsync(async (req, res) => {
|
||||
const result = await order_service.get_single_order_from_db(req);
|
||||
manageResponse(res, {
|
||||
success: true,
|
||||
statusCode: 200,
|
||||
message: "Single order fetched successfully.",
|
||||
data: result,
|
||||
meta: {},
|
||||
});
|
||||
});
|
||||
const create_order = catchAsync(async (req, res) => {
|
||||
const result = await order_service.create_order_into_db(req);
|
||||
manageResponse(res, {
|
||||
success: true,
|
||||
statusCode: 200,
|
||||
message: "order created successfully.",
|
||||
data: result,
|
||||
meta: {},
|
||||
});
|
||||
});
|
||||
const update_order = catchAsync(async (req, res) => {
|
||||
const result = await order_service.update_order_into_db(req);
|
||||
manageResponse(res, {
|
||||
success: true,
|
||||
statusCode: 200,
|
||||
message: "order updated successfully.",
|
||||
data: result,
|
||||
meta: {},
|
||||
});
|
||||
});
|
||||
const delete_order = catchAsync(async (req, res) => {
|
||||
const result = await order_service.delete_order_from_db(req);
|
||||
manageResponse(res, {
|
||||
success: true,
|
||||
statusCode: 200,
|
||||
message: "order deleted successfully.",
|
||||
data: result,
|
||||
meta: {},
|
||||
});
|
||||
});
|
||||
export const order_controller = {
|
||||
get_all_order,
|
||||
get_single_order,
|
||||
create_order,
|
||||
update_order,
|
||||
delete_order,
|
||||
};
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { Router } from "express";
|
||||
import RequestValidator from "../../middlewares/request_validator.js";
|
||||
import { order_controller } from "./order.controller.js";
|
||||
import { order_validations } from "./order.validation.js";
|
||||
import auth from "../../middlewares/auth.js";
|
||||
const router = Router();
|
||||
router.get("/", order_controller.get_all_order);
|
||||
router.post("/", RequestValidator(order_validations.create_order), order_controller.create_order);
|
||||
router.get("/:id", order_controller.get_single_order);
|
||||
router.patch("/:id", auth("ADMIN"), RequestValidator(order_validations.update_order), order_controller.update_order);
|
||||
router.delete("/:id", order_controller.delete_order);
|
||||
export default router;
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
import { configs } from "../../configs/index.js";
|
||||
import { prisma } from "../../lib/prisma.js";
|
||||
import { orderEmailQueue } from "../../queues/email/order/order.email.queue.js";
|
||||
import { AppError } from "../../utils/app_error.js";
|
||||
import paginationHelper from "../../utils/pagination_helper.js";
|
||||
const get_all_order_from_db = async (req) => {
|
||||
// define your own login here
|
||||
const search = req.query.search;
|
||||
const customerName = req.query.customerName;
|
||||
const productName = req.query.productName;
|
||||
// for date filter
|
||||
const startDate = req.query.startDate;
|
||||
const endDate = req.query.endDate;
|
||||
const status = req.query.status || undefined;
|
||||
const { page, limit, skip, sortBy, sortOrder } = paginationHelper(req.query);
|
||||
const andCondition = [];
|
||||
if (search) {
|
||||
andCondition.push({
|
||||
OR: [
|
||||
{
|
||||
productName: {
|
||||
contains: search,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (customerName) {
|
||||
andCondition.push({
|
||||
OR: [
|
||||
{
|
||||
customerName: {
|
||||
contains: customerName,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (productName) {
|
||||
andCondition.push({
|
||||
OR: [
|
||||
{
|
||||
productName: {
|
||||
contains: productName,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
if (status) {
|
||||
andCondition.push({
|
||||
OR: [
|
||||
{
|
||||
status: {
|
||||
contains: status,
|
||||
mode: "insensitive",
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
// for date filter
|
||||
const dateFilter = {};
|
||||
if (startDate) {
|
||||
const start = new Date(startDate);
|
||||
start.setHours(0, 0, 0, 0);
|
||||
dateFilter.gte = start;
|
||||
}
|
||||
if (endDate) {
|
||||
const end = new Date(endDate);
|
||||
end.setHours(23, 59, 59, 999);
|
||||
dateFilter.lte = end;
|
||||
}
|
||||
if (Object.keys(dateFilter).length > 0) {
|
||||
andCondition.push({
|
||||
createdAt: dateFilter,
|
||||
});
|
||||
}
|
||||
const getAllOrders = await prisma.order.findMany({
|
||||
take: limit,
|
||||
skip,
|
||||
where: {
|
||||
AND: andCondition,
|
||||
},
|
||||
orderBy: {
|
||||
[sortBy]: sortOrder,
|
||||
},
|
||||
});
|
||||
const result = await prisma.order.count({
|
||||
where: {
|
||||
AND: andCondition,
|
||||
},
|
||||
});
|
||||
return {
|
||||
data: getAllOrders,
|
||||
pagination: {
|
||||
total: result,
|
||||
page,
|
||||
limit,
|
||||
totalPages: Math.ceil(result / limit),
|
||||
},
|
||||
};
|
||||
};
|
||||
const get_single_order_from_db = async (req) => {
|
||||
// define your own login here
|
||||
const { id } = req.params;
|
||||
const result = await prisma.order.findUnique({ where: { id } });
|
||||
return result;
|
||||
};
|
||||
const create_order_into_db = async (req) => {
|
||||
const payload = req?.body;
|
||||
console.log(payload);
|
||||
payload.status = "INITIATED";
|
||||
payload.paymentType = "COD";
|
||||
// nwo init order
|
||||
const result = await prisma.order.create({ data: payload });
|
||||
// if email exist sent tracking link
|
||||
if (payload.customerEmail) {
|
||||
const trackingLink = `${configs.jwt.front_end_url}/track-order/${result.id}`;
|
||||
await orderEmailQueue.add("order-email-queue", {
|
||||
email: payload.customerEmail,
|
||||
subject: "Order Tracking",
|
||||
textBody: `Your order has been created. Track your order here: ${trackingLink}`,
|
||||
htmlBody: `<p>Your order has been created. Track your order here: <a href="${trackingLink}">Track Order</a></p>`,
|
||||
});
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const update_order_into_db = async (req) => {
|
||||
// define your own login here
|
||||
const user = req.user;
|
||||
console.log(user);
|
||||
if (user?.role !== "ADMIN") {
|
||||
throw new AppError("You are not authorized to perform this action", 403);
|
||||
}
|
||||
const { id } = req.params;
|
||||
const isProductExist = await prisma.order.findUnique({ where: { id } });
|
||||
if (!isProductExist) {
|
||||
throw new AppError("Order is not found", 404);
|
||||
}
|
||||
const result = await prisma.order.update({ where: { id }, data: req.body });
|
||||
return result;
|
||||
};
|
||||
const delete_order_from_db = async (req) => {
|
||||
// define your own login here
|
||||
const { id } = req.params;
|
||||
const result = await prisma.order.delete({ where: { id } });
|
||||
return result;
|
||||
};
|
||||
export const order_service = {
|
||||
get_all_order_from_db,
|
||||
get_single_order_from_db,
|
||||
create_order_into_db,
|
||||
update_order_into_db,
|
||||
delete_order_from_db,
|
||||
};
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
export const orderSwaggerDocs = {
|
||||
"/api/order": {
|
||||
post: {
|
||||
tags: ["order"],
|
||||
summary: "Create new order",
|
||||
description: "",
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
example: JSON.stringify({
|
||||
shopAccountId: "",
|
||||
productPrice: 1500,
|
||||
productQuantity: 2,
|
||||
productName: "Wireless Mouse",
|
||||
customerName: "Rahim Uddin",
|
||||
customerPhone: "+8801712345678",
|
||||
customerEmail: "softvence.abumahid@gmail.com",
|
||||
customerAddress: "Rangpur, Bangladesh",
|
||||
customerNote: "Please deliver between 3-5 PM",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
201: { description: "order created successfully" },
|
||||
500: { description: "Validation error or internal server error" },
|
||||
},
|
||||
},
|
||||
get: {
|
||||
tags: ["order"],
|
||||
summary: "Get all order",
|
||||
description: "",
|
||||
parameters: [
|
||||
{
|
||||
name: "page",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "number" },
|
||||
},
|
||||
{
|
||||
name: "limit",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "number" },
|
||||
},
|
||||
{
|
||||
name: "search",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
{
|
||||
name: "customerName",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
{
|
||||
name: "productName",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
{
|
||||
name: "status",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
{
|
||||
name: "date",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
{
|
||||
name: "startDate",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "string", format: "date" },
|
||||
example: "2026-04-01",
|
||||
},
|
||||
{
|
||||
name: "endDate",
|
||||
in: "query",
|
||||
required: false,
|
||||
schema: { type: "string", format: "date" },
|
||||
example: "2026-04-31",
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
200: { description: "order fetched successfully" },
|
||||
401: { description: "unauthorized" },
|
||||
},
|
||||
},
|
||||
},
|
||||
"/api/order/{id}": {
|
||||
get: {
|
||||
tags: ["order"],
|
||||
summary: "Get single order",
|
||||
description: "",
|
||||
parameters: [
|
||||
{
|
||||
name: "id",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
200: { description: "order fetched successfully" },
|
||||
401: { description: "unauthorized" },
|
||||
},
|
||||
},
|
||||
patch: {
|
||||
tags: ["order"],
|
||||
summary: "Update order",
|
||||
description: "",
|
||||
parameters: [
|
||||
{
|
||||
name: "id",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
],
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
example: JSON.stringify({
|
||||
status: "INITIATED",
|
||||
}), // put your request body
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: { description: "order updated successfully" },
|
||||
500: { description: "Validation error or internal server error" },
|
||||
},
|
||||
},
|
||||
delete: {
|
||||
tags: ["order"],
|
||||
summary: "Delete order",
|
||||
description: "",
|
||||
parameters: [
|
||||
{
|
||||
name: "id",
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: { type: "string" },
|
||||
},
|
||||
],
|
||||
responses: {
|
||||
200: { description: "order delete successfully" },
|
||||
401: { description: "unauthorized" },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { z } from "zod";
|
||||
const create_order = z.object({
|
||||
shopAccountId: z.string(),
|
||||
productPrice: z.number(),
|
||||
productQuantity: z.number(),
|
||||
productName: z.string(),
|
||||
customerName: z.string(),
|
||||
customerPhone: z.string(),
|
||||
customerEmail: z.string().optional(),
|
||||
customerAddress: z.string(),
|
||||
customerNote: z.string().optional()
|
||||
});
|
||||
const update_order = z.object({
|
||||
status: z.string().optional()
|
||||
});
|
||||
export const order_validations = {
|
||||
create_order,
|
||||
update_order,
|
||||
};
|
||||
Reference in New Issue
Block a user