diff --git a/src/router/user.js b/src/router/user.js index 4a24169..83ef7b3 100644 --- a/src/router/user.js +++ b/src/router/user.js @@ -1,5 +1,5 @@ const getRates = require("../util/exchangeRate"); -const { calculatePlanProgress, updatePlanProgressInDB } = require("../util/calculations"); +const { calculateProgress, updatePlanProgressInDB } = require("../util/calculations"); const suggestions = require("../util/suggestions"); const status = require("../util/statuses"); const ObjectId = require('mongodb').ObjectId; @@ -86,13 +86,11 @@ module.exports = (middleware, users, plans, assets) => { toCurrencyRates: [], }; } - let planSchema = await plans.find({ userId: new ObjectId(user) }).project({ - name: 1, retirementAssets: 1, progress: 1, _id: 1, - }).toArray(); + const userPlansFromDB = await plans.find({ userId: new ObjectId(req.session.userId) }).toArray(); - for (const plan of planSchema) { - const percentage = await calculatePlanProgress(plan, assets, req.session.user._id); - await updatePlanProgressInDB(plan._id, percentage, plans); + for (const plan of userPlansFromDB) { + const progress = await calculateProgress(plan, assets, users, req.session.user._id); + await updatePlanProgressInDB(plan._id, progress.percentage, plans); } const updatedUserPlans = await plans.find({ userId: new ObjectId(req.session.user._id) }).toArray(); @@ -122,8 +120,8 @@ module.exports = (middleware, users, plans, assets) => { const userPlansFromDB = await plans.find({ userId: new ObjectId(req.session.userId) }).toArray(); for (const plan of userPlansFromDB) { - const percentage = await calculatePlanProgress(plan, assets, req.session.user._id); - await updatePlanProgressInDB(plan._id, percentage, plans); + const progress = await calculateProgress(plan, assets, users, req.session.user._id); + await updatePlanProgressInDB(plan._id, progress.percentage, plans); } const updatedUserPlans = await plans.find({ userId: new ObjectId(req.session.user._id) }).toArray(); @@ -159,12 +157,15 @@ module.exports = (middleware, users, plans, assets) => { req.session.errMessage = "Plan not found or you do not have permission to view it."; return res.status(status.NotFound).redirect('/plans'); } + const progress = await calculateProgress(plan, assets, users, req.session.userId); + res.render('planDetail', { user: req.session.user, plan: plan, geoData: req.session.geoData, assets: userAssets, + progress: progress, suggestions: await suggestions.generateSuggestions(), }); diff --git a/src/util/calculations.js b/src/util/calculations.js index 25f5d33..19d3222 100644 --- a/src/util/calculations.js +++ b/src/util/calculations.js @@ -42,4 +42,72 @@ async function updatePlanProgressInDB(planId, percentage, plans) { } } -module.exports = { calculatePlanProgress, updatePlanProgressInDB }; \ No newline at end of file + +async function calculateProgress(plan, assets, users, userId) { + if (!plan || typeof plan !== 'object') { + console.error("Error with the plan"); + return; + } + if (!assets || typeof assets.find !== 'function') { + console.error("Error with the assets collection"); + return; + } + if (!users || typeof users.findOne !== 'function') { + console.error("Error with the users collection"); + return; + } + if (!userId) { + console.error("No user ID provided"); + return; + } + + try { + const userAssets = await assets.find({ userId: new ObjectId(userId) }).toArray(); + const totalUserAssetValue = userAssets.reduce((total, asset) => total + asset.value, 0); + const totalUserPlanValue = plan.retirementAssets; + + const userDoc = await users.findOne({ _id: new ObjectId(userId) }); + if (!userDoc || !userDoc.dob) { + console.error("User document or DOB not found for userId:", userId); + return { monthlyInvestment: NaN, totalCostOfRetirement: NaN, monthsUntilRetirement: NaN, yearsRetired: NaN, percentage: NaN }; + } + const userDob = new Date(userDoc.dob); + + if (isNaN(userDob.getTime())) { + console.error("userDob is an invalid date. Aborting calculation."); + return { monthlyInvestment: NaN, totalCostOfRetirement: NaN, monthsUntilRetirement: NaN, yearsRetired: NaN, percentage: NaN }; + } + + const today = new Date(); + const userUnalivedBy = new Date(userDob); + userUnalivedBy.setFullYear(userUnalivedBy.getFullYear() + 90); + const yearOfRetirement = userDob.getFullYear() + plan.retirementAge; + const monthsUntilRetirement = (yearOfRetirement - today.getFullYear()) * 12; + const yearsRetired = userUnalivedBy.getFullYear() - yearOfRetirement; + + const totalCostOfRetirement = ((plan.retirementExpenses + plan.retirementLiabilities) * 12) * yearsRetired; + + const monthlyInvestment = (totalUserPlanValue - totalUserAssetValue + totalCostOfRetirement) / monthsUntilRetirement; + + const percentageCalculated = (totalUserAssetValue / (totalUserPlanValue + totalCostOfRetirement)) * 100; + + const progress = {}; + + progress.monthlyInvestment = Math.round(monthlyInvestment); + progress.totalCostOfRetirement = totalCostOfRetirement; + progress.monthsUntilRetirement = monthsUntilRetirement; + progress.yearsRetired = yearsRetired; + progress.yearsUntilRetirement = (yearOfRetirement - today.getFullYear()); + progress.percentage = percentageCalculated; + + return progress; + + } catch (err) { + console.error("Error in calculateProgress:", err); + return; + } +} + + + +module.exports = { calculatePlanProgress, updatePlanProgressInDB, calculateProgress}; \ No newline at end of file diff --git a/src/views/newPlan.ejs b/src/views/newPlan.ejs index c1ae0e7..d337639 100644 --- a/src/views/newPlan.ejs +++ b/src/views/newPlan.ejs @@ -2,7 +2,6 @@ <%- include("./partials/header") %>
-

Welcome: <%= user.name %>

Retirement Plan

diff --git a/src/views/planDetail.ejs b/src/views/planDetail.ejs index 2d0729e..0541b29 100644 --- a/src/views/planDetail.ejs +++ b/src/views/planDetail.ejs @@ -2,9 +2,7 @@ <%- include("./partials/header") %>
-

Welcome: <%= user.name %>

-

<%= plan.name %>

@@ -19,6 +17,13 @@
+
+
+ Calculated Monthly Investment + <%- new Intl.NumberFormat('en-US', { style: 'currency', currency: geoData.currency ? geoData.currency : 'CAD' }).format(progress.monthlyInvestment > 0 ? progress.monthlyInvestment : 0) %> +
+
+

Assets:

@@ -29,7 +34,7 @@
-

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

+

<%- new Intl.NumberFormat('en-US', { style: 'currency', currency: geoData.currency ? geoData.currency : 'CAD' }).format(assets.reduce((total, asset) => total + asset.value, 0)) %>

@@ -43,16 +48,32 @@

<%= plan.retirementAge %>

- -

<%= plan.retirementExpenses %>

+ +

<%- new Intl.NumberFormat('en-US', { style: 'currency', currency: geoData.currency ? geoData.currency : 'CAD' }).format(plan.retirementExpenses) %>

- -

<%= plan.retirementAssets %>

+ +

<%- new Intl.NumberFormat('en-US', { style: 'currency', currency: geoData.currency ? geoData.currency : 'CAD' }).format(plan.retirementAssets) %>

- -

<%= plan.retirementLiabilities %>

+ +

<%- new Intl.NumberFormat('en-US', { style: 'currency', currency: geoData.currency ? geoData.currency : 'CAD' }).format(plan.retirementLiabilities) %>

+
+
+ +

<%- progress.yearsUntilRetirement %>

+
+
+ +

<%- progress.yearsRetired %>

+
+
+ +

<%- new Intl.NumberFormat('en-US', { style: 'currency', currency: geoData.currency ? geoData.currency : 'CAD' }).format(progress.totalCostOfRetirement) %>

+
+
+ +

<%- new Intl.NumberFormat('en-US', { style: 'currency', currency: geoData.currency ? geoData.currency : 'CAD' }).format(progress.totalCostOfRetirement + progress.monthlyInvestment * progress.monthsUntilRetirement) %>

diff --git a/src/views/plans.ejs b/src/views/plans.ejs index 343256a..950eede 100644 --- a/src/views/plans.ejs +++ b/src/views/plans.ejs @@ -2,7 +2,6 @@ <%- include("./partials/header") %>
-

Welcome: <%= user.name %>

My Retirement Plans

New Plan