From 9c0c5604410873eb7fd04de0843b646623aa2373 Mon Sep 17 00:00:00 2001 From: nicoagostini Date: Thu, 8 May 2025 20:09:22 -0700 Subject: [PATCH] Progress bar calculations added, displaying and updating the database --- src/router/user.js | 35 ++++++++++++++++++++++++------- src/util/calculations.js | 45 ++++++++++++++++++++++++++++++++++++++++ src/views/planDetail.ejs | 8 +++---- src/views/plans.ejs | 2 +- 4 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 src/util/calculations.js diff --git a/src/router/user.js b/src/router/user.js index 740bc59..084ea03 100644 --- a/src/router/user.js +++ b/src/router/user.js @@ -1,4 +1,5 @@ const getRates = require("../util/exchangeRate"); +const { calculatePlanProgress, updatePlanProgressInDB } = require("../util/calculations"); const status = require("../util/statuses"); const ObjectId = require('mongodb').ObjectId; const session = require("express-session"); @@ -89,11 +90,21 @@ module.exports = (middleware, users, plans, assets) => { router.get('/plans', async (req, res) => { try { // console.log(new ObjectId(req.session.user._id)); - const userPlans = await plans.find({userId: new ObjectId(req.session.user._id) }).toArray(); - // console.log(userPlans); + const userPlansFromDB = await plans.find({userId: new ObjectId(req.session.user._id) }).toArray(); + // console.log(userPlansFromDB); + + // Use a for...of loop for proper async/await behavior in series for updates + for (const plan of userPlansFromDB) { + const percentage = await calculatePlanProgress(plan, assets, req.session.user._id); + await updatePlanProgressInDB(plan._id, percentage, plans); // Pass the 'plans' collection + } + + // Re-fetch plans to get updated progress for rendering + const updatedUserPlans = await plans.find({ userId: new ObjectId(req.session.user._id) }).toArray(); + res.render('plans', { user: req.session.user, - plans: userPlans, + plans: updatedUserPlans, // Send the most up-to-date plans geoData: req.session.geoData }); } catch (err) { @@ -107,7 +118,8 @@ module.exports = (middleware, users, plans, assets) => { try { const planId = req.params.id; - + let userAssets = await assets.find({ userId: new ObjectId(req.session.user._id) }).toArray(); + if (!ObjectId.isValid(planId)) { req.session.errMessage = "Invalid plan ID format."; @@ -122,10 +134,19 @@ module.exports = (middleware, users, plans, assets) => { return res.status(status.NotFound).redirect('/plans'); } // console.log("Found plan:", plan); + + // The plan.progress should be up-to-date from the database as it was updated in the /plans route + // or when assets/plans are modified. If an immediate recalculation for this specific view is absolutely needed, + // (e.g., if assets were modified without an immediate plan progress update elsewhere), + // you could do it here: + // const currentProgress = await calculatePlanProgress(plan, assets, req.session.user._id); + // plan.progress = currentProgress; // This would only update the 'plan' object for this render, not in DB + res.render('planDetail', { user: req.session.user, - plan: plan, - geoData: req.session.geoData + plan: plan, // This plan object will have the progress from the database + geoData: req.session.geoData, + assets: userAssets, }); } catch (err) { @@ -174,7 +195,7 @@ module.exports = (middleware, users, plans, assets) => { retirementExpenses: value.retirementExpenses, retirementAssets: value.retirementAssets, retirementLiabilities: value.retirementLiabilities, - progress: "0%" + progress: "0" }; try{ diff --git a/src/util/calculations.js b/src/util/calculations.js new file mode 100644 index 0000000..25f5d33 --- /dev/null +++ b/src/util/calculations.js @@ -0,0 +1,45 @@ +const ObjectId = require('mongodb').ObjectId; + +async function calculatePlanProgress(plans, assets, userId) { + if (!plans || typeof plans.retirementAssets === 'undefined') { + console.error("Invalid plan document provided to calculatePlanProgress:", plans); + return 0; + } + if (!assets || typeof assets.find !== 'function') { + console.error("Invalid assetsCollection provided to calculatePlanProgress"); + return 0; + } + + try { + const userAssets = await assets.find({ userId: new ObjectId(userId) }).toArray(); + const totalUserAssetValue = userAssets.reduce((total, asset) => total + asset.value, 0); + let percentage = 0; + + if (plans.retirementAssets > 0) { + percentage = (totalUserAssetValue / plans.retirementAssets) * 100; + } + return percentage; + } catch (err) { + console.error("Error in calculatePlanProgress:", err); + return 0; + } +} + +async function updatePlanProgressInDB(planId, percentage, plans) { + if (!plans || typeof plans.updateOne !== 'function') { + console.error("Error with the plans collection"); + return; + } + if (typeof percentage !== 'number' || isNaN(percentage)) { + console.error(`Error with the percentage: ${percentage}`); + return; + } + + try { + await plans.updateOne({ _id: new ObjectId(planId) }, { $set: { progress: parseFloat(percentage.toFixed(2)) } }); + } catch (err) { + console.error("Error in updatePlanProgressInDB:", err); + } +} + +module.exports = { calculatePlanProgress, updatePlanProgressInDB }; \ No newline at end of file diff --git a/src/views/planDetail.ejs b/src/views/planDetail.ejs index 8b430f1..49c34f9 100644 --- a/src/views/planDetail.ejs +++ b/src/views/planDetail.ejs @@ -12,10 +12,10 @@
Progress - <%= plan.progress %> + <%= plan.progress %>%
-
+
@@ -25,11 +25,11 @@
-

16 MOCK

+

<%= assets.length %>

-

$165,000 MOCK

+

<%= assets.reduce((total, asset) => total + asset.value, 0) %>

diff --git a/src/views/plans.ejs b/src/views/plans.ejs index ce7ca80..0b1b68b 100644 --- a/src/views/plans.ejs +++ b/src/views/plans.ejs @@ -11,7 +11,7 @@
<%= plan.name %>
-
+

<%= plan.description %>