feat: complete day 2
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
const { Op } = require("sequelize");
|
||||
|
||||
class PaginationService {
|
||||
/**
|
||||
* Handle offset-based pagination with sorting
|
||||
*/
|
||||
static async paginateWithSort(model, options = {}) {
|
||||
const {
|
||||
page = 1,
|
||||
limit = 10,
|
||||
sort = "id",
|
||||
direction = "ASC",
|
||||
where = {},
|
||||
} = options;
|
||||
|
||||
const offset = (page - 1) * limit;
|
||||
const order = [[sort, direction.toUpperCase()]];
|
||||
|
||||
const { count, rows } = await model.findAndCountAll({
|
||||
where,
|
||||
order,
|
||||
limit: parseInt(limit),
|
||||
offset: parseInt(offset),
|
||||
});
|
||||
|
||||
const totalPages = Math.ceil(count / limit);
|
||||
|
||||
return {
|
||||
total: count,
|
||||
page: parseInt(page),
|
||||
totalPages,
|
||||
list: rows,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle cursor-based pagination
|
||||
*/
|
||||
static async paginateWithCursor(model, options = {}) {
|
||||
const {
|
||||
id,
|
||||
limit = 10,
|
||||
sort = "id",
|
||||
direction = "ASC",
|
||||
where = {},
|
||||
} = options;
|
||||
|
||||
const order = [[sort, direction.toUpperCase()]];
|
||||
const cursorWhere = {
|
||||
...where,
|
||||
[sort]: {
|
||||
[direction.toUpperCase() === "ASC" ? Op.gt : Op.lt]: id,
|
||||
},
|
||||
};
|
||||
|
||||
const rows = await model.findAll({
|
||||
where: cursorWhere,
|
||||
order,
|
||||
limit: parseInt(limit),
|
||||
});
|
||||
|
||||
return {
|
||||
id: parseInt(id),
|
||||
list: rows,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get odd order IDs
|
||||
*/
|
||||
static async getOddOrders(model) {
|
||||
return await model.findAll({
|
||||
where: {
|
||||
id: {
|
||||
[Op.mod]: [2, 1], // id % 2 = 1 (odd numbers)
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PaginationService;
|
||||
@@ -0,0 +1,169 @@
|
||||
const { Op, fn, col, literal } = require("sequelize");
|
||||
|
||||
class ReportService {
|
||||
/**
|
||||
* Get total sales for a specific month and year
|
||||
*/
|
||||
static async getMonthlySales(model, month, year) {
|
||||
const result = await model.findOne({
|
||||
attributes: [[fn("SUM", col("amount")), "total_amount"]],
|
||||
where: {
|
||||
created_at: {
|
||||
[Op.and]: [
|
||||
literal(`MONTH(created_at) = ${month}`),
|
||||
literal(`YEAR(created_at) = ${year}`),
|
||||
],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
month: parseInt(month),
|
||||
year: parseInt(year),
|
||||
total_amount: parseFloat(result?.dataValues?.total_amount || 0),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total sales for a date range
|
||||
*/
|
||||
static async getSalesByDateRange(model, fromDate, toDate) {
|
||||
// Ensure dates are in correct order
|
||||
const startDate = new Date(fromDate) < new Date(toDate) ? fromDate : toDate;
|
||||
const endDate = new Date(fromDate) < new Date(toDate) ? toDate : fromDate;
|
||||
|
||||
const result = await model.findOne({
|
||||
attributes: [[fn("SUM", col("amount")), "total_amount"]],
|
||||
where: {
|
||||
created_at: {
|
||||
[Op.between]: [startDate, endDate],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
from_date: startDate,
|
||||
to_date: endDate,
|
||||
total_amount: parseFloat(result?.dataValues?.total_amount || 0),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get monthly sales for a year (only months with sales > 0)
|
||||
*/
|
||||
static async getMonthlySalesByYear(model, year) {
|
||||
const results = await model.findAll({
|
||||
attributes: [
|
||||
[fn("MONTH", col("created_at")), "month"],
|
||||
[fn("SUM", col("amount")), "total_amount"],
|
||||
],
|
||||
where: {
|
||||
created_at: {
|
||||
[Op.and]: [literal(`YEAR(created_at) = ${year}`)],
|
||||
},
|
||||
},
|
||||
group: [fn("MONTH", col("created_at"))],
|
||||
having: literal("SUM(amount) > 0"),
|
||||
order: [[fn("MONTH", col("created_at")), "ASC"]],
|
||||
});
|
||||
|
||||
return results.map((result) => ({
|
||||
month: parseInt(result.dataValues.month),
|
||||
total_amount: parseFloat(result.dataValues.total_amount),
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get monthly sales for a year by user_id (only months with sales > 0)
|
||||
*/
|
||||
static async getMonthlySalesByUser(model, year, userId) {
|
||||
const results = await model.findAll({
|
||||
attributes: [
|
||||
[fn("MONTH", col("created_at")), "month"],
|
||||
[fn("SUM", col("amount")), "total_amount"],
|
||||
],
|
||||
where: {
|
||||
created_at: {
|
||||
[Op.and]: [literal(`YEAR(created_at) = ${year}`)],
|
||||
},
|
||||
user_id: userId,
|
||||
},
|
||||
group: [fn("MONTH", col("created_at"))],
|
||||
having: literal("SUM(amount) > 0"),
|
||||
order: [[fn("MONTH", col("created_at")), "ASC"]],
|
||||
});
|
||||
|
||||
return results.map((result) => ({
|
||||
month: parseInt(result.dataValues.month),
|
||||
total_amount: parseFloat(result.dataValues.total_amount),
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get monthly sales for a year by shipping_dock_id (only months with sales > 0)
|
||||
*/
|
||||
static async getMonthlySalesByShippingDock(model, year, shippingDockId) {
|
||||
const results = await model.findAll({
|
||||
attributes: [
|
||||
[fn("MONTH", col("created_at")), "month"],
|
||||
[fn("SUM", col("amount")), "total_amount"],
|
||||
],
|
||||
where: {
|
||||
created_at: {
|
||||
[Op.and]: [literal(`YEAR(created_at) = ${year}`)],
|
||||
},
|
||||
shipping_dock_id: shippingDockId,
|
||||
},
|
||||
group: [fn("MONTH", col("created_at"))],
|
||||
having: literal("SUM(amount) > 0"),
|
||||
order: [[fn("MONTH", col("created_at")), "ASC"]],
|
||||
});
|
||||
|
||||
return results.map((result) => ({
|
||||
month: parseInt(result.dataValues.month),
|
||||
total_amount: parseFloat(result.dataValues.total_amount),
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get order count per month for a user in a year (include months with 0 orders)
|
||||
*/
|
||||
static async getOrderCountByUser(model, year, userId) {
|
||||
// First get all months with orders
|
||||
const orderMonths = await model.findAll({
|
||||
attributes: [
|
||||
[fn("MONTH", col("created_at")), "month"],
|
||||
[fn("COUNT", col("id")), "order_count"],
|
||||
],
|
||||
where: {
|
||||
created_at: {
|
||||
[Op.and]: [literal(`YEAR(created_at) = ${year}`)],
|
||||
},
|
||||
user_id: userId,
|
||||
},
|
||||
group: [fn("MONTH", col("created_at"))],
|
||||
order: [[fn("MONTH", col("created_at")), "ASC"]],
|
||||
});
|
||||
|
||||
// Create a map of months with orders
|
||||
const monthMap = {};
|
||||
orderMonths.forEach((result) => {
|
||||
monthMap[parseInt(result.dataValues.month)] = parseInt(
|
||||
result.dataValues.order_count
|
||||
);
|
||||
});
|
||||
|
||||
// Create result array with all 12 months
|
||||
const result = [];
|
||||
for (let month = 1; month <= 12; month++) {
|
||||
result.push({
|
||||
month,
|
||||
order_count: monthMap[month] || 0,
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReportService;
|
||||
Reference in New Issue
Block a user