feat(stats): seller stat api completed

This commit is contained in:
rahat0078
2026-04-29 20:18:49 +06:00
parent 86b2292272
commit 7d89f3f4ea
7 changed files with 424 additions and 0 deletions
@@ -0,0 +1,92 @@
import manageResponse from "../../utils/manage_response";
import { Request, Response } from "express";
import catchAsync from "../../utils/catch_async";
import { statictics_service } from "./statictics.service";
const get_seller_stats = catchAsync(async (req: Request, res: Response) => {
const shopAccountId = req.user?.accountId;
if (!shopAccountId) {
return res.status(401).json({
success: false,
message: "Unauthorized",
});
}
const range = (req.query.range as "7d" | "30d" | "all") || "7d";
const result = await statictics_service.get_seller_stats_fromDb(
shopAccountId,
range,
);
manageResponse(res, {
success: true,
statusCode: 200,
message: "All statictics fetched successfully.",
data: result,
meta: {},
});
});
// const get_all_statictics = catchAsync(async (req, res) => {
// const result = await statictics_service.get_all_statictics_from_db(req);
// manageResponse(res, {
// success: true,
// statusCode: 200,
// message: "All statictics fetched successfully.",
// data: result,
// meta: {},
// });
// });
// const get_single_statictics = catchAsync(async (req, res) => {
// const result = await statictics_service.get_single_statictics_from_db(req);
// manageResponse(res, {
// success: true,
// statusCode: 200,
// message: "Single statictics fetched successfully.",
// data: result,
// meta: {},
// });
// });
// const create_statictics = catchAsync(async (req, res) => {
// const result = await statictics_service.create_statictics_into_db(req);
// manageResponse(res, {
// success: true,
// statusCode: 200,
// message: "statictics created successfully.",
// data: result,
// meta: {},
// });
// });
// const update_statictics = catchAsync(async (req, res) => {
// const result = await statictics_service.update_statictics_into_db(req);
// manageResponse(res, {
// success: true,
// statusCode: 200,
// message: "statictics updated successfully.",
// data: result,
// meta: {},
// });
// });
// const delete_statictics = catchAsync(async (req, res) => {
// const result = await statictics_service.delete_statictics_from_db(req);
// manageResponse(res, {
// success: true,
// statusCode: 200,
// message: "statictics deleted successfully.",
// data: result,
// meta: {},
// });
// });
export const statictics_controller = {
get_seller_stats,
// get_all_statictics,
// get_single_statictics,
// create_statictics,
// update_statictics,
// delete_statictics,
};
@@ -0,0 +1,26 @@
import { Router } from "express";
import auth from "../../middlewares/auth";
import { statictics_controller } from "./statictics.controller";
import RequestValidator from "../../middlewares/request_validator";
// import { statictics_controller } from "./statictics.controller";
// import { statictics_validations } from "./statictics.validation";
const router = Router();
router.get("/seller", auth("USER"), statictics_controller.get_seller_stats)
// router.post(
// "/",
// RequestValidator(statictics_validations.create_statictics),
// statictics_controller.create_statictics,
// );
// router.get("/:id", statictics_controller.get_single_statictics);
// router.patch(
// "/:id",
// RequestValidator(statictics_validations.update_statictics),
// statictics_controller.update_statictics,
// );
// router.delete("/:id", statictics_controller.delete_statictics);
export default router;
@@ -0,0 +1,151 @@
// import { Request } from "express";
// import { prisma } from "../../lib/prisma";
import { prisma } from "../../lib/prisma";
type Range = "7d" | "30d" | "all";
const get_seller_stats_fromDb = async (shopAccountId: string, range: Range) => {
let createdAtFilter: any = {};
if (range !== "all") {
const days = range === "7d" ? 7 : 30;
const from = new Date();
from.setDate(from.getDate() - days);
createdAtFilter = { gte: from };
}
const baseWhere: any = {
shopAccountId,
...(range !== "all" && { createdAt: createdAtFilter }),
};
const [
totalOrders,
completedOrders,
pendingOrders,
rejectedOrders,
revenueResult,
last7DaysRejected,
ordersForChart,
] = await Promise.all([
prisma.order.count({ where: baseWhere }),
prisma.order.count({
where: { ...baseWhere, status: "DELIVERED" },
}),
prisma.order.count({
where: {
...baseWhere,
status: { in: ["INITIATED", "CONFIRMED", "ONGOING"] },
},
}),
prisma.order.count({
where: { ...baseWhere, status: "CANCELLED" },
}),
prisma.order.aggregate({
where: { ...baseWhere, status: "DELIVERED" },
_sum: { productPrice: true },
}),
prisma.order.count({
where: {
shopAccountId,
status: "CANCELLED",
createdAt: {
gte: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
},
},
}),
range !== "all"
? prisma.order.findMany({
where: {
shopAccountId,
status: "DELIVERED",
createdAt: createdAtFilter,
},
select: {
productPrice: true,
createdAt: true,
},
})
: Promise.resolve([]),
]);
const totalRevenue = revenueResult._sum.productPrice || 0;
const avgOrderValue =
completedOrders > 0 ? totalRevenue / completedOrders : 0;
const dailyMap: Record<string, number> = {};
for (const o of ordersForChart) {
const date = o.createdAt.toISOString().split("T")[0];
if (!dailyMap[date]) dailyMap[date] = 0;
dailyMap[date] += o.productPrice;
}
const dailyRevenue = Object.entries(dailyMap).map(([date, revenue]) => ({
date,
revenue,
}));
return {
totalOrders,
completedOrders,
pendingOrders,
rejectedOrders,
totalRevenue,
avgOrderValue,
last7DaysRejected,
dailyRevenue,
};
};
// const get_all_statictics_from_db = async (req: Request) => {
// // define your own login here
// const result = await prisma.statictics.findMany();
// return result;
// };
// const get_single_statictics_from_db = async (req: Request) => {
// // define your own login here
// const { id } = req.params;
// const result = await prisma.statictics.findUnique({where:{id}});
// return result;
// };
// const create_statictics_into_db = async (req: Request) => {
// // define your own login here
// const result = await prisma.statictics.create({data:req.body});
// return result;
// };
// const update_statictics_into_db = async (req: Request) => {
// // define your own login here
// const { id } = req.params;
// const result = await prisma.statictics.update({where:{id},data:req.body});
// return result;
// };
// const delete_statictics_from_db = async (req: Request) => {
// // define your own login here
// const { id } = req.params;
// const result = await prisma.statictics.delete({where:{id}});
// return result;
// };
export const statictics_service = {
get_seller_stats_fromDb,
// get_all_statictics_from_db,
// get_single_statictics_from_db,
// create_statictics_into_db,
// update_statictics_into_db,
// delete_statictics_from_db,
};
@@ -0,0 +1,141 @@
export const staticticsSwaggerDocs = {
"/api/statictics": {
post: {
tags: ["statictics"],
summary: "Create new statictics",
description: "",
requestBody: {
required: true,
content: {
"application/json": {
example: JSON.stringify({}), // put your request body
},
},
},
responses: {
201: { description: "statictics created successfully" },
500: { description: "Validation error or internal server error" },
},
},
get: {
tags: ["statictics"],
summary: "Get all statictics",
description: "",
parameters: [
{
name: "page",
in: "query",
required: false,
schema: { type: "number" },
},
{
name: "limit",
in: "query",
required: false,
schema: { type: "number" },
},
],
responses: {
200: { description: "statictics fetched successfully" },
401: { description: "unauthorized" },
},
},
},
"/api/statictics/seller": {
get: {
tags: ["statistics"],
summary: "Get seller statistics",
description: "Fetch seller dashboard stats (7d, 30d, all)",
parameters: [
{
name: "range",
in: "query",
required: false,
schema: {
type: "string",
enum: ["7d", "30d", "all"],
default: "7d",
},
description: "Time range for statistics",
},
],
responses: {
200: {
description: "Statistics fetched successfully",
},
401: {
description: "Unauthorized",
},
},
},
},
"/api/statictics/{id}": {
get: {
tags: ["statictics"],
summary: "Get single statictics",
description: "",
parameters: [
{
name: "id",
in: "path",
required: true,
schema: { type: "string" },
},
],
responses: {
200: { description: "statictics fetched successfully" },
401: { description: "unauthorized" },
},
},
patch: {
tags: ["statictics"],
summary: "Update statictics",
description: "",
parameters: [
{
name: "id",
in: "path",
required: true,
schema: { type: "string" },
},
],
requestBody: {
required: true,
content: {
"application/json": {
example: JSON.stringify({}), // put your request body
},
},
},
responses: {
200: { description: "statictics updated successfully" },
500: { description: "Validation error or internal server error" },
},
},
delete: {
tags: ["statictics"],
summary: "Delete statictics",
description: "",
parameters: [
{
name: "id",
in: "path",
required: true,
schema: { type: "string" },
},
],
responses: {
200: { description: "statictics delete successfully" },
401: { description: "unauthorized" },
},
},
},
};
@@ -0,0 +1,10 @@
import { z } from "zod";
const create_statictics = z.object({});
const update_statictics = z.object({});
export const statictics_validations = {
create_statictics,
update_statictics,
};