Skip to content

Commit cf56d64

Browse files
Merge pull request #2120 from OneCommunityGlobal/development
Backend Release to Main [2.93]
2 parents 5d28df2 + 17be92d commit cf56d64

File tree

19 files changed

+751
-16
lines changed

19 files changed

+751
-16
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
"serve": "babel-node src/server.js",
3030
"prepare-macos-linux": "husky install && chmod ug+x .husky/* && chmod ug+x .git/hooks/*",
3131
"prepare": "husky install",
32-
"install": "npm install --ignore-scripts sharp"
32+
"install": "npm install --ignore-scripts sharp",
33+
"postinstall": "npx puppeteer browsers install chrome"
3334
},
3435
"author": "AK",
3536
"license": "ISC",

src/app.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const express = require('express');
22
const Sentry = require('@sentry/node');
3+
const testRoutes = require('./routes/testRoutes');
34

45
const app = express();
56
const logger = require('./startup/logger');
@@ -15,6 +16,8 @@ require('./startup/compression')(app);
1516
require('./startup/cors')(app);
1617
require('./startup/bodyParser')(app);
1718

19+
app.use('/api/test', testRoutes);
20+
1821
const helpFeedbackRouter = require('./routes/helpFeedbackRouter');
1922
const helpRequestRouter = require('./routes/helpRequestRouter');
2023

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
const KIInventoryItem = require('../../models/kitchenandinventory/KIInventoryItems');
2+
3+
const KIInventoryController = () => {
4+
const addItem = async (req, res) => {
5+
const {
6+
name,
7+
storedQuantity,
8+
unit,
9+
type,
10+
monthlyUsage,
11+
category,
12+
expiryDate,
13+
location,
14+
onsite,
15+
reorderAt,
16+
lastHarvestDate,
17+
nextHarvestDate,
18+
nextHarvestQuantity,
19+
} = req.body;
20+
const newItem = new KIInventoryItem({
21+
name,
22+
storedQuantity,
23+
presentQuantity: storedQuantity,
24+
unit,
25+
type,
26+
monthlyUsage,
27+
category,
28+
expiryDate,
29+
location,
30+
onsite,
31+
reorderAt,
32+
lastHarvestDate,
33+
nextHarvestDate,
34+
nextHarvestQuantity,
35+
});
36+
try {
37+
const savedItem = await newItem.save();
38+
res.status(201).json({
39+
message: 'Inventory item added successfully',
40+
data: savedItem,
41+
});
42+
} catch (error) {
43+
res.status(400).json({ message: error.message });
44+
}
45+
};
46+
const getItems = async (req, res) => {
47+
try {
48+
const items = await KIInventoryItem.find(null, { __v: 0 }).lean().sort({ createdAt: -1 });
49+
res.status(200).json({ message: 'All Items fetched successfully.', data: items });
50+
} catch (err) {
51+
res.status(400).json({ message: 'Something went wrong while fetching items.' });
52+
}
53+
};
54+
const getItemsByCategory = async (req, res) => {
55+
const { category } = req.params;
56+
try {
57+
const items = await KIInventoryItem.find({ category }, { __v: 0 })
58+
.lean()
59+
.sort({ createdAt: -1 });
60+
res.status(200).json({ message: 'Items fetched successfully.', data: items });
61+
} catch (err) {
62+
res.status(400).json({ message: 'Something went wrong while fetching items.' });
63+
}
64+
};
65+
const getPreservedStock = async (req, res) => {
66+
const oneyearFromNow = new Date();
67+
oneyearFromNow.setFullYear(oneyearFromNow.getFullYear() + 1);
68+
try {
69+
const items = await KIInventoryItem.find(
70+
{ category: 'INGREDIENT', expiryDate: { $gte: oneyearFromNow } },
71+
{ __v: 0 },
72+
)
73+
.lean()
74+
.sort({ presentQuantity: -1 });
75+
res.status(200).json({ message: 'Preserved stock items fetched successfully.', data: items });
76+
} catch (err) {
77+
res
78+
.status(400)
79+
.json({ message: 'Something went wrong while fetching preserved stock items.' });
80+
}
81+
};
82+
const updateOnUsage = async (req, res) => {
83+
const { itemId, usedQuantity } = req.body;
84+
if (usedQuantity <= 0) {
85+
return res.status(400).json({ message: 'Used quantity must be greater than zero.' });
86+
}
87+
try {
88+
const item = await KIInventoryItem.findById(itemId);
89+
if (!item) {
90+
return res.status(404).json({ message: 'Item not found.' });
91+
}
92+
if (item.expiryDate < new Date()) {
93+
return res.status(400).json({ message: `This item was expired on ${item.expiryDate}` });
94+
}
95+
let present = item.presentQuantity;
96+
present -= usedQuantity;
97+
if (present < 0) {
98+
present = 0;
99+
}
100+
item.presentQuantity = present;
101+
item.updatedAt = new Date();
102+
await item.save();
103+
res.status(200).json({ message: 'Item usage updated successfully.', data: item });
104+
} catch (err) {
105+
res.status(400).json({ message: err.message });
106+
}
107+
};
108+
const updateStoredQuantity = async (req, res) => {
109+
const { itemId, addedQuantity, newExpiry } = req.body;
110+
if (addedQuantity <= 0) {
111+
return res.status(400).json({ message: 'Added quantity must be greater than zero.' });
112+
}
113+
if (newExpiry && new Date(newExpiry) < new Date()) {
114+
return res.status(400).json({ message: 'New expiry date must be a future date.' });
115+
}
116+
try {
117+
const item = await KIInventoryItem.findById(itemId);
118+
if (!item) {
119+
return res.status(404).json({ message: 'Item not found.' });
120+
}
121+
if (item.presentQuantity === 0 || item.expiryDate < new Date()) {
122+
item.storedQuantity = addedQuantity;
123+
item.presentQuantity = 0;
124+
} else {
125+
item.storedQuantity += addedQuantity;
126+
}
127+
item.presentQuantity += addedQuantity;
128+
if (newExpiry) {
129+
item.expiryDate = newExpiry;
130+
}
131+
item.updatedAt = new Date();
132+
await item.save();
133+
res.status(200).json({ message: 'Stored quantity updated successfully.', data: item });
134+
} catch (err) {
135+
res.status(400).json({ message: err.message });
136+
}
137+
};
138+
const updateNextHarvest = async (req, res) => {
139+
const { itemId, lastHarvestSuccess, nextHarvestDate, nextHarvestQuantity } = req.body;
140+
try {
141+
const item = await KIInventoryItem.findById(itemId);
142+
if (!item) {
143+
return res.status(404).json({ message: 'Item not found.' });
144+
}
145+
if (lastHarvestSuccess) {
146+
item.lastHarvestDate = item.nextHarvestDate;
147+
}
148+
item.nextHarvestDate = nextHarvestDate;
149+
item.nextHarvestQuantity = nextHarvestQuantity;
150+
item.updatedAt = new Date();
151+
await item.save();
152+
res.status(200).json({ message: 'Next harvest details updated successfully.', data: item });
153+
} catch (err) {
154+
res.status(400).json({ message: err.message });
155+
}
156+
};
157+
return {
158+
addItem,
159+
getItems,
160+
getItemsByCategory,
161+
getPreservedStock,
162+
updateOnUsage,
163+
updateStoredQuantity,
164+
updateNextHarvest,
165+
};
166+
};
167+
module.exports = KIInventoryController;
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
const prGradingConfigController = function (PRGradingConfig) {
2+
const getAllConfigs = async (req, res) => {
3+
try {
4+
const configs = await PRGradingConfig.find().sort({ createdAt: -1 });
5+
res.status(200).json(configs);
6+
} catch (err) {
7+
res.status(500).json({ error: 'Failed to fetch configurations', details: err.message });
8+
}
9+
};
10+
11+
const createConfig = async (req, res) => {
12+
try {
13+
const { teamName, reviewerCount, testDataType, reviewerNames, notes } = req.body;
14+
15+
if (!teamName || !reviewerCount || !testDataType) {
16+
return res
17+
.status(400)
18+
.json({ error: 'teamName, reviewerCount, and testDataType are required.' });
19+
}
20+
21+
if (typeof reviewerCount !== 'number' || reviewerCount < 1) {
22+
return res.status(400).json({ error: 'reviewerCount must be a positive number.' });
23+
}
24+
25+
const existing = await PRGradingConfig.findOne({ teamName: teamName.trim() });
26+
if (existing) {
27+
return res
28+
.status(409)
29+
.json({ error: `A configuration with team name "${teamName}" already exists.` });
30+
}
31+
32+
const newConfig = new PRGradingConfig({
33+
teamName: teamName.trim(),
34+
reviewerCount,
35+
testDataType,
36+
reviewerNames: reviewerNames || [],
37+
notes: notes || '',
38+
});
39+
40+
const saved = await newConfig.save();
41+
res.status(201).json(saved);
42+
} catch (err) {
43+
res.status(500).json({ error: 'Failed to create configuration', details: err.message });
44+
}
45+
};
46+
47+
const deleteConfig = async (req, res) => {
48+
try {
49+
const { id } = req.params;
50+
const deleted = await PRGradingConfig.findByIdAndDelete(id);
51+
if (!deleted) {
52+
return res.status(404).json({ error: 'Configuration not found.' });
53+
}
54+
res.status(200).json({ message: 'Configuration deleted successfully.' });
55+
} catch (err) {
56+
res.status(500).json({ error: 'Failed to delete configuration', details: err.message });
57+
}
58+
};
59+
60+
return { getAllConfigs, createConfig, deleteConfig };
61+
};
62+
63+
module.exports = prGradingConfigController;

src/controllers/reportsController.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ const reportsController = function () {
623623
createdDate: 1,
624624
getWeeklyReport: 1,
625625
permissionGrantedToGetWeeklySummaryReport: 1,
626+
isActive: 1,
626627
},
627628
)
628629
.then((results) => {

src/controllers/userProfileController.js

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const moment_ = require('moment');
1414
const jwt = require('jsonwebtoken');
1515
const userHelper = require('../helpers/userHelper')();
1616
const TimeEntry = require('../models/timeentry');
17+
const Team = require('../models/team');
1718
const logger = require('../startup/logger');
1819
const Badge = require('../models/badge');
1920
// eslint-disable-next-line no-unused-vars
@@ -477,7 +478,39 @@ const createControllerMethods = function (UserProfile, Project, cache) {
477478
}
478479

479480
if (req.body.teams !== undefined) {
480-
record.teams = Array.from(new Set(req.body.teams));
481+
const updatedTeams = Array.from(new Set(req.body.teams));
482+
483+
// Find teams that were removed
484+
const removedTeams = record.teams.filter(
485+
(teamId) => !updatedTeams.includes(teamId.toString()),
486+
);
487+
488+
// Find teams that were added
489+
const addedTeams = updatedTeams.filter(
490+
(teamId) => !record.teams.map((t) => t.toString()).includes(teamId),
491+
);
492+
493+
// Remove user from Team's members array for each removed team
494+
if (removedTeams.length > 0) {
495+
await Team.updateMany(
496+
{ _id: { $in: removedTeams } },
497+
{ $pull: { members: { userId: mongoose.Types.ObjectId(record._id) } } },
498+
);
499+
}
500+
501+
// Add user to Team's members array for each added team
502+
if (addedTeams.length > 0) {
503+
await Team.updateMany(
504+
{ _id: { $in: addedTeams } },
505+
{
506+
$push: {
507+
members: { userId: mongoose.Types.ObjectId(record._id), addDateTime: new Date() },
508+
},
509+
},
510+
);
511+
}
512+
513+
record.teams = updatedTeams;
481514
}
482515

483516
await updateProjects(req, record);

0 commit comments

Comments
 (0)