Skip to content

Commit

Permalink
Merge pull request #100 from atlp-rwanda/ft-Seller-Stats-#187419165
Browse files Browse the repository at this point in the history
added seller statistic feature
  • Loading branch information
teerenzo authored Jul 31, 2024
2 parents ba8fd4e + 7d054ed commit d8f01d8
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 1 deletion.
21 changes: 21 additions & 0 deletions src/controllers/statsController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Request, Response } from 'express';
import { StatisticsService } from '../services/stats.service';
// import { StatisticsService } from './statisticsService';

export async function getYearlyStats(req:Request, res:Response) {
const sellerId = (req as any).user.id;
const now = new Date();
const startOfYear = new Date(now.getFullYear(), now.getMonth() - 11, 1);

const stats = [];

for (let month = startOfYear; month <= now; month.setMonth(month.getMonth() + 1)) {
const startOfMonth = new Date(month.getFullYear(), month.getMonth(), 1);
const endOfMonth = new Date(month.getFullYear(), month.getMonth() + 1, 0);

const monthlyStats = await StatisticsService.calculateMonthlyStats(sellerId, startOfMonth, endOfMonth);
stats.push(monthlyStats);
}

res.json(stats);
}
16 changes: 16 additions & 0 deletions src/docs/stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const getSellerStats = {
tags: ["stats"],
security: [{ bearerAuth: [] }],
summary: "Get seller statistics",
responses: {
200: {
description: "success",
},
401: {
description: "Unauthorized",
},
500: {
description: "Internal Server Error",
},
},
}
7 changes: 6 additions & 1 deletion src/docs/swagger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { createReviewProduct, deleteReview, getReviewProduct, reviewSchema, upda
import { getAdProducts } from "./products";
import {PrivateChatSchema, getAllUserPrivateChats, getUserToUserPrivateMessages, createPrivateChat } from "./privateChatDoc"
import { StatusSchema, buyerAndSellerOrder, statusUpdate } from "./orders";
import { getSellerStats } from "./stats";

const docRouter = express.Router();

Expand Down Expand Up @@ -80,7 +81,8 @@ const options = {
{ name: "Carts", description: "Endpoints related to Cart" },
{ name: "Payments", description: "Endpoints related to payments" },
{ name: "PrivateChat", description: "Endpoints related to Private Chat" },
{name: "orders", description: "Endpoints related to orders"}
{name: "orders", description: "Endpoints related to orders"},
{name: "stats", description: "Endpoints related to Seller statistics"}
],

paths: {
Expand Down Expand Up @@ -205,6 +207,9 @@ const options = {
},
"/api/v1/orders/{id}/status": {
patch: statusUpdate
},
"/api/v1/stats":{
get: getSellerStats
}
},
components: {
Expand Down
2 changes: 2 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import notificationRoutes from "./notificationRoutes";
import paymentRouter from "./paymentRoutes";
import PrivateChatRoutes from "./privateChatRoutes";
import orderRouter from "./orderRoute";
import statsRouter from "./statsRoutes";
const appROutes = Router();

appROutes.use("/chats", PrivateChatRoutes);
Expand All @@ -21,4 +22,5 @@ appROutes.use("/carts", cartRoutes);
appROutes.use("/notifications", notificationRoutes);
appROutes.use("/payment", paymentRouter);
appROutes.use("/orders", orderRouter)
appROutes.use("/stats", statsRouter);
export default appROutes;
11 changes: 11 additions & 0 deletions src/routes/statsRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import express from "express";

import { getYearlyStats } from "../controllers/statsController";
import { isLoggedIn } from "../middlewares/isLoggedIn";
import { isAseller } from "../middlewares/sellerAuth";

const statsRouter = express.Router();

statsRouter.get("/", isLoggedIn, isAseller , getYearlyStats);

export default statsRouter;
50 changes: 50 additions & 0 deletions src/services/stats.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Op, Sequelize } from 'sequelize';
import Product from '../sequelize/models/products';
import OrderItem from '../sequelize/models/orderItems';

interface OrderItemWithProduct extends OrderItem {
product: Product;
}

export class StatisticsService {
static async calculateMonthlyStats(sellerId: string, startOfMonth: Date, endOfMonth: Date) {

const totalProducts = await Product.count({ where: { userId: sellerId } });

const itemsOrdered= (await OrderItem.findAll({
include: [{
model: Product,
as: 'product',
where: { userId: sellerId },
required: true
}],
where: {
createdAt: { [Op.gte]: startOfMonth, [Op.lte]: endOfMonth }
}
})) as OrderItemWithProduct[];

const monthlySales = itemsOrdered.reduce((sum, item) => sum + item.quantity, 0);

const monthlyRevenue = itemsOrdered.reduce((sum, item) => sum + (item.product.price * item.quantity), 0);


const expiredProducts = await Product.findAll({
where: {
userId: sellerId,
expiryDate: { [Op.gte]: startOfMonth, [Op.lte]: endOfMonth }
}
});


const losses = expiredProducts.reduce((sum, product) => sum + product.price, 0);
const monthName = startOfMonth.toLocaleString('default', { month: 'long' });
return {
month: monthName,
totalProducts,
monthlySales,
monthlyRevenue,
expiredProducts,
losses,
};
}
}

0 comments on commit d8f01d8

Please sign in to comment.