diff --git a/package-lock.json b/package-lock.json index 4f94329e9..32621abe1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8928,6 +8928,20 @@ "version": "1.0.0", "license": "ISC" }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "license": "MIT", diff --git a/src/controllers/kitchenRecipeController.js b/src/controllers/kitchenRecipeController.js new file mode 100644 index 000000000..a962b07d4 --- /dev/null +++ b/src/controllers/kitchenRecipeController.js @@ -0,0 +1,71 @@ +const kitchenRecipeController = function (KitchenRecipe) { + const getRecipes = function (req, res) { + KitchenRecipe.find() + .then((recipes) => { + res.status(200).send(recipes); + }) + .catch((error) => { + res.status(500).send({ message: error.message || 'Error fetching recipes' }); + }); + }; + + const getRecipeById = function (req, res) { + const { recipeId } = req.params; + KitchenRecipe.findById(recipeId) + .then((recipe) => { + if (!recipe) { + return res.status(404).send({ message: 'Recipe not found' }); + } + return res.status(200).send(recipe); + }) + .catch((error) => { + res.status(500).send({ message: error.message || 'Error fetching recipe' }); + }); + }; + + const substituteIngredient = function (req, res) { + const { recipeId } = req.params; + const { ingredientId, substituteName, quantity } = req.body; + + if (!ingredientId || !substituteName || !quantity) { + return res.status(400).send({ + message: 'ingredientId, substituteName, and quantity are required', + }); + } + + return KitchenRecipe.findById(recipeId) + .then((recipe) => { + if (!recipe) { + return res.status(404).send({ message: 'Recipe not found' }); + } + + const ingredient = recipe.ingredients.id(ingredientId); + if (!ingredient) { + return res.status(404).send({ message: 'Ingredient not found in recipe' }); + } + + ingredient.name = substituteName; + ingredient.quantity = quantity; + ingredient.isAvailable = true; + recipe.updatedAt = Date.now(); + + return recipe.save().then((updatedRecipe) => { + res.status(200).send({ + message: 'Ingredient substituted', + recipe: updatedRecipe, + }); + }); + }) + .catch((error) => { + res.status(500).send({ message: error.message || 'Error substituting ingredient' }); + }); + }; + + return { + getRecipes, + getRecipeById, + substituteIngredient, + }; +}; + +module.exports = kitchenRecipeController; diff --git a/src/models/kitchenRecipe.js b/src/models/kitchenRecipe.js new file mode 100644 index 000000000..db2400265 --- /dev/null +++ b/src/models/kitchenRecipe.js @@ -0,0 +1,29 @@ +const mongoose = require('mongoose'); + +const { Schema } = mongoose; + +const ingredientSchema = new Schema({ + name: { type: String, required: true }, + quantity: { type: String, required: true }, + isOnsite: { type: Boolean, default: false }, + isAvailable: { type: Boolean, default: true }, +}); + +const kitchenRecipeSchema = new Schema({ + name: { type: String, required: true }, + type: { type: String, required: true }, + description: { type: String }, + prepTime: { type: Number }, + servings: { type: Number }, + difficulty: { type: String, enum: ['Easy', 'Medium', 'Hard'] }, + tags: [{ type: String }], + hasPriorityIngredients: { type: Boolean, default: false }, + onsitePercentage: { type: Number, default: 0 }, + ingredients: [ingredientSchema], + instructions: [{ type: String }], + createdBy: { type: Schema.Types.ObjectId, ref: 'userProfile' }, + createdAt: { type: Date, default: Date.now }, + updatedAt: { type: Date, default: Date.now }, +}); + +module.exports = mongoose.model('kitchenRecipe', kitchenRecipeSchema, 'kitchenRecipes'); diff --git a/src/routes/kitchenRecipeRouter.js b/src/routes/kitchenRecipeRouter.js new file mode 100644 index 000000000..83a043745 --- /dev/null +++ b/src/routes/kitchenRecipeRouter.js @@ -0,0 +1,18 @@ +const express = require('express'); + +const routes = function (KitchenRecipe) { + const controller = require('../controllers/kitchenRecipeController')(KitchenRecipe); + const kitchenRecipeRouter = express.Router(); + + kitchenRecipeRouter.route('/kitchenandinventory/recipes').get(controller.getRecipes); + + kitchenRecipeRouter.route('/kitchenandinventory/recipes/:recipeId').get(controller.getRecipeById); + + kitchenRecipeRouter + .route('/kitchenandinventory/recipes/:recipeId/substitute') + .put(controller.substituteIngredient); + + return kitchenRecipeRouter; +}; + +module.exports = routes; diff --git a/src/startup/routes.js b/src/startup/routes.js index ab3700235..bc7f8a68b 100644 --- a/src/startup/routes.js +++ b/src/startup/routes.js @@ -382,6 +382,10 @@ const summaryDashboardRouter = require('../routes/summaryDashboard.routes'); // Actual Cost const actualCostRouter = require('../routes/actualCostRouter')(); +// Kitchen and Inventory +const kitchenRecipe = require('../models/kitchenRecipe'); +const kitchenRecipeRouter = require('../routes/kitchenRecipeRouter')(kitchenRecipe); + module.exports = function (app) { app.use('/api/bm/summary-dashboard', summaryDashboardRouter); app.use('/api', forgotPwdRouter); @@ -496,7 +500,6 @@ module.exports = function (app) { app.use('/api', toolUtilizationRouter); // lb dashboard - app.use('/api', toolAvailabilityRouter); app.use('/api', projectCostTrackingRouter); @@ -563,4 +566,7 @@ module.exports = function (app) { app.use('/api', materialCostRouter); app.use('/api/lp', lessonPlanSubmissionRouter); + + // Kitchen and Inventory + app.use('/api', kitchenRecipeRouter); };