Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7d8148d
feat: add project status summary API for donut chart (backend)
Saicharan1505 Aug 31, 2025
df94dbb
Merge branch development into current
Juhitha-Reddy Sep 18, 2025
94fdea3
update lock file to sync dependencies
Juhitha-Reddy Sep 18, 2025
bc5a060
chore: resolved merge conflicts in app.js and package files
Saicharan1505 Oct 4, 2025
dfbbbba
chore: accepted latest messagingSocket.js from development during merge
Saicharan1505 Oct 4, 2025
a74c838
chore: rebuilt package-lock.json with cross-platform sharp binaries
Saicharan1505 Oct 4, 2025
f3d7616
chore: merge development into feature/project-status-donut-backend
vamsidharpanithi Oct 17, 2025
5dea23b
fix(routes): import bmExpenditureRouter without invoking
vamsidharpanithi Oct 17, 2025
550a4d9
chore(lockfile): resolve merge by taking development package-lock.json
vamsidharpanithi Oct 17, 2025
8151be8
fix: update project status controller to use correct project model
Juhitha-Reddy Mar 1, 2026
e50392c
fix: update log of user controlled data
Juhitha-Reddy Mar 1, 2026
b868f11
Fixed coding standard issue
Juhitha-Reddy Mar 3, 2026
2079780
Merge branch 'development' into feature/project-status-donut-backend
Juhitha-Reddy Apr 6, 2026
9b4c76b
added try catch block
Juhitha-Reddy Apr 6, 2026
58c22a9
Fixed lint issues
Juhitha-Reddy Apr 6, 2026
74b8453
Resolve merge conflicts with origin/development
Jun 17, 2026
4cacc48
Resolve merge conflicts with origin/development
Jun 17, 2026
aa86136
Fix undefined isReceiverActive and isReceiverInChat variables
Jun 17, 2026
d28eb2c
fix: update projectStatusRouter to use correct controller with window…
saurabhdipte Jun 27, 2026
6ad6ede
fix(merge): Merge branch 'development' of into feature/project-status…
shreevathsrao Jul 29, 2026
dcd2863
fix: Fix socket bug
shreevathsrao Aug 10, 2026
1d0dfc4
fix: Merge branch 'development' into feature/project-status-donut-bac…
shreevathsrao Aug 10, 2026
685d7c9
fix: Fix SonarCube issue
shreevathsrao Aug 10, 2026
4942706
fix: Add Test cases
shreevathsrao Aug 13, 2026
ab7a1c3
fix: add more test cases
shreevathsrao Aug 13, 2026
682a8ce
fix: merge branch 'development' of into feature/project-status-donut-…
shreevathsrao Aug 21, 2026
d6f06ca
fix: Merge branch 'development' of into feature/project-status-donut-…
shreevathsrao Aug 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12,152 changes: 7,950 additions & 4,202 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@
},
"dependencies": {
"@azure/storage-blob": "^12.26.0",
"mongoose": "^5.13.23",
"@babel/cli": "^7.15.4",
"@babel/core": "^7.10.2",
"@babel/node": "^7.14.9",
Expand All @@ -70,6 +69,7 @@
"compression": "^1.8.0",
"cors": "^2.8.4",
"cron": "^1.8.2",
"dayjs": "^1.11.13",
"dotenv": "^5.0.1",
"dropbox": "^10.34.0",
"express": "^4.17.1",
Expand All @@ -82,6 +82,7 @@
"moment": "^2.29.4",
"moment-timezone": "^0.5.35",
"mongodb": "^3.7.3",
"mongoose": "^5.13.23",
"mongoose-validator": "^2.1.0",
"multer": "^1.4.5-lts.1",
"node-cache": "^5.1.2",
Expand Down
2 changes: 2 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const app = express();
const logger = require('./startup/logger');
const globalErrorHandler = require('./utilities/errorHandling/globalErrorHandler');
const experienceRoutes = require('./routes/applicantAnalyticsRoutes');

logger.init();

// The request handler must be the first middleware on the app
Expand All @@ -14,6 +15,7 @@ require('./startup/compression')(app);
require('./startup/cors')(app);
require('./startup/bodyParser')(app);
require('./startup/middleware')(app);

require('./startup/routes')(app);

// The error handler must be before any other error middleware and after all controllers
Expand Down
26 changes: 26 additions & 0 deletions src/controllers/projectStatus.controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const dayjs = require('dayjs');
const { getProjectStatusSummary } = require('../services/projectStatus.service');

exports.fetchProjectStatus = async (req, res) => {
try {
const { startDate, endDate } = req.query;

// Validate dates
if (startDate && !dayjs(startDate, 'YYYY-MM-DD', true).isValid()) {
return res.status(400).json({ message: 'Invalid startDate (YYYY-MM-DD)' });
}
if (endDate && !dayjs(endDate, 'YYYY-MM-DD', true).isValid()) {
return res.status(400).json({ message: 'Invalid endDate (YYYY-MM-DD)' });
}
if (startDate && endDate && dayjs(startDate).isAfter(dayjs(endDate))) {
return res.status(400).json({ message: 'startDate cannot be after endDate' });
}

const data = await getProjectStatusSummary({ startDate, endDate });
return res.json(data);
} catch (err) {
// eslint-disable-next-line no-console
console.error('fetchProjectStatus error:', err);
return res.status(500).json({ message: 'Internal server error' });
}
};
23 changes: 23 additions & 0 deletions src/models/projectStatus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const mongoose = require('mongoose');

const { Schema } = mongoose;

const projectStatusSchema = new Schema(
{
name: { type: String, required: true },
status: {
type: String,
enum: ['Active', 'Completed', 'Delayed'],
required: true,
},
startDate: { type: Date, required: true },
completionDate: { type: Date },
},
{ timestamps: true },
);

// Indexes for faster queries
projectStatusSchema.index({ status: 1 });
projectStatusSchema.index({ startDate: 1 });

module.exports = mongoose.model('ProjectStatus', projectStatusSchema, 'projectStatus');
16 changes: 16 additions & 0 deletions src/routes/projectStatusRouter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
const express = require('express');

const router = express.Router();
const { fetchProjectStatus } = require('../controllers/projectStatus.controller');

// Quick sanity check endpoint
router.get('/status', (req, res) => {
console.log(' Project status route hit!');
res.json({ message: ' projectStatus route is working!' });
});

// Main API endpoint
router.get('/summary', fetchProjectStatus);

// Export the router directly (not a function)
module.exports = router;
50 changes: 50 additions & 0 deletions src/services/projectStatus.service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const dayjs = require('dayjs');
const ProjectStatus = require('../models/projectStatus');

// Utility to compute percentages safely
const calcPct = (count, total) => (total ? Number(((count / total) * 100).toFixed(1)) : 0.0);

async function getProjectStatusSummary({ startDate, endDate }) {
Comment thread
shree-vaths marked this conversation as resolved.
const match = {};

if (startDate || endDate) {
match.startDate = {};
if (startDate) match.startDate.$gte = dayjs(startDate).startOf('day').toDate();
if (endDate) match.startDate.$lte = dayjs(endDate).endOf('day').toDate();
}

const pipeline = [
Object.keys(match).length ? { $match: match } : null,
{ $group: { _id: '$status', count: { $sum: 1 } } },
].filter(Boolean);

const rows = await ProjectStatus.aggregate(pipeline);

// Normalize counts
const counts = { active: 0, completed: 0, delayed: 0 };
rows.forEach((r) => {
if (r._id === 'Active') counts.active = r.count;
if (r._id === 'Completed') counts.completed = r.count;
if (r._id === 'Delayed') counts.delayed = r.count;
});

const totalProjects = counts.active + counts.completed + counts.delayed;

return {
totalProjects,
activeProjects: counts.active,
completedProjects: counts.completed,
delayedProjects: counts.delayed,
percentages: {
active: calcPct(counts.active, totalProjects),
completed: calcPct(counts.completed, totalProjects),
delayed: calcPct(counts.delayed, totalProjects),
},
window: {
startDate: startDate || null,
endDate: endDate || null,
},
};
}

module.exports = { getProjectStatusSummary };
4 changes: 4 additions & 0 deletions src/startup/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ const blueSquareEmailAssignment = require('../models/BlueSquareEmailAssignment')
const hgnformRouter = require('../routes/hgnformRouter');
const hgnFormResponseRouter = require('../routes/hgnFormResponseRouter');

const projectStatusRouter = require('../routes/projectStatusRouter');

const questionnaireAnalyticsRouter = require('../routes/questionnaireAnalyticsRouter');
const weeklySummaryAIPrompt = require('../models/weeklySummaryAIPrompt');

Expand Down Expand Up @@ -262,6 +264,8 @@ const tagRouter = require('../routes/tagRouter')(tag);
const applicantVolunteerRatioRouter = require('../routes/applicantVolunteerRatioRouter');

module.exports = function (app) {
app.use('/api/project-status', projectStatusRouter);

app.use('/api', forgotPwdRouter);
app.use('/api', loginRouter);
app.use('/api', forcePwdRouter);
Expand Down