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;