-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #100 from atlp-rwanda/ft-Seller-Stats-#187419165
added seller statistic feature
- Loading branch information
Showing
6 changed files
with
106 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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", | ||
}, | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}; | ||
} | ||
} |