Skip to content

Commit c8ada9f

Browse files
Merge pull request #2018 from OneCommunityGlobal/bhanuanish-kitchenandinventory-inventoryitems
Bhanuanish kitchenandinventory inventoryitems
2 parents 6c969e0 + d96644b commit c8ada9f

4 files changed

Lines changed: 235 additions & 0 deletions

File tree

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: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
const mongoose = require('mongoose');
2+
3+
const KIInventoryItemSchema = new mongoose.Schema({
4+
name: { type: String, required: true, trim: true, minlength: 3, maxlength: 50 },
5+
presentQuantity: { type: Number, required: false },
6+
storedQuantity: { type: Number, required: true, min: 0 },
7+
unit: { type: String, required: true },
8+
type: { type: String, required: true, trim: true },
9+
monthlyUsage: { type: Number, required: true },
10+
reorderAt: { type: Number, required: true },
11+
category: {
12+
type: String,
13+
required: true,
14+
enum: ['INGREDIENT', 'EQUIPEMENTANDSUPPLIES', 'SEEDS', 'CANNINGSUPPLIES', 'ANIMALSUPPLIES'],
15+
},
16+
createdAt: { type: Date, default: Date.now },
17+
updatedAt: { type: Date, default: Date.now },
18+
expiryDate: { type: Date, required: true, min: Date.now },
19+
location: { type: String, optional: true },
20+
onsite: { type: Boolean, default: false },
21+
lastHarvestDate: { type: Date, optional: true, max: Date.now },
22+
nextHarvestDate: { type: Date, optional: true, min: Date.now },
23+
nextHarvestQuantity: { type: Number, optional: true },
24+
});
25+
26+
module.exports = mongoose.model('KIInventoryItem', KIInventoryItemSchema);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const express = require('express');
2+
const controller = require('../../controllers/kitchenandinventory/KIInventoryController')();
3+
4+
const router = function () {
5+
const inventoryRouter = express.Router();
6+
// Routes for inventory items
7+
inventoryRouter.route('/items').post(controller.addItem); // Route to add a new inventory item
8+
inventoryRouter.route('/items').get(controller.getItems); // Route to get all inventory items
9+
inventoryRouter.route('/items/:category').get(controller.getItemsByCategory); // Route to get items by category
10+
inventoryRouter.route('/items/ingredients/preserved').get(controller.getPreservedStock); // Route to get preserved items
11+
// Below update endpoints are non-idempotent and meant to be used for specific actions
12+
inventoryRouter.route('/items/usage').post(controller.updateOnUsage); // Route to update item on usage
13+
inventoryRouter.route('/items/storedQuantity').post(controller.updateStoredQuantity); // Route to update stored quantity
14+
inventoryRouter.route('/items/nextHarvest').put(controller.updateNextHarvest); // Route to update next harvest details
15+
return inventoryRouter;
16+
};
17+
18+
module.exports = router;

src/startup/routes.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ const badgeSystemRouter = require('../routes/educationPortal/badgeSystemRouter')
382382

383383
const promotionDetailsRouter = require('../routes/promotionDetailsRouter');
384384

385+
// Kitchen and Inventory portal routes
386+
const kitchenInventoryRouter = require('../routes/kitchenandinventory/KIInventoryRouter')();
385387
const summaryDashboardRouter = require('../routes/summaryDashboard.routes');
386388

387389
// Actual Cost
@@ -562,6 +564,28 @@ module.exports = function (app) {
562564
app.use('/api', projectMaterialRouter);
563565
app.use('/api/bm', bmRentalChart);
564566
app.use('/api/lb', lbWishlistsRouter);
567+
app.use('/api/lb', listingAvailablityRouter);
568+
// lb dashboard
569+
app.use('/api/lb', bidTermsRouter);
570+
app.use('/api/lb', bidsRouter);
571+
app.use('/api/lb', paymentsRouter);
572+
app.use('/api/lb', webhookRouter);
573+
app.use('/api/lb', bidNotificationsRouter);
574+
app.use('/api/lb', bidDeadlinesRouter);
575+
app.use('/api/lb', SMSRouter);
576+
app.use('/api', materialCostRouter);
577+
578+
// education portal
579+
app.use('/api/education', badgeSystemRouter);
580+
581+
app.use('/api/lp', lessonPlanSubmissionRouter);
582+
583+
app.use('/api/education', browsableLessonPlanRouter);
584+
585+
app.use('/api/educator/reports', downloadReportRouter);
586+
587+
// Kitchen and Inventory portal routes
588+
app.use('/api/kitchenandinventory/inventory', kitchenInventoryRouter);
565589

566590
// Education Portal
567591
app.use('/api/student/profile', educationProfileRouter);

0 commit comments

Comments
 (0)