GWM : Admin dashboard api

This commit is contained in:
Gowtham M 2025-11-06 11:30:17 +05:30
parent f0db22f2bd
commit 5c4bc028ba
3 changed files with 133 additions and 38 deletions

View File

@ -1,6 +1,6 @@
const { Sequelize, Op } = require("sequelize"); 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) { function getQuarter(date) {
const month = date.getMonth() + 1; const month = date.getMonth() + 1;
@ -154,37 +154,45 @@ exports.getEstablishmentDashboard = async (req, res) => {
exports.adminDashboard = async (req, res) => { exports.adminDashboard = async (req, res) => {
try { try {
const { quarter, year } = req.query; // e.g., Q1, 2025 let { quarter, year } = req.query;
// --- Summary Counts --- // if quarter/year not passed → take latest open config
const [ if (!quarter || !year) {
totalEstablishments, const lastConfig = await QuarterlyWindowsConfiguration.findOne({
submittedCount, order: [
approvedCount, ['year', 'DESC'],
rejectedCount, ['quarter', 'DESC']
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 if (lastConfig) {
quarter = lastConfig.quarter;
year = lastConfig.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({ const startedEstIds = await Submission.findAll({
attributes: [[Sequelize.fn("DISTINCT", Sequelize.col("establishment_id")), "id"]], attributes: [[Sequelize.fn("DISTINCT", Sequelize.col("establishment_id")), "id"]],
raw: true, raw: true,
}); });
const startedIds = startedEstIds.map(e => e.id); const startedIds = startedEstIds.map(e => e.id);
const notStartedCount = await Establishment.count({ notStartedCount = await Establishment.count({
where: { id: { [Op.notIn]: startedIds } }, 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({ const recentSubmissions = await Submission.findAll({
where: whereCond, where: whereCond,
@ -197,11 +205,7 @@ exports.adminDashboard = async (req, res) => {
{ model: Emirate, as: "establishment_emirate", attributes: ["name"] }, { model: Emirate, as: "establishment_emirate", attributes: ["name"] },
], ],
}, },
{ { model: EstablishmentUser, as: "created_user", attributes: ["name"] },
model: EstablishmentUser,
as: "created_user",
attributes: ["name"],
},
], ],
attributes: { attributes: {
include: [ include: [
@ -219,9 +223,10 @@ exports.adminDashboard = async (req, res) => {
limit: 10, limit: 10,
}); });
// --- Send Response ---
return res.status(200).json({ return res.status(200).json({
status: "success", status: "success",
selected_quarter: quarter,
selected_year: year,
summary: { summary: {
total_establishments: totalEstablishments, total_establishments: totalEstablishments,
submitted: submittedCount, submitted: submittedCount,
@ -232,8 +237,97 @@ exports.adminDashboard = async (req, res) => {
}, },
recent_submissions: recentSubmissions, recent_submissions: recentSubmissions,
}); });
} catch (err) { } catch (err) {
console.error(err); console.error(err);
return res.status(500).json({ status: "failed", message: err.message }); return res.status(500).json({ status: "failed", message: err.message });
} }
}; };
// 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 });
// }
// };

View File

@ -24,6 +24,7 @@ exports.testEmail = async (req, res) => {
} }
await sendEmailService('gowthamceline46@gmail.com', 'establishment_user_creation_to_user', placeHolderData); await sendEmailService('gowthamceline46@gmail.com', 'establishment_user_creation_to_user', placeHolderData);
}; };
exports.createEstablishment = async (req, res) => { exports.createEstablishment = async (req, res) => {
try { try {
const { const {
@ -634,16 +635,16 @@ exports.forgotPasswordVerifyOTP = async (req, res) => {
const user = await EstablishmentUser.findOne({ where: { email: registered_email } }); const user = await EstablishmentUser.findOne({ where: { email: registered_email } });
if (!user || !user.reset_otp) 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 // Check OTP expiry
if (new Date() > new Date(user.reset_otp_expires_at)) 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 // Compare OTP
const isOtpValid = await bcrypt.compare(otp, user.reset_otp); const isOtpValid = await bcrypt.compare(otp, user.reset_otp);
if (!isOtpValid) 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 // Update password
const hashedPassword = await bcrypt.hash(password, 10); const hashedPassword = await bcrypt.hash(password, 10);

View File

@ -2236,12 +2236,12 @@ router.get("/establishment_dashboard",[verifySignature, verifyToken],dashboardCo
* parameters: * parameters:
* - in: query * - in: query
* name: quarter * name: quarter
* required: true * required: false
* schema: * schema:
* type: string * type: string
* - in: query * - in: query
* name: year * name: year
* required: true * required: false
* schema: * schema:
* type: integer * type: integer
* responses: * responses: