Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion src/app.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const express = require('express');
const Sentry = require('@sentry/node');
const testRoutes = require('./routes/testRoutes');

Check warning on line 3 in src/app.js

View workflow job for this annotation

GitHub Actions / Lint Check

There should be no empty line between import groups

const app = express();
const logger = require('./startup/logger');
const globalErrorHandler = require('./utilities/errorHandling/globalErrorHandler');

Check warning on line 7 in src/app.js

View workflow job for this annotation

GitHub Actions / Lint Check

There should be no empty line between import groups
// const experienceRoutes = require('./routes/applicantAnalyticsRoutes');

logger.init();
Expand All @@ -15,12 +15,12 @@
require('./startup/compression')(app);
require('./startup/cors')(app);
require('./startup/bodyParser')(app);
require('./startup/session')(app); // Add session before middleware and routes
require('./startup/session')(app); // Add session before middleware and routes

app.use('/api/test', testRoutes);

const helpFeedbackRouter = require('./routes/helpFeedbackRouter');
const helpRequestRouter = require('./routes/helpRequestRouter');

Check warning on line 23 in src/app.js

View workflow job for this annotation

GitHub Actions / Lint Check

There should be no empty line between import groups

app.use('/api/feedback', helpFeedbackRouter);
app.use('/api/helprequest', helpRequestRouter);
Expand Down
199 changes: 67 additions & 132 deletions src/controllers/bmdashboard/bmInventoryTypeController.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
const fs = require('fs');
const fsPromises = require('fs/promises');
const path = require('path');
const mongoose = require('mongoose');

const filename = 'BuildingUnits.json';
const currentFilePath = __filename;
const rootPath = path.resolve(path.dirname(currentFilePath), '../../../'); // Go up three levels to the root
const filepath = path.join(rootPath, filename);
const { readFile } = fs;
const { writeFile } = fs;

