From 5c4bc028ba2772b5e7ff313b3f6b08435226915a Mon Sep 17 00:00:00 2001 From: Gowtham M Date: Thu, 6 Nov 2025 11:30:17 +0530 Subject: [PATCH] GWM : Admin dashboard api --- app/controllers/dashboard.controller.js | 160 ++++++++++++++++---- app/controllers/establishment.controller.js | 7 +- app/routes/routes.js | 4 +- 3 files changed, 133 insertions(+), 38 deletions(-) diff --git a/app/controllers/dashboard.controller.js b/app/controllers/dashboard.controller.js index d451fce..c4c4ca8 100644 --- a/app/controllers/dashboard.controller.js +++ b/app/controllers/dashboard.controller.js @@ -1,6 +1,6 @@ const { Sequelize, Op } = require("sequelize"); -const { Establishment, Submission, Emirate, EstablishmentUser, SubmissionProduct, SubmissionDeadline } = require("../models"); +const { Establishment, Submission, Emirate, EstablishmentUser, SubmissionProduct, SubmissionDeadline, QuarterlyWindowsConfiguration } = require("../models"); function getQuarter(date) { const month = date.getMonth() + 1; @@ -154,38 +154,46 @@ exports.getEstablishmentDashboard = async (req, res) => { exports.adminDashboard = async (req, res) => { try { - const { quarter, year } = req.query; // e.g., Q1, 2025 + let { quarter, year } = req.query; - // --- Summary Counts --- - const [ - totalEstablishments, - submittedCount, - approvedCount, - rejectedCount, - pendingCount - ] = await Promise.all([ - Establishment.count(), - Submission.count(), - Submission.count({ where: { status: "Approved" } }), - Submission.count({ where: { status: "Rejected" } }), - Submission.count({ where: { status: "Pending" } }), - ]); + // if quarter/year not passed → take latest open config + if (!quarter || !year) { + const lastConfig = await QuarterlyWindowsConfiguration.findOne({ + order: [ + ['year', 'DESC'], + ['quarter', 'DESC'] + ] + }); - // Not Started = total establishments - those that have any submission - const startedEstIds = await Submission.findAll({ - attributes: [[Sequelize.fn("DISTINCT", Sequelize.col("establishment_id")), "id"]], - raw: true, - }); - const startedIds = startedEstIds.map(e => e.id); - const notStartedCount = await Establishment.count({ - where: { id: { [Op.notIn]: startedIds } }, - }); + if (lastConfig) { + quarter = lastConfig.quarter; + year = lastConfig.year; + } + } - // --- Recent 10 submissions for given quarter & year --- const whereCond = {}; if (quarter) whereCond.quarter = quarter; if (year) whereCond.year = year; + const totalEstablishments = await Establishment.count(); + const submittedCount = await Submission.count({ where: whereCond }); + const approvedCount = await Submission.count({ where: { ...whereCond, status: "Approved" } }); + const rejectedCount = await Submission.count({ where: { ...whereCond, status: "Rejected" } }); + const pendingCount = await Submission.count({ where: { ...whereCond, status: "Pending" } }); + + // only when query param not used → not started count + let notStartedCount = 0; + if (!req.query.quarter && !req.query.year) { + const startedEstIds = await Submission.findAll({ + attributes: [[Sequelize.fn("DISTINCT", Sequelize.col("establishment_id")), "id"]], + raw: true, + }); + const startedIds = startedEstIds.map(e => e.id); + notStartedCount = await Establishment.count({ + where: { id: { [Op.notIn]: startedIds } }, + }); + } + const recentSubmissions = await Submission.findAll({ where: whereCond, include: [ @@ -197,11 +205,7 @@ exports.adminDashboard = async (req, res) => { { model: Emirate, as: "establishment_emirate", attributes: ["name"] }, ], }, - { - model: EstablishmentUser, - as: "created_user", - attributes: ["name"], - }, + { model: EstablishmentUser, as: "created_user", attributes: ["name"] }, ], attributes: { include: [ @@ -219,9 +223,10 @@ exports.adminDashboard = async (req, res) => { limit: 10, }); - // --- Send Response --- return res.status(200).json({ status: "success", + selected_quarter: quarter, + selected_year: year, summary: { total_establishments: totalEstablishments, submitted: submittedCount, @@ -232,8 +237,97 @@ exports.adminDashboard = async (req, res) => { }, recent_submissions: recentSubmissions, }); + } catch (err) { console.error(err); return res.status(500).json({ status: "failed", message: err.message }); } -}; \ No newline at end of file +}; + + + +// exports.adminDashboard = async (req, res) => { +// try { +// const { quarter, year } = req.query; // e.g., Q1, 2025 + +// // --- Summary Counts --- +// const [ +// totalEstablishments, +// submittedCount, +// approvedCount, +// rejectedCount, +// pendingCount +// ] = await Promise.all([ +// Establishment.count(), +// Submission.count(), +// Submission.count({ where: { status: "Approved" } }), +// Submission.count({ where: { status: "Rejected" } }), +// Submission.count({ where: { status: "Pending" } }), +// ]); + +// // Not Started = total establishments - those that have any submission +// const startedEstIds = await Submission.findAll({ +// attributes: [[Sequelize.fn("DISTINCT", Sequelize.col("establishment_id")), "id"]], +// raw: true, +// }); +// const startedIds = startedEstIds.map(e => e.id); +// const notStartedCount = await Establishment.count({ +// where: { id: { [Op.notIn]: startedIds } }, +// }); + +// // --- Recent 10 submissions for given quarter & year --- +// const whereCond = {}; +// if (quarter) whereCond.quarter = quarter; +// if (year) whereCond.year = year; + +// const recentSubmissions = await Submission.findAll({ +// where: whereCond, +// include: [ +// { +// model: Establishment, +// as: "establishment", +// attributes: ["factory_name"], +// include: [ +// { model: Emirate, as: "establishment_emirate", attributes: ["name"] }, +// ], +// }, +// { +// model: EstablishmentUser, +// as: "created_user", +// attributes: ["name"], +// }, +// ], +// attributes: { +// include: [ +// [ +// Sequelize.literal(`( +// SELECT COUNT(*) +// FROM submission_products AS sp +// WHERE sp.submission_id = submission.id +// )`), +// "product_count", +// ], +// ], +// }, +// order: [["created_at", "DESC"]], +// limit: 10, +// }); + +// // --- Send Response --- +// return res.status(200).json({ +// status: "success", +// summary: { +// total_establishments: totalEstablishments, +// submitted: submittedCount, +// approved: approvedCount, +// rejected: rejectedCount, +// pending: pendingCount, +// not_started: notStartedCount, +// }, +// recent_submissions: recentSubmissions, +// }); +// } catch (err) { +// console.error(err); +// return res.status(500).json({ status: "failed", message: err.message }); +// } +// }; \ No newline at end of file diff --git a/app/controllers/establishment.controller.js b/app/controllers/establishment.controller.js index 3176d39..48d95e3 100644 --- a/app/controllers/establishment.controller.js +++ b/app/controllers/establishment.controller.js @@ -24,6 +24,7 @@ exports.testEmail = async (req, res) => { } await sendEmailService('gowthamceline46@gmail.com', 'establishment_user_creation_to_user', placeHolderData); }; + exports.createEstablishment = async (req, res) => { try { const { @@ -634,16 +635,16 @@ exports.forgotPasswordVerifyOTP = async (req, res) => { const user = await EstablishmentUser.findOne({ where: { email: registered_email } }); if (!user || !user.reset_otp) - return res.status(404).json({ status: "failed", message: "OTP not found or invalid user" }); + return res.status(404).json({ status: "failed", message: "verification code not found or invalid user" }); // Check OTP expiry if (new Date() > new Date(user.reset_otp_expires_at)) - return res.status(400).json({ status: "failed", message: "OTP expired" }); + return res.status(400).json({ status: "failed", message: "Verification code has expired. Please request a new one" }); // Compare OTP const isOtpValid = await bcrypt.compare(otp, user.reset_otp); if (!isOtpValid) - return res.status(400).json({ status: "failed", message: "Invalid OTP" }); + return res.status(400).json({ status: "failed", message: "Invalid verification code" }); // Update password const hashedPassword = await bcrypt.hash(password, 10); diff --git a/app/routes/routes.js b/app/routes/routes.js index 3a82504..c9895dd 100644 --- a/app/routes/routes.js +++ b/app/routes/routes.js @@ -2236,12 +2236,12 @@ router.get("/establishment_dashboard",[verifySignature, verifyToken],dashboardCo * parameters: * - in: query * name: quarter - * required: true + * required: false * schema: * type: string * - in: query * name: year - * required: true + * required: false * schema: * type: integer * responses: