fcsc_ipi_backend/app/controllers/dashboard.controller.js
2025-10-29 11:38:32 +05:30

242 lines
6.7 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { Sequelize, Op } = require("sequelize");
const { Establishment, Submission, Emirate, EstablishmentUser, SubmissionProduct, SubmissionDeadline } = require("../models");
function getQuarter(date) {
const month = date.getMonth() + 1;
if (month >= 4 && month <= 6) return "Q1";
if (month >= 7 && month <= 9) return "Q2";
if (month >= 10 && month <= 12) return "Q3";
return "Q4"; // Jan-Mar
}
function getQuarterDates(quarter, year) {
switch (quarter) {
case "Q1":
return { start: new Date(year, 3, 1), end: new Date(year, 5, 30) };
case "Q2":
return { start: new Date(year, 6, 1), end: new Date(year, 8, 30) };
case "Q3":
return { start: new Date(year, 9, 1), end: new Date(year, 11, 31) };
case "Q4":
return { start: new Date(year, 0, 1), end: new Date(year, 2, 31) };
default:
return {};
}
}
function getPrevCurrNextQuarter(date) {
const month = date.getMonth() + 1; // 1-12
const year = date.getFullYear();
const quarters = ["Q1", "Q2", "Q3", "Q4"];
// map month -> index: 0=Q1(Apr-Jun),1=Q2(Jul-Sep),2=Q3(Oct-Dec),3=Q4(Jan-Mar)
const getQuarterIndex = (m) => {
if (m >= 4 && m <= 6) return 0; // Apr-Jun -> Q1
if (m >= 7 && m <= 9) return 1; // Jul-Sep -> Q2
if (m >= 10 && m <= 12) return 2; // Oct-Dec -> Q3
return 3; // Jan-Mar -> Q4
};
const currentIndex = getQuarterIndex(month);
const currentQuarter = quarters[currentIndex];
const previousIndex = (currentIndex - 1 + 4) % 4;
const nextIndex = (currentIndex + 1) % 4;
const previousQuarter = quarters[previousIndex];
const nextQuarter = quarters[nextIndex];
const previousQuarterYear = (currentIndex === 3) ? year - 1 : year;
const nextQuarterYear = (currentIndex === 2) ? year + 1 : year;
return {
previous_quarter: previousQuarter,
previous_quarter_year: previousQuarterYear,
current_quarter: currentQuarter,
current_quarter_year: year,
next_quarter: nextQuarter,
next_quarter_year: nextQuarterYear,
};
}
exports.getEstablishmentDashboard = async (req, res) => {
try {
const establishment_id = req.query.establishment_id;
if (!establishment_id) {
return res.status(400).json({ status: "failed", message: "establishment_id required" });
}
const today = new Date();
const quarters = getPrevCurrNextQuarter(today);
const submission_history = await Submission.findAll({
where: { establishment_id },
order: [["created_at", "DESC"]],
limit: 5,
attributes: {
include: [
[
Sequelize.literal(`(
SELECT COUNT(*)
FROM submission_products AS sp
WHERE sp.submission_id = submission.id
)`),
"product_count",
],
],
},
});
// Submission status for current quarter
const currentQuarterDates = getQuarterDates(quarters.current_quarter, quarters.current_quarter_year);
const currentSubmission = await Submission.findOne({
where: {
establishment_id,
quarter: quarters.current_quarter,
year: quarters.current_quarter_year,
},
order: [["created_at", "DESC"]],
});
// Get submission deadline (assuming only one row)
const deadline = await SubmissionDeadline.findByPk(1);
let nextDeadline = null;
let submissionStatus = "Pending";
if (deadline) {
const quarterEnd = currentQuarterDates.end;
const deadlineDate = new Date(quarterEnd);
deadlineDate.setDate(deadlineDate.getDate() + deadline.deadline_days_after_quarter_end);
nextDeadline = deadlineDate;
if (currentSubmission) {
submissionStatus = "Submitted";
}
}
let lastSubmissionInfo = null;
if (submission_history.length > 0) {
const last = submission_history[0];
lastSubmissionInfo = {
quarter: last.quarter,
year: last.year,
submitted_on: last.created_at,
};
}
res.status(200).json({
status: "success",
data: {
...quarters,
submission_status: submissionStatus,
next_deadline: nextDeadline,
last_submission: lastSubmissionInfo,
submission_history,
},
});
} catch (err) {
console.error(err);
res.status(500).json({ status: "failed", message: err.message });
}
};
exports.adminDashboard = async (req, res) => {
try {
const { quarter, year } = req.query; // e.g., Q1, 2025
// --- 1⃣ 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 } },
});
// --- 2⃣ 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,
});
// --- 3⃣ 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 });
}
};