From 63de1d12b07af4f84cc32fa5407af4e2edeaddb6 Mon Sep 17 00:00:00 2001 From: Tim Kent Date: Fri, 20 Oct 2023 09:21:52 -0700 Subject: [PATCH 1/5] add bm proj route, router, controller --- .../bmdashboard/bmProjectsController.js | 18 ++++++++++++++++++ src/routes/bmdashboard/bmMaterialsRouter.js | 4 ++-- src/routes/bmdashboard/bmProjectsRouter.js | 14 ++++++++++++++ src/startup/routes.js | 2 ++ 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 src/controllers/bmdashboard/bmProjectsController.js create mode 100644 src/routes/bmdashboard/bmProjectsRouter.js diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js new file mode 100644 index 000000000..946869bce --- /dev/null +++ b/src/controllers/bmdashboard/bmProjectsController.js @@ -0,0 +1,18 @@ +const mongoose = require('mongoose'); + +const bmMProjectsController = function () { + // fetches projects with reference to BM userProfile id + const bmProjectsSummary = async function _projSumm(req, res) { + try { + res.json({ message: 'Hello world' }); + + // .then(results => res.status(200).send(results)) + // .catch(error => res.status(500).send(error)) + } catch (err) { + res.json(err); + } + }; + return { bmProjectsSummary }; +}; + +module.exports = bmMProjectsController; diff --git a/src/routes/bmdashboard/bmMaterialsRouter.js b/src/routes/bmdashboard/bmMaterialsRouter.js index ab8a67388..1188acf9d 100644 --- a/src/routes/bmdashboard/bmMaterialsRouter.js +++ b/src/routes/bmdashboard/bmMaterialsRouter.js @@ -8,6 +8,6 @@ materialsRouter.route('/materials') .get(controller.bmMaterialsList); return materialsRouter; -} +}; -module.exports = routes; \ No newline at end of file +module.exports = routes; diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js new file mode 100644 index 000000000..204efbfad --- /dev/null +++ b/src/routes/bmdashboard/bmProjectsRouter.js @@ -0,0 +1,14 @@ +const express = require('express'); + +const routes = function () { + const projectsRouter = express.Router(); + const controller = require('../../controllers/bmdashboard/bmProjectsController')(); +// const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial); + +projectsRouter.route('/projects') + .get(controller.bmProjectsSummary); + + return projectsRouter; +}; + +module.exports = routes; diff --git a/src/startup/routes.js b/src/startup/routes.js index 2fd7337a6..7208535d8 100644 --- a/src/startup/routes.js +++ b/src/startup/routes.js @@ -61,6 +61,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe // bm dashboard const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')(); const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial); +const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')(); module.exports = function (app) { app.use('/api', forgotPwdRouter); @@ -96,4 +97,5 @@ module.exports = function (app) { // bm dashboard app.use('/api/bm', bmLoginRouter); app.use('/api/bm', bmMaterialsRouter); + app.use('/api/bm', bmProjectsRouter); }; From 815b0f5ae588efb855fbde13fa65f301280b7686 Mon Sep 17 00:00:00 2001 From: Tim Kent Date: Thu, 26 Oct 2023 13:23:24 -0700 Subject: [PATCH 2/5] update projects controller to return basic proj info --- .../bmdashboard/bmMaterialsController.js | 24 +++++++++---------- .../bmdashboard/bmProjectsController.js | 23 ++++++++++++++---- src/routes/bmdashboard/bmProjectsRouter.js | 7 +++--- src/startup/routes.js | 2 +- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/controllers/bmdashboard/bmMaterialsController.js b/src/controllers/bmdashboard/bmMaterialsController.js index a31ed460e..fb6003e90 100644 --- a/src/controllers/bmdashboard/bmMaterialsController.js +++ b/src/controllers/bmdashboard/bmMaterialsController.js @@ -1,4 +1,4 @@ -const mongoose = require('mongoose') +const mongoose = require('mongoose'); const bmMaterialsController = function (ItemMaterial) { const bmMaterialsList = async function _matsList(req, res) { @@ -7,37 +7,37 @@ const bmMaterialsController = function (ItemMaterial) { .populate([ { path: 'project', - select: '_id projectName' + select: '_id projectName', }, { path: 'inventoryItemType', - select: '_id name uom totalStock totalAvailable' + select: '_id name uom totalStock totalAvailable', }, { path: 'usageRecord', populate: { path: 'createdBy', - select: '_id firstName lastName' - } + select: '_id firstName lastName', + }, }, { path: 'updateRecord', populate: { path: 'createdBy', - select: '_id firstName lastName' - } + select: '_id firstName lastName', + }, }, { path: 'purchaseRecord', populate: { path: 'createdBy', - select: '_id firstName lastName' - } - } + select: '_id firstName lastName', + }, + }, ]) .exec() .then(results => res.status(200).send(results)) - .catch(error => res.status(500).send(error)) + .catch(error => res.status(500).send(error)); } catch (err) { res.json(err); } @@ -45,4 +45,4 @@ const bmMaterialsController = function (ItemMaterial) { return { bmMaterialsList }; }; -module.exports = bmMaterialsController; \ No newline at end of file +module.exports = bmMaterialsController; diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js index 946869bce..f80eea6c0 100644 --- a/src/controllers/bmdashboard/bmProjectsController.js +++ b/src/controllers/bmdashboard/bmProjectsController.js @@ -1,13 +1,26 @@ const mongoose = require('mongoose'); -const bmMProjectsController = function () { - // fetches projects with reference to BM userProfile id +const bmMProjectsController = function (UserProfile) { const bmProjectsSummary = async function _projSumm(req, res) { + const { userId } = req.params; try { - res.json({ message: 'Hello world' }); + const projectData = await UserProfile + // fetch user profile, return only projects array + .findOne({ _id: userId }, { projects: 1 }) + // populate data with projects documents using the ObjectId in the projects array + .populate({ + path: 'projects', + // limit to projects with category value 'Housing' + match: { category: 'Housing' }, + // returns only these fields + select: '_id projectName isActive createdDatetime', + }) + .exec() + .then(result => result.projects) + .catch(error => res.status(500).send(error)); - // .then(results => res.status(200).send(results)) - // .catch(error => res.status(500).send(error)) + // for each project, find all materials in the project + res.status(200).send(projectData); } catch (err) { res.json(err); } diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js index 204efbfad..05adfa59d 100644 --- a/src/routes/bmdashboard/bmProjectsRouter.js +++ b/src/routes/bmdashboard/bmProjectsRouter.js @@ -1,11 +1,10 @@ const express = require('express'); -const routes = function () { +const routes = function (userProfile) { const projectsRouter = express.Router(); - const controller = require('../../controllers/bmdashboard/bmProjectsController')(); -// const controller = require('../../controllers/bmdashboard/bmMaterialsController')(itemMaterial); + const controller = require('../../controllers/bmdashboard/bmProjectsController')(userProfile); -projectsRouter.route('/projects') +projectsRouter.route('/projects/:userId') .get(controller.bmProjectsSummary); return projectsRouter; diff --git a/src/startup/routes.js b/src/startup/routes.js index 7208535d8..aa786dbbd 100644 --- a/src/startup/routes.js +++ b/src/startup/routes.js @@ -61,7 +61,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe // bm dashboard const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')(); const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial); -const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')(); +const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')(userProfile); module.exports = function (app) { app.use('/api', forgotPwdRouter); From 66c6c3c8d8d1f637efc7cb850b03f269149f428c Mon Sep 17 00:00:00 2001 From: Tim Kent Date: Wed, 1 Nov 2023 09:22:24 -0700 Subject: [PATCH 3/5] add building project schema. update project summary controller. --- .../bmdashboard/bmProjectController.js | 27 ++++++++++++++++ .../bmdashboard/bmProjectsController.js | 31 ------------------- src/models/bmdashboard/buildingProject.js | 15 +++++++++ src/models/inventoryItemMaterial.js | 6 ++-- src/routes/bmdashboard/bmProjectRouter.js | 13 ++++++++ src/routes/bmdashboard/bmProjectsRouter.js | 13 -------- src/startup/routes.js | 6 ++-- 7 files changed, 62 insertions(+), 49 deletions(-) create mode 100644 src/controllers/bmdashboard/bmProjectController.js delete mode 100644 src/controllers/bmdashboard/bmProjectsController.js create mode 100644 src/models/bmdashboard/buildingProject.js create mode 100644 src/routes/bmdashboard/bmProjectRouter.js delete mode 100644 src/routes/bmdashboard/bmProjectsRouter.js diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js new file mode 100644 index 000000000..96f19ab60 --- /dev/null +++ b/src/controllers/bmdashboard/bmProjectController.js @@ -0,0 +1,27 @@ +const bmMProjectController = function (BuildingProject) { + const bmProjectSummary = async function _projSumm(req, res) { + try { + const projectData = await BuildingProject + .find() + .populate([ + { + path: 'buildingManager', + select: '_id firstName lastName email', + }, + { + path: 'team', + select: '_id firstName lastName email', + }, + ]) + .exec() + .then(result => result) + .catch(error => res.status(500).send(error)); + res.status(200).send(projectData); + } catch (err) { + res.json(err); + } + }; + return { bmProjectSummary }; +}; + +module.exports = bmMProjectController; diff --git a/src/controllers/bmdashboard/bmProjectsController.js b/src/controllers/bmdashboard/bmProjectsController.js deleted file mode 100644 index f80eea6c0..000000000 --- a/src/controllers/bmdashboard/bmProjectsController.js +++ /dev/null @@ -1,31 +0,0 @@ -const mongoose = require('mongoose'); - -const bmMProjectsController = function (UserProfile) { - const bmProjectsSummary = async function _projSumm(req, res) { - const { userId } = req.params; - try { - const projectData = await UserProfile - // fetch user profile, return only projects array - .findOne({ _id: userId }, { projects: 1 }) - // populate data with projects documents using the ObjectId in the projects array - .populate({ - path: 'projects', - // limit to projects with category value 'Housing' - match: { category: 'Housing' }, - // returns only these fields - select: '_id projectName isActive createdDatetime', - }) - .exec() - .then(result => result.projects) - .catch(error => res.status(500).send(error)); - - // for each project, find all materials in the project - res.status(200).send(projectData); - } catch (err) { - res.json(err); - } - }; - return { bmProjectsSummary }; -}; - -module.exports = bmMProjectsController; diff --git a/src/models/bmdashboard/buildingProject.js b/src/models/bmdashboard/buildingProject.js new file mode 100644 index 000000000..566bc124e --- /dev/null +++ b/src/models/bmdashboard/buildingProject.js @@ -0,0 +1,15 @@ +const mongoose = require('mongoose'); + +const { Schema } = mongoose; + +const buildingProject = new Schema({ + isActive: Boolean, + name: String, + template: String, // construction template (ie Earthbag Village) + location: String, // use lat/lng instead? + dateCreated: { type: Date, default: Date.now }, + buildingManager: { type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }, // BM's id + team: [{ type: mongoose.SchemaTypes.ObjectId, ref: 'userProfile' }], +}); + +module.exports = mongoose.model('buildingProject', buildingProject, 'buildingProjects'); diff --git a/src/models/inventoryItemMaterial.js b/src/models/inventoryItemMaterial.js index e6153af45..8460ecd6e 100644 --- a/src/models/inventoryItemMaterial.js +++ b/src/models/inventoryItemMaterial.js @@ -29,12 +29,12 @@ const InventoryItemMaterial = new Schema({ poId: { type: String, required: true }, sellerId: { type: String, required: true }, quantity: { type: Number, required: true }, // adds to stockBought - unitPrice: {type: Number, required: true}, + unitPrice: { type: Number, required: true }, currency: { type: String, required: true }, subtotal: { type: Number, required: true }, tax: { type: Number, required: true }, shipping: { type: Number, required: true }, - }] -}) + }], +}); module.exports = mongoose.model('inventoryItemMaterial', InventoryItemMaterial, 'inventoryMaterial'); diff --git a/src/routes/bmdashboard/bmProjectRouter.js b/src/routes/bmdashboard/bmProjectRouter.js new file mode 100644 index 000000000..6bd535ae1 --- /dev/null +++ b/src/routes/bmdashboard/bmProjectRouter.js @@ -0,0 +1,13 @@ +const express = require('express'); + +const routes = function (buildingProject) { + const projectRouter = express.Router(); + const controller = require('../../controllers/bmdashboard/bmProjectController')(buildingProject); + +projectRouter.route('/projects') + .get(controller.bmProjectSummary); + + return projectRouter; +}; + +module.exports = routes; diff --git a/src/routes/bmdashboard/bmProjectsRouter.js b/src/routes/bmdashboard/bmProjectsRouter.js deleted file mode 100644 index 05adfa59d..000000000 --- a/src/routes/bmdashboard/bmProjectsRouter.js +++ /dev/null @@ -1,13 +0,0 @@ -const express = require('express'); - -const routes = function (userProfile) { - const projectsRouter = express.Router(); - const controller = require('../../controllers/bmdashboard/bmProjectsController')(userProfile); - -projectsRouter.route('/projects/:userId') - .get(controller.bmProjectsSummary); - - return projectsRouter; -}; - -module.exports = routes; diff --git a/src/startup/routes.js b/src/startup/routes.js index aa786dbbd..7f9446315 100644 --- a/src/startup/routes.js +++ b/src/startup/routes.js @@ -22,6 +22,8 @@ const profileInitialSetuptoken = require('../models/profileInitialSetupToken'); const reason = require('../models/reason'); const mouseoverText = require('../models/mouseoverText'); const inventoryItemMaterial = require('../models/inventoryItemMaterial'); +const buildingProject = require('../models/bmdashboard/buildingProject'); + const userProfileRouter = require('../routes/userProfileRouter')(userProfile); const badgeRouter = require('../routes/badgeRouter')(badge); @@ -61,7 +63,7 @@ const mouseoverTextRouter = require('../routes/mouseoverTextRouter')(mouseoverTe // bm dashboard const bmLoginRouter = require('../routes/bmdashboard/bmLoginRouter')(); const bmMaterialsRouter = require('../routes/bmdashboard/bmMaterialsRouter')(inventoryItemMaterial); -const bmProjectsRouter = require('../routes/bmdashboard/bmProjectsRouter')(userProfile); +const bmProjectRouter = require('../routes/bmdashboard/bmProjectRouter')(buildingProject); module.exports = function (app) { app.use('/api', forgotPwdRouter); @@ -97,5 +99,5 @@ module.exports = function (app) { // bm dashboard app.use('/api/bm', bmLoginRouter); app.use('/api/bm', bmMaterialsRouter); - app.use('/api/bm', bmProjectsRouter); + app.use('/api/bm', bmProjectRouter); }; From 0058b42a8bd1b7ad00cd4e9aeec2007ec40c6c2d Mon Sep 17 00:00:00 2001 From: Tim Kent Date: Mon, 6 Nov 2023 13:02:46 -0800 Subject: [PATCH 4/5] add fetch single project api. update fetch all projects query. --- .../bmdashboard/bmProjectController.js | 43 +++++++++++++++++-- src/routes/bmdashboard/bmProjectRouter.js | 7 ++- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js index 96f19ab60..3e88ea08a 100644 --- a/src/controllers/bmdashboard/bmProjectController.js +++ b/src/controllers/bmdashboard/bmProjectController.js @@ -1,8 +1,10 @@ const bmMProjectController = function (BuildingProject) { - const bmProjectSummary = async function _projSumm(req, res) { - try { + // fetches all projects by building manager id + const fetchAllProjects = async (req, res) => { + const { userId } = req.params; + try { const projectData = await BuildingProject - .find() + .find({ buildingManager: userId }) .populate([ { path: 'buildingManager', @@ -21,7 +23,40 @@ const bmMProjectController = function (BuildingProject) { res.json(err); } }; - return { bmProjectSummary }; + + // fetches single project by project id + const fetchSingleProject = async (req, res) => { + const { userId, projectId } = req.params; + try { + BuildingProject + .findById(projectId) + .populate([ + { + path: 'buildingManager', + select: '_id firstName lastName email', + }, + { + path: 'team', + select: '_id firstName lastName email', + }, + ]) + .exec() + .then((project) => { + // authenticate request by comparing userId param with buildingManager id field + // ObjectId must be converted to string + if (userId !== project.buildingManager._id.toString()) { + return res.status(403).send({ + message: 'You are not authorized to view this record.', + }); + } + return res.status(200).send(project); + }) + .catch(error => res.status(500).send(error)); + } catch (err) { + res.json(err); + } + }; + return { fetchAllProjects, fetchSingleProject }; }; module.exports = bmMProjectController; diff --git a/src/routes/bmdashboard/bmProjectRouter.js b/src/routes/bmdashboard/bmProjectRouter.js index 6bd535ae1..7069950dc 100644 --- a/src/routes/bmdashboard/bmProjectRouter.js +++ b/src/routes/bmdashboard/bmProjectRouter.js @@ -4,8 +4,11 @@ const routes = function (buildingProject) { const projectRouter = express.Router(); const controller = require('../../controllers/bmdashboard/bmProjectController')(buildingProject); -projectRouter.route('/projects') - .get(controller.bmProjectSummary); +projectRouter.route('/projects/:userId') + .get(controller.fetchAllProjects); + +projectRouter.route('/projects/:userId/:projectId') + .get(controller.fetchSingleProject); return projectRouter; }; From ec5d40584a18cd5de8d8b6f255dc54acc68a2f20 Mon Sep 17 00:00:00 2001 From: Tim Kent Date: Tue, 7 Nov 2023 12:41:53 -0800 Subject: [PATCH 5/5] update project routes. add auth checks to controllers. --- .../bmdashboard/bmProjectController.js | 47 +++++++++++++------ src/routes/bmdashboard/bmProjectRouter.js | 4 +- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/controllers/bmdashboard/bmProjectController.js b/src/controllers/bmdashboard/bmProjectController.js index 3e88ea08a..929aba4ba 100644 --- a/src/controllers/bmdashboard/bmProjectController.js +++ b/src/controllers/bmdashboard/bmProjectController.js @@ -1,10 +1,21 @@ +// TODO: uncomment when executing auth checks +// const jwt = require('jsonwebtoken'); +// const config = require('../../config'); + const bmMProjectController = function (BuildingProject) { - // fetches all projects by building manager id + // TODO: uncomment when executing auth checks + // const { JWT_SECRET } = config; + const fetchAllProjects = async (req, res) => { - const { userId } = req.params; - try { + //! Note: for easier testing this route currently returns all projects from the db + // TODO: uncomment the lines below to return only projects where field buildingManager === userid + // const token = req.headers.authorization; + // const { userid } = jwt.verify(token, JWT_SECRET); + try { const projectData = await BuildingProject - .find({ buildingManager: userId }) + // TODO: uncomment this line to filter by buildingManager field + // .find({ buildingManager: userid }) + .find() .populate([ { path: 'buildingManager', @@ -26,7 +37,11 @@ const bmMProjectController = function (BuildingProject) { // fetches single project by project id const fetchSingleProject = async (req, res) => { - const { userId, projectId } = req.params; + //! Note: for easier testing this route currently returns the project without an auth check + // TODO: uncomment the lines below to check the user's ability to view the current project + // const token = req.headers.authorization; + // const { userid } = jwt.verify(token, JWT_SECRET); + const { projectId } = req.params; try { BuildingProject .findById(projectId) @@ -41,16 +56,18 @@ const bmMProjectController = function (BuildingProject) { }, ]) .exec() - .then((project) => { - // authenticate request by comparing userId param with buildingManager id field - // ObjectId must be converted to string - if (userId !== project.buildingManager._id.toString()) { - return res.status(403).send({ - message: 'You are not authorized to view this record.', - }); - } - return res.status(200).send(project); - }) + .then(project => res.status(200).send(project)) + // TODO: uncomment this block to execute the auth check + // authenticate request by comparing userId param with buildingManager id field + // Note: _id has type object and must be converted to string + // .then((project) => { + // if (userid !== project.buildingManager._id.toString()) { + // return res.status(403).send({ + // message: 'You are not authorized to view this record.', + // }); + // } + // return res.status(200).send(project); + // }) .catch(error => res.status(500).send(error)); } catch (err) { res.json(err); diff --git a/src/routes/bmdashboard/bmProjectRouter.js b/src/routes/bmdashboard/bmProjectRouter.js index 7069950dc..d60ea9b2b 100644 --- a/src/routes/bmdashboard/bmProjectRouter.js +++ b/src/routes/bmdashboard/bmProjectRouter.js @@ -4,10 +4,10 @@ const routes = function (buildingProject) { const projectRouter = express.Router(); const controller = require('../../controllers/bmdashboard/bmProjectController')(buildingProject); -projectRouter.route('/projects/:userId') +projectRouter.route('/projects') .get(controller.fetchAllProjects); -projectRouter.route('/projects/:userId/:projectId') +projectRouter.route('/project/:projectId') .get(controller.fetchSingleProject); return projectRouter;