function bmInventoryTypeController(
InvType,
MatType,
ConsType,
ReusType,
ToolType,
EquipType,
BuildingUnit,
invTypeHistory,
) {
async function fetchMaterialTypes(req, res) {
Expand Down Expand Up @@ -78,23 +69,10 @@ function bmInventoryTypeController(

const fetchInvUnitsFromJson = async (req, res) => {
try {
// console.log(__dirname,filepath)
readFile(filepath, 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
res.status(500).send(err);
}

try {
const jsonData = JSON.parse(data);
res.status(200).send(jsonData);
} catch (parseError) {
console.error('Error parsing JSON:', parseError);
res.status(500).send(parseError);
}
});
const units = await BuildingUnit.find().exec();
res.status(200).send(units);
} catch (err) {
res.json(err);
res.status(500).json({ error: err.message });
}
};

Expand All @@ -119,31 +97,20 @@ function bmInventoryTypeController(
createdBy: requestorId,
};
MatType.create(newDoc)
.then((results) => {
.then(async (results) => {
res.status(201).send(results);
if (req.body.customUnit) {
try {
// Add new unit to json file : src\controllers\bmdashboard\BuildingUnits.json
const newItem = { unit: req.body.customUnit, category: 'Material' };
const newItemString = JSON.stringify(newItem, null, 2);
readFile(filepath, 'utf8', (err, data) => {
if (err) {
console.error('Error reading file:', err);
return;
}
// Remove the last array bracket and comma
const updatedContent = data.trim().replace(/\s*]$/, '');

// Add a comma and newline if the file is not empty
const separator = updatedContent !== '' ? ',\n' : '';
const updatedFileContent = `${updatedContent}${separator}${newItemString}\n]`;

writeFile(filepath, updatedFileContent, 'utf8', (error) => {
if (error) {
console.error('Error writing to file:', error);
}
const trimmedUnit = req.body.customUnit.trim();
const exists = await BuildingUnit.findOne({
unit: trimmedUnit,
}).collation({ locale: 'en', strength: 2 });
if (!exists) {
await BuildingUnit.create({
unit: trimmedUnit,
category: 'Material',
});
});
}
} catch (e) {
console.log(e);
}
Expand Down Expand Up @@ -208,7 +175,7 @@ function bmInventoryTypeController(
}
}

async function addToolType(req, res) {
async function addPurchasableItemType(Model, category, req, res) {
const {
name,
description,
Expand All @@ -230,13 +197,13 @@ function bmInventoryTypeController(
} = req.body;

try {
ToolType.find({ name })
Model.find({ name })
.then((result) => {
if (result.length) {
res.status(409).send('Oops!! Tool already exists!');
res.status(409).send(`Oops!! ${category} already exists!`);
} else {
const newDoc = {
category: 'Tool',
category,
name,
description,
invoice,
Expand All @@ -255,7 +222,7 @@ function bmInventoryTypeController(
link,
createdBy: requestorId,
};
ToolType.create(newDoc)
Model.create(newDoc)
.then((results) => {
res.status(201).send(results);
})
Expand All @@ -276,6 +243,14 @@ function bmInventoryTypeController(
}
}

async function addToolType(req, res) {
return addPurchasableItemType(ToolType, 'Tool', req, res);
}

async function addReusableType(req, res) {
return addPurchasableItemType(ReusType, 'Reusable', req, res);
}

async function fetchInventoryByType(req, res) {
const { type } = req.params;
let SelectedType = InvType;
Expand Down Expand Up @@ -361,41 +336,6 @@ function bmInventoryTypeController(
}
}

async function addReusableType(req, res) {
const {
name,
description,
requestor: { requestorId },
} = req.body;
try {
ReusType.find({ name })
.then((result) => {
if (result.length) {
res.status(409).send();
} else {
const newDoc = {
category: 'Reusable',
name,
description,
createdBy: requestorId,
};
ReusType.create(newDoc)
.then(() => res.status(201).send())
.catch((error) => {
if (error._message.includes('validation failed')) {
res.status(400).send(error);
} else {
res.status(500).send(error);
}
});
}
})
.catch((error) => res.status(500).send(error));
} catch (error) {
res.status(500).send(error);
}
}

const fetchSingleInventoryType = async (req, res) => {
const { invtypeId } = req.params;
try {
Expand Down Expand Up @@ -503,60 +443,54 @@ function bmInventoryTypeController(
}
};

const addInvUnit = async (req, res) => {
// NOTE: category is default to be Material as no other item types need units
const { unit, category = 'Material' } = req.body;
if (typeof unit !== 'string' || unit.length === 0) {
res.status(400).json('Invalid unit');
return;
}

const addInventoryUnit = async (req, res) => {
try {
// read JSON file and parse it into an array
const unitsJSON = await fsPromises.readFile(filepath, { encoding: 'utf8' });
const unitsArray = JSON.parse(unitsJSON);
const { category } = req.body;
const unit = req.body.unit?.trim();

// append new unit into array
unitsArray.push({ unit, category });
if (!unit) {
return res.status(400).json({ error: 'Unit is required' });
}

// save updated array into JSON file and rend it back
await fsPromises.writeFile(filepath, JSON.stringify(unitsArray, null, ' '));
const exists = await BuildingUnit.findOne({
unit,
}).collation({ locale: 'en', strength: 2 });
if (exists) {
return res.status(409).json({ error: 'Unit already exists' });
}

res.status(201).send(unitsArray);
} catch (err) {
res.status(500).send(err);
console.error(err);
const newUnit = await BuildingUnit.create({ unit, category: category || 'Material' });
res.status(201).json(newUnit);
} catch (error) {
res.status(500).json({ error: error.message });
}
};

const deleteInvUnit = async (req, res) => {
const { unit } = req.body;
if (typeof unit !== 'string' || unit.length === 0) {
res.status(400).json('Invalid unit');
return;
}

const deleteInventoryUnit = async (req, res) => {
try {
// read JSON file and parse it into an array
const unitsJSON = await fsPromises.readFile(filepath, { encoding: 'utf8' });
const unitsArray = JSON.parse(unitsJSON);

// if unit does not exist, send err response
const index = unitsArray.findIndex((unitObject) => unitObject.unit === unit);
if (index === -1) {
res.status(400).json('Unit does not exist');
return;
const { unitName } = req.params;

if (!unitName) {
return res.status(400).json({ error: 'Unit identifier is required' });
}

// otherwise, remove unit
const filteredUnits = unitsArray.filter((unitObject) => unitObject.unit !== unit);
let deleted;
if (unitName.match(/^[0-9a-fA-F]{24}$/)) {
deleted = await BuildingUnit.findByIdAndDelete(unitName);
} else {
const decodedUnitName = decodeURIComponent(unitName).trim();
deleted = await BuildingUnit.findOneAndDelete({
unit: decodedUnitName,
}).collation({ locale: 'en', strength: 2 });
}

// save updated array into JSON file and rend it back
await fsPromises.writeFile(filepath, JSON.stringify(filteredUnits, null, ' '));
res.status(200).send(filteredUnits);
} catch (err) {
res.status(500).send(err);
console.error(err);
if (!deleted) {
return res.status(404).json({ error: 'Unit not found' });
}

res.status(200).json({ message: 'Unit deleted successfully' });
} catch (error) {
res.status(500).json({ error: error.message });
}
};

Expand Down Expand Up @@ -743,6 +677,7 @@ function bmInventoryTypeController(
res.status(500).json({ message: 'Failed to fetch inventory history' });
}
};

return {
fetchMaterialTypes,
fetchConsumableTypes,
Expand All @@ -758,8 +693,8 @@ function bmInventoryTypeController(
updateNameAndUnit,
fetchInvUnitsFromJson,
fetchInventoryByType,
addInvUnit,
deleteInvUnit,
addInventoryUnit,
deleteInventoryUnit,
updateSingleInvType,
deleteSingleInvType,
fetchInvTypeHistory,
Expand Down
9 changes: 7 additions & 2 deletions src/controllers/progressController.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,10 @@ const progressController = function () {
}

// Check if progress record already exists
const existingProgress = await Progress.findOne({ studentId: sanitizedStudentId, atomId: sanitizedAtomId });
const existingProgress = await Progress.findOne({
studentId: sanitizedStudentId,
atomId: sanitizedAtomId,
});
if (existingProgress) {
return res
.status(400)
Expand Down Expand Up @@ -532,7 +535,9 @@ const progressController = function () {
.select('name description difficulty moleculeType subjectId');

// Find unearned atoms (atoms not in progress records)
const progressAtomIds = new Set(progressRecords.map((p) => p.atomId?._id.toString()).filter(Boolean));
const progressAtomIds = new Set(
progressRecords.map((p) => p.atomId?._id.toString()).filter(Boolean),
);
const unearnedAtoms = allAtoms
.filter((atom) => !progressAtomIds.has(atom._id.toString()))
.map((atom) => ({
Expand Down
2 changes: 1 addition & 1 deletion src/models/bmdashboard/buildingIssue.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@ buildingIssue.index({ issueDate: 1 });
// This index supports queries that filter by multiple criteria simultaneously
buildingIssue.index({ projectId: 1, issueType: 1, issueDate: 1 });

module.exports = mongoose.model('buildingIssue', buildingIssue, 'buildingIssues');
module.exports = mongoose.model('buildingIssue', buildingIssue, 'buildingIssues');
10 changes: 10 additions & 0 deletions src/models/bmdashboard/buildingUnit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const mongoose = require('mongoose');

const { Schema } = mongoose;

const buildingUnitSchema = new Schema({
unit: { type: String, required: true, unique: true },
category: { type: String, default: 'Material' },
});

module.exports = mongoose.model('buildingUnit', buildingUnitSchema, 'buildingUnits');
2 changes: 1 addition & 1 deletion src/routes/blueskyRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ router.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
return res.status(400).json({
success: false,
error: 'Image upload failed: ' + err.message,
error: `Image upload failed: ${err.message}`,
});
}

Expand Down
9 changes: 6 additions & 3 deletions src/routes/bmdashboard/bmInventoryTypeRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const routes = function (
reusType,
toolType,
equipType,
buildingUnit,
invTypeHistory,
) {
const inventoryTypeRouter = express.Router();
Expand All @@ -17,6 +18,7 @@ const routes = function (
reusType,
toolType,
equipType,
buildingUnit,
invTypeHistory,
);

Expand All @@ -31,7 +33,7 @@ const routes = function (

inventoryTypeRouter.route('/tools').post(controller.addToolType);

inventoryTypeRouter.route('/invtypes/reusables').post(controller.addReusableType);
inventoryTypeRouter.route('/invtypes/reusable').post(controller.addReusableType);

inventoryTypeRouter.route('/invtypes/tools').get(controller.fetchToolTypes);

Expand All @@ -58,8 +60,9 @@ const routes = function (
inventoryTypeRouter
.route('/inventoryUnits')
.get(controller.fetchInvUnitsFromJson)
.post(controller.addInvUnit)
.delete(controller.deleteInvUnit);
.post(controller.addInventoryUnit);

inventoryTypeRouter.route('/inventoryUnits/:unitName').delete(controller.deleteInventoryUnit);

return inventoryTypeRouter;
};
Expand Down
Loading
Loading