From a41987b327b56c13ac4e9dee525cae0dfbf98aaa Mon Sep 17 00:00:00 2001 From: Sathishkumar Krishnan Date: Mon, 27 Dec 2021 12:29:56 +0530 Subject: [PATCH 01/13] fix: merge auth utils --- src/config/auth.js | 53 ------------------------------- src/controller/index.js | 2 +- src/controller/utils/authorize.js | 51 +++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 56 deletions(-) delete mode 100644 src/config/auth.js diff --git a/src/config/auth.js b/src/config/auth.js deleted file mode 100644 index ec146ed..0000000 --- a/src/config/auth.js +++ /dev/null @@ -1,53 +0,0 @@ -const jwt = require("jsonwebtoken"); -const { JWT_SECRET } = require("./env"); -const User = require("../models/User"); -const constants = require("./constants"); - -const authenticate = async (token) => { - const decodedToken = jwt.verify(token, JWT_SECRET); - if (decodedToken) { - return await User.findById(decodedToken.id) - .populate({ path: "roles", populate: "permissions" }) - .populate("permissions"); - } -}; - -const authorize = async ( - user, - requiredRoles = [], - requiredPermissions = [] -) => { - const userRoles = user.roles.map((_) => _._id); - const userPermissions = [ - ...user.permissions.map((_) => _._id), - ...userRoles.map((_) => _.permissions).flat(), - ]; - - return ( - user != undefined && - requiredRoles.every((_) => userRoles.includes(_)) && - requiredPermissions.every((_) => userPermissions.includes(_)) - ); -}; - -module.exports = { - AuthenticateMiddleware: async (req, res, next) => { - try { - const token = req.headers.authorization || ""; - if (token) { - const user = authenticate(token); - res.locals.user = user; - next(); - } - } catch (error) { - res - .status(401) - .send({ - success: false, - error: constants.AUTHENTICATION_FAILURE_ERROR_MESSAGE, - }); - } - }, - - AuthorizeUser: authorize, -}; diff --git a/src/controller/index.js b/src/controller/index.js index 64bc9dd..3cbe6c5 100644 --- a/src/controller/index.js +++ b/src/controller/index.js @@ -2,7 +2,7 @@ const router = require("express").Router(); const userRouter = require("./user.router"); const userRoleRouter = require("./userRole.router"); const userPermissionRouter = require("./userPermission.router"); -const { AuthenticateMiddleware } = require("../config/auth"); +const { AuthenticateMiddleware } = require("./utils/authorize"); const companyRouter = require("./company.router"); const warehouseRouter = require("./warehouse.router"); diff --git a/src/controller/utils/authorize.js b/src/controller/utils/authorize.js index 4c17cdc..11e801e 100644 --- a/src/controller/utils/authorize.js +++ b/src/controller/utils/authorize.js @@ -1,11 +1,41 @@ const UserRole = require("../../models/UserRole"); -const { AuthorizeUser } = require("../../config/auth"); const { SUPER_ADMIN_ROLE, AUTHORIZATION_FAILURE_ERROR_MESSAGE } = require("../../config/constants"); +const jwt = require("jsonwebtoken"); +const { JWT_SECRET } = require("./env"); +const User = require("../models/User"); +const constants = require("./constants"); + +const authenticate = async (token) => { + const decodedToken = jwt.verify(token, JWT_SECRET); + if (decodedToken) { + return await User.findById(decodedToken.id) + .populate({ path: "roles", populate: "permissions" }) + .populate("permissions"); + } +}; + +const authorize = async ( + user, + requiredRoles = [], + requiredPermissions = [] +) => { + const userRoles = user.roles.map((_) => _._id); + const userPermissions = [ + ...user.permissions.map((_) => _._id), + ...userRoles.map((_) => _.permissions).flat(), + ]; + + return ( + user != undefined && + requiredRoles.every((_) => userRoles.includes(_)) && + requiredPermissions.every((_) => userPermissions.includes(_)) + ); +}; module.exports = { SuperAdminCheck: async (req, res, next) => { const SuperAdmin = await UserRole.findOne({ name: SUPER_ADMIN_ROLE }); - if (AuthorizeUser(req.locals.user, [SuperAdmin.id])) { + if (authorize(req.locals.user, [SuperAdmin.id])) { next(); } else { res @@ -13,4 +43,21 @@ module.exports = { .send({ success: false, error: AUTHORIZATION_FAILURE_ERROR_MESSAGE }); } }, + AuthenticateMiddleware: async (req, res, next) => { + try { + const token = req.headers.authorization || ""; + if (token) { + const user = authenticate(token); + res.locals.user = user; + next(); + } + } catch (error) { + res.status(401).send({ + success: false, + error: constants.AUTHENTICATION_FAILURE_ERROR_MESSAGE, + }); + } + }, + + AuthorizeUser: authorize, }; From 141997342be1947ff97ef26cbd0d3b5f0bdc37f8 Mon Sep 17 00:00:00 2001 From: Sathishkumar Krishnan Date: Mon, 27 Dec 2021 12:48:55 +0530 Subject: [PATCH 02/13] fix: conflict due to merge --- src/controller/user.router.js | 3 +-- src/controller/utils/authorize.js | 15 ++++++++++----- src/models/Level.js | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/controller/user.router.js b/src/controller/user.router.js index 7c0c39d..ffb840a 100644 --- a/src/controller/user.router.js +++ b/src/controller/user.router.js @@ -1,7 +1,6 @@ const router = require("express").Router(); const controller = require("./user.controller"); -const { AuthenticateMiddleware } = require("../config/auth"); -const { SuperAdminCheck } = require("./utils/authorize"); +const { SuperAdminCheck, AuthenticateMiddleware } = require("./utils/authorize"); router.post("/register", controller.registerUser); router.post("/login", controller.loginUser); diff --git a/src/controller/utils/authorize.js b/src/controller/utils/authorize.js index 11e801e..ea92041 100644 --- a/src/controller/utils/authorize.js +++ b/src/controller/utils/authorize.js @@ -1,9 +1,12 @@ -const UserRole = require("../../models/UserRole"); -const { SUPER_ADMIN_ROLE, AUTHORIZATION_FAILURE_ERROR_MESSAGE } = require("../../config/constants"); const jwt = require("jsonwebtoken"); -const { JWT_SECRET } = require("./env"); -const User = require("../models/User"); -const constants = require("./constants"); +const User = require("../../models/User"); +const UserRole = require("../../models/UserRole"); +const { + SUPER_ADMIN_ROLE, + AUTHORIZATION_FAILURE_ERROR_MESSAGE, +} = require("../../config/constants"); +const { JWT_SECRET } = require("../../config/env"); +const constants = require("../../config/constants"); const authenticate = async (token) => { const decodedToken = jwt.verify(token, JWT_SECRET); @@ -50,6 +53,8 @@ module.exports = { const user = authenticate(token); res.locals.user = user; next(); + } else { + throw new Error("Not Authenticated user!"); } } catch (error) { res.status(401).send({ diff --git a/src/models/Level.js b/src/models/Level.js index 43b04c0..3e7b010 100644 --- a/src/models/Level.js +++ b/src/models/Level.js @@ -51,6 +51,6 @@ const schema = new mongoose.Schema( } ); -const Level = mongoose.model("Level", schema); +const Level = mongoose.models.Level || mongoose.model("Level", schema); module.exports = Level; From 449749d32016e9246c48db3c68cebd18122dbcd3 Mon Sep 17 00:00:00 2001 From: Sathishkumar Krishnan Date: Mon, 27 Dec 2021 12:57:12 +0530 Subject: [PATCH 03/13] feat: inventory endpoint --- src/controller/inventory.controller.js | 89 ++++++++++++++++++++++++++ src/controller/inventory.router.js | 19 ++++++ 2 files changed, 108 insertions(+) create mode 100644 src/controller/inventory.controller.js create mode 100644 src/controller/inventory.router.js diff --git a/src/controller/inventory.controller.js b/src/controller/inventory.controller.js new file mode 100644 index 0000000..9175e00 --- /dev/null +++ b/src/controller/inventory.controller.js @@ -0,0 +1,89 @@ +const Inventory = require("../models/Inventory"); + +module.exports = { + /** + * Gets the Inventory data by `id` + */ + getInventoryByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + try { + const inventoryData = await Inventory.findById(id); + if (!inventoryData) { + res.status(404); + return; + } + req.send({ success: true, data: inventoryData }); + } catch (error) { + next(error); + } + }, + + /** + * Create a Inventory + */ + createInventory: async (req, res, next) => { + const { name, type } = req.body; + + if (!(name && type)) { + res.status(400).send("Missing params param"); + return; + } + + try { + const inventoryData = new Inventory({ + name, + type, + }); + + await inventoryData.save(); + if (!inventoryData) { + res.status(404); + return; + } + req.send({ success: true, data: inventoryData }); + } catch (error) { + next(error); + } + }, + + /** + * Update a Inventory detail + */ + updateInventoryByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + const { name, type } = req.body; + + if (!(name || type)) { + res.status(400).send("Missing data in body"); + return; + } + + try { + const inventoryData = await Inventory.findById(id); + if (!inventoryData) { + res.status(404); + return; + } + + if (name) inventoryData.name = name; + if (type) inventoryData.type = type; + + await inventoryData.save(); + req.send({ success: true, data: inventoryData }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/inventory.router.js b/src/controller/inventory.router.js new file mode 100644 index 0000000..a00ad8e --- /dev/null +++ b/src/controller/inventory.router.js @@ -0,0 +1,19 @@ +const router = require("express").Router(); +const controller = require("./inventory.controller"); + +/** + * @route /inventory/:id + */ +router.get("/:id", controller.getInventoryByID); + +/** + * @route /inventory/ + */ +router.post("/", controller.createInventory); + +/** + * @route /inventory/ + */ +router.patch("/:id", controller.updateInventoryByID); + +module.exports = router; From ef4b420dec3711217fa95a686093171b6c1f8946 Mon Sep 17 00:00:00 2001 From: Llewellyn D'souza Date: Tue, 28 Dec 2021 18:04:11 +0530 Subject: [PATCH 04/13] Added: multer middleware --- src/middleware/fileUpload.js | 42 ++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/middleware/fileUpload.js diff --git a/src/middleware/fileUpload.js b/src/middleware/fileUpload.js new file mode 100644 index 0000000..ad27f9f --- /dev/null +++ b/src/middleware/fileUpload.js @@ -0,0 +1,42 @@ +const multer = require("multer"); + +const storage = multer.diskStorage({ + // multers disk storage settings + destination: function (req, file, cb) { + cb(null, "./uploads/"); + }, + limits: { + // files: 1, + fileSize: 1024 * 1024, + }, + filename: function (req, file, cb) { + cb( + null, + file.fieldname + + "-" + + Date.now() + + "." + + file.originalname.split(".")[file.originalname.split(".").length - 1] + ); + }, + onFileUploadStart: function (file) { + console.log("Inside uploads"); + if ( + file.mimetype == "image/jpg" || + file.mimetype == "image/jpeg" || + file.mimetype == "image/png" + ) { + return true; + } else { + return false; + } + }, +}); + +const upload = multer({ + // multer settings + storage, +}); + +// http://expressjs.com/en/resources/middleware/multer.html +module.exports = upload; From 5d07fb88718e68ef7cacb3102b88ad73dd0a60f6 Mon Sep 17 00:00:00 2001 From: Llewellyn D'souza Date: Tue, 28 Dec 2021 18:04:25 +0530 Subject: [PATCH 05/13] Integrated --- src/controller/warehouse.controller.js | 9 +++++++++ src/controller/warehouse.router.js | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/controller/warehouse.controller.js b/src/controller/warehouse.controller.js index 4acf1a0..6aaae28 100644 --- a/src/controller/warehouse.controller.js +++ b/src/controller/warehouse.controller.js @@ -55,6 +55,15 @@ module.exports = { } }, + /** + * Upload an image for the warehouse + */ + addWarehouseImage: async (req, res, next) => { + // req.file contains the `warehouse-image` + console.dir({ file: req.file }); + res.send("ok"); + }, + /** * Update a warehouses detail */ diff --git a/src/controller/warehouse.router.js b/src/controller/warehouse.router.js index 98b4dc7..4c2e7cf 100644 --- a/src/controller/warehouse.router.js +++ b/src/controller/warehouse.router.js @@ -1,4 +1,5 @@ const router = require("express").Router(); +const upload = require("../middleware/fileUpload"); const controller = require("./warehouse.controller"); /** @@ -11,6 +12,15 @@ router.get("/:id", controller.getWarehouseByID); */ router.post("/", controller.createWarehouse); +/** + * @route /warehouse/add-image + */ +router.post( + "/add-image", + upload.single("warehouse-image"), + controller.addWarehouseImage +); + /** * @route /warehouse/ */ From e221527ae86833f3f9acfe3692a17b4740533498 Mon Sep 17 00:00:00 2001 From: Llewellyn D'souza Date: Tue, 28 Dec 2021 18:05:14 +0530 Subject: [PATCH 06/13] Added: multer npm --- package-lock.json | 348 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 2 files changed, 345 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0eb075..6832058 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "jsonwebtoken": "^8.5.1", "mongoose": "^6.1.2", "morgan": "^1.10.0", + "multer": "^1.4.4", "validator": "^13.7.0" }, "devDependencies": { @@ -243,6 +244,11 @@ "node": ">= 8" } }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -448,6 +454,39 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "dependencies": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/busboy/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/busboy/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "node_modules/bytes": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", @@ -634,6 +673,52 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -688,6 +773,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -809,6 +899,34 @@ "node": ">=0.10" } }, + "node_modules/dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "dependencies": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/dicer/node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/dicer/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1710,6 +1828,11 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1996,8 +2119,7 @@ "node_modules/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "node_modules/minipass": { "version": "3.1.6", @@ -2143,6 +2265,35 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2460,6 +2611,11 @@ "node": ">=4" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -2867,6 +3023,14 @@ "node": ">= 0.6" } }, + "node_modules/streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -3048,6 +3212,11 @@ "node": ">= 0.6" } }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "node_modules/typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -3274,6 +3443,14 @@ "node": ">=8" } }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", @@ -3451,6 +3628,11 @@ "picomatch": "^2.0.4" } }, + "append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=" + }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -3604,6 +3786,38 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "busboy": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", + "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", + "requires": { + "dicer": "0.2.5", + "readable-stream": "1.1.x" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "bytes": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz", @@ -3741,6 +3955,51 @@ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "configstore": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", @@ -3783,6 +4042,11 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", @@ -3869,6 +4133,33 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" }, + "dicer": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", + "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", + "requires": { + "readable-stream": "1.1.x", + "streamsearch": "0.1.2" + }, + "dependencies": { + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4552,6 +4843,11 @@ "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", "dev": true }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -4787,8 +5083,7 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" }, "minipass": { "version": "3.1.6", @@ -4900,6 +5195,31 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "multer": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4.tgz", + "integrity": "sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==", + "requires": { + "append-field": "^1.0.0", + "busboy": "^0.2.11", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "on-finished": "^2.3.0", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + } + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5140,6 +5460,11 @@ "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", "dev": true }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -5454,6 +5779,11 @@ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, + "streamsearch": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", + "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5586,6 +5916,11 @@ "mime-types": "~2.1.24" } }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + }, "typedarray-to-buffer": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", @@ -5761,6 +6096,11 @@ "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index c07558c..738acd7 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "jsonwebtoken": "^8.5.1", "mongoose": "^6.1.2", "morgan": "^1.10.0", + "multer": "^1.4.4", "validator": "^13.7.0" }, "devDependencies": { From 3407c252b985f6e8b64c40425284c53e50df0710 Mon Sep 17 00:00:00 2001 From: Sathishkumar Krishnan Date: Wed, 29 Dec 2021 05:33:49 +0530 Subject: [PATCH 07/13] feat: added item controllers --- src/controller/item.controller.js | 112 ++++++++++++++++++++++++++++++ src/controller/item.router.js | 19 +++++ src/models/Item.js | 4 -- 3 files changed, 131 insertions(+), 4 deletions(-) create mode 100644 src/controller/item.controller.js create mode 100644 src/controller/item.router.js diff --git a/src/controller/item.controller.js b/src/controller/item.controller.js new file mode 100644 index 0000000..f584e80 --- /dev/null +++ b/src/controller/item.controller.js @@ -0,0 +1,112 @@ +const Item = require("../models/Item"); + +module.exports = { + /** + * Gets the Item data by `id` + */ + getItemByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + try { + const itemData = await Item.findById(id); + if (!itemData) { + res.status(404); + return; + } + req.send({ success: true, data: itemData }); + } catch (error) { + next(error); + } + }, + + /** + * Create a Item + */ + createItem: async (req, res, next) => { + const item = { + commonName: req.body.commonName, + formalName: req.body.formalName, + description: req.body.description, + manufacturer: req.body.manufacturer, + size: req.body.size, + color: req.body.color, + type: req.body.type, + unitOfMaterial: req.body.unitOfMaterial, + unitCost: req.body.unitCost, + packageCount: req.body.packageCount, + countPerPallet: req.body.countPerPallet, + countPerPalletPackage: req.body.countPerPalletPackage, + customAttributes: req.body.customAttributes, + }; + + if (Object.values(item).every((_) => _)) { + res.status(400).send("Missing params param"); + return; + } + + try { + const itemData = new Item(item); + + await itemData.save(); + if (!itemData) { + res.status(404); + return; + } + req.send({ success: true, data: itemData }); + } catch (error) { + next(error); + } + }, + + /** + * Update a Item detail + */ + updateItemByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + const item = { + commonName: req.body.commonName, + formalName: req.body.formalName, + description: req.body.description, + manufacturer: req.body.manufacturer, + size: req.body.size, + color: req.body.color, + type: req.body.type, + unitOfMaterial: req.body.unitOfMaterial, + unitCost: req.body.unitCost, + packageCount: req.body.packageCount, + countPerPallet: req.body.countPerPallet, + countPerPalletPackage: req.body.countPerPalletPackage, + customAttributes: req.body.customAttributes, + }; + + try { + const itemData = await Item.findById(id); + if (!itemData) { + res.status(404); + return; + } + + for (const key of Object.keys(item)) { + if (item[key] !== undefined) { + itemData[key] = item[key]; + } + } + + await itemData.save(); + req.send({ success: true, data: itemData }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/item.router.js b/src/controller/item.router.js new file mode 100644 index 0000000..effbc24 --- /dev/null +++ b/src/controller/item.router.js @@ -0,0 +1,19 @@ +const router = require("express").Router(); +const controller = require("./item.controller"); + +/** + * @route /item/:id + */ +router.get("/:id", controller.getItemByID); + +/** + * @route /item/ + */ +router.post("/", controller.createItem); + +/** + * @route /item/ + */ +router.patch("/:id", controller.updateItemByID); + +module.exports = router; diff --git a/src/models/Item.js b/src/models/Item.js index 1d83044..b9056be 100644 --- a/src/models/Item.js +++ b/src/models/Item.js @@ -47,10 +47,6 @@ const schema = new mongoose.Schema( type: Number, required: true, }, - unitQuantity: { - type: Number, - required: true, - }, packageCount: { type: Number, required: true, From cd00c9b7bbfb702433d879f6e7e7a2bd814d835e Mon Sep 17 00:00:00 2001 From: Sathishkumar Krishnan Date: Wed, 29 Dec 2021 05:46:34 +0530 Subject: [PATCH 08/13] feat: added material endpoints --- src/controller/material.controller.js | 122 ++++++++++++++++++++++++++ src/controller/material.router.js | 19 ++++ src/models/Material.js | 24 ++--- 3 files changed, 150 insertions(+), 15 deletions(-) create mode 100644 src/controller/material.controller.js create mode 100644 src/controller/material.router.js diff --git a/src/controller/material.controller.js b/src/controller/material.controller.js new file mode 100644 index 0000000..da5fb4e --- /dev/null +++ b/src/controller/material.controller.js @@ -0,0 +1,122 @@ +const mongoose = require("mongoose"); +const Material = require("../models/Material"); +const Inventory = require("../models/Inventory"); + +module.exports = { + /** + * Gets the Material data by `id` + */ + getMaterialByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + try { + const materialData = await Material.findById(id); + if (!materialData) { + res.status(404); + return; + } + req.send({ success: true, data: materialData }); + } catch (error) { + next(error); + } + }, + + /** + * Create a Material + */ + createMaterial: async (req, res, next) => { + const { name, parentId, inventoryId } = req.body; + + try { + let parent; + if (parentId && mongoose.isValidObjectId(parentId)) { + parent = await Material.findById(parent); + } else if (parentId && !mongoose.isValidObjectId(parentId)) { + res.status(400).send("Invalid params parentId"); + return; + } + + let inventory; + if (inventoryId && mongoose.isValidObjectId(inventoryId)) { + inventory = await Inventory.findById(inventoryId); + } else { + res.status(400).send("Invalid params inventoryId"); + return; + } + + const materialData = new Material({ + name, + parent, + inventory, + }); + + await materialData.save(); + if (!materialData) { + res.status(404); + return; + } + req.send({ success: true, data: materialData }); + } catch (error) { + next(error); + } + }, + + /** + * Update a Material detail + */ + updateMaterialByID: async (req, res, next) => { + const { id } = req.params; + + if (!id) { + res.status(400).send("Missing id param"); + return; + } + + const { name, parentId, inventoryId } = req.body; + + if (!(name || parentId || inventoryId)) { + res.status(400).send("Missing data in body"); + return; + } + + try { + const materialData = await Material.findById(id); + if (!materialData) { + res.status(404); + return; + } + + if (name) { + materialData.name = name; + } + + let parent; + if (parentId && mongoose.isValidObjectId(parentId)) { + parent = await Material.findById(parent); + materialData.parent = parent; + } else if (parentId && !mongoose.isValidObjectId(parentId)) { + res.status(400).send("Invalid params parentId"); + return; + } + + let inventory; + if (inventoryId && mongoose.isValidObjectId(inventoryId)) { + inventory = await Inventory.findById(inventoryId); + materialData.inventory = inventory; + } else { + res.status(400).send("Invalid params inventoryId"); + return; + } + + await materialData.save(); + req.send({ success: true, data: materialData }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/material.router.js b/src/controller/material.router.js new file mode 100644 index 0000000..7fa0873 --- /dev/null +++ b/src/controller/material.router.js @@ -0,0 +1,19 @@ +const router = require("express").Router(); +const controller = require("./material.controller"); + +/** + * @route /material/:id + */ +router.get("/:id", controller.getMaterialByID); + +/** + * @route /material/ + */ +router.post("/", controller.createMaterial); + +/** + * @route /material/ + */ +router.patch("/:id", controller.updateMaterialByID); + +module.exports = router; diff --git a/src/models/Material.js b/src/models/Material.js index 4aaf280..3f39983 100644 --- a/src/models/Material.js +++ b/src/models/Material.js @@ -7,21 +7,15 @@ const schema = new mongoose.Schema( required: true, trim: true, }, - family: [ - { - name: { - type: String, - required: true, - trim: true, - }, - depth: { - type: Number, - required: true, - min: 1, - max: 10 - }, - }, - ], + parent: { + type: mongoose.Schema.Types.ObjectId, + ref: "Material", + }, + inventory: { + type: mongoose.Schema.Types.ObjectId, + ref: "Inventory", + required: true + }, }, { timestamps: true, From 60e6f0cb9419e5696efb9e9af6ad2bce94f04ccb Mon Sep 17 00:00:00 2001 From: Sathishkumar Krishnan Date: Wed, 29 Dec 2021 07:15:34 +0530 Subject: [PATCH 09/13] feat: added dashboard controllers --- src/controller/dashboard.controller.js | 328 +++++++++++++++++++++++++ src/controller/dashboard.router.js | 14 ++ src/controller/index.js | 3 +- src/controller/item.controller.js | 7 + src/models/Bay.js | 4 +- src/models/Item.js | 5 + src/models/Level.js | 2 +- src/models/Sublevel.js | 4 +- 8 files changed, 361 insertions(+), 6 deletions(-) create mode 100644 src/controller/dashboard.controller.js create mode 100644 src/controller/dashboard.router.js diff --git a/src/controller/dashboard.controller.js b/src/controller/dashboard.controller.js new file mode 100644 index 0000000..cd99c29 --- /dev/null +++ b/src/controller/dashboard.controller.js @@ -0,0 +1,328 @@ +const mongoose = require("mongoose"); + +const Warehouse = require("../models/Warehouse"); +const Zone = require("../models/Zone"); +const Area = require("../models/Area"); +const Row = require("../models/Row"); +const Bay = require("../models/Bay"); +const Level = require("../models/Level"); +const Sublevel = require("../models/Sublevel"); +const Inventory = require("../models/Inventory"); +const Material = require("../models/Material"); +const Item = require("../models/Item"); + +const createWarehouse = async ({ name, address, specs, company_id }) => { + if (!(name && address)) { + return; + } + + return await Warehouse.create({ + name, + address, + specs, + company_id: mongoose.Types.ObjectId(company_id), + }); +}; + +const createZones = async (zones, warehouse) => { + const zonesArr = []; + for (const zone of zones) { + const { name, type, specs } = zone; + + const zoneObj = new Zone({ + name, + type, + specs, + warehouse_id: mongoose.Types.ObjectId(warehouse._id), + }); + + await zoneObj.save(); + + if (zone.areas) { + zoneObj.areas = await createAreas(zone.areas, zoneObj); + } + + zonesArr.push(zoneObj); + } + return zonesArr; +}; + +const createAreas = async (areas, zone) => { + const areasArr = []; + for (const area of areas) { + const { name, type, specs } = area; + const areaObj = new Area({ + name, + type, + specs, + zone_id: mongoose.Types.ObjectId(zone._id), + }); + + await areaObj.save(); + if (area.rows) { + areaObj.rows = await createRows(zone.areas, area); + } + areasArr.push(areaObj); + } + return areasArr; +}; + +const createRows = async (rows, area) => { + const rowsArr = []; + for (const row of rows) { + const { name, number, specs } = row; + const rowObj = new Row({ + name, + number: parseInt(number), + specs, + area_id: mongoose.Types.ObjectId(area._id), + }); + + await rowObj.save(); + if (row.bays) { + rowObj.bays = await createBays(row.bays, row); + } + rowsArr.push(rowObj); + } + return rowsArr; +}; + +const createBays = async (bays, row) => { + const baysArr = []; + for (const bay of bays) { + const { name, number, type, specs } = bay; + const bayObj = new Bay({ + name, + number: parseInt(number), + type, + specs, + row_id: mongoose.Types.ObjectId(row._id), + }); + + await bayObj.save(); + if (bay.levels) { + bayObj.levels = await createLevels(bay.levels, bay); + } + baysArr.push(bayObj); + } + return baysArr; +}; + +const createLevels = async (levels, bay) => { + const levelsArr = []; + for (const level of levels) { + const { name, number, specs } = level; + const levelObj = new Level({ + name, + number: parseInt(number), + specs, + row_id: mongoose.Types.ObjectId(bay._id), + }); + + await levelObj.save(); + if (level.levels) { + levelObj.subLevels = await createSublevels(level.subLevels, level); + } + levelsArr.push(levelObj); + } + return levelsArr; +}; + +const createSublevels = async ( + subLevels, + level, + parent = undefined, + depth = 0 +) => { + const subLevelsArr = []; + for (const subLevel of subLevels) { + const subLevelObj = await Sublevel.create({ + name: subLevel.name, + type: subLevel.type, + specs: subLevel.specs, + main_level_id: level._id, + current_depth: depth, + parent_subLevel_id: parent ? parent._id : undefined, + has_inventory: subLevel.has_inventory, + inventory: subLevel.inventory, + }); + + if (subLevel.sub_levels) { + const subSubLevels = await createSublevels( + subLevel.sub_levels, + level, + subLevelObj, + depth + 1 + ); + + subLevelObj.sub_levels = subSubLevels.map((_) => { + return { + type: _.type, + depth: _.depth, + sub_level_id: _._id, + }; + }); + + await subLevelObj.save(); + } + + subLevelsArr.push(subLevelObj); + } + return subLevelsArr; +}; + +const createInventory = async ({ name, type }) => { + if (!(name && type)) { + return; + } + + return await Inventory.create({ + name, + type, + }); +}; + +const createItems = async (items, material) => { + const itemsArray = []; + for (const itemData of items) { + const item = { + commonName: itemData.commonName, + formalName: itemData.formalName, + description: itemData.description, + manufacturer: itemData.manufacturer, + size: itemData.size, + color: itemData.color, + type: itemData.type, + unitOfMaterial: itemData.unitOfMaterial, + unitCost: itemData.unitCost, + packageCount: itemData.packageCount, + countPerPallet: itemData.countPerPallet, + countPerPalletPackage: itemData.countPerPalletPackage, + customAttributes: itemData.customAttributes, + material, + }; + + if (Object.values(item).every((_) => _)) { + const itemObj = await Item.create(item); + itemsArray.push(itemObj); + } + } + return itemsArray; +}; + +const createMaterials = async (materials, inventory, parent = undefined) => { + const materialsData = []; + for (const materialData of materials) { + const material = await Material.create({ + name, + parent, + inventory, + }); + + let materialFamily; + if (materialData.family) { + materialFamily = await createMaterials( + materialData.family, + inventory, + material + ); + } + + let items; + if (materialData.items) { + items = await createItems(materialData.items, material); + } + + materialsData.push({ + material, + family: materialFamily, + items, + }); + } + + return materialsData; +}; + +module.exports = { + createWarehouseSchema: async (req, res, next) => { + try { + const warehouseSchema = {}; + if (!req.body.warehouse) { + res.status(400).send({ + success: false, + message: "Creation of Inventory Failed, missing params", + }); + return; + } + + const warehouse = await createWarehouse(req.body.warehouse); + if (!warehouse) { + res.status(400).send({ + success: false, + message: "Creation of Inventory Failed, invalid/missing params", + }); + return; + } + + warehouseSchema.warehouse = warehouse; + if (!req.body.warehouse.zones) { + const zones = createZones(req.body.warehouse.zones, warehouse); + if (!zones) { + res.status(400).send({ + success: false, + message: "Creation of Zones Failed, invalid/missing params", + }); + return; + } + + warehouseSchema.warehouse.zones = zones; + } + res.send({ success: true, data: warehouseSchema }); + } catch (error) { + next(error); + } + }, + createInventorySchema: async (req, res, next) => { + try { + const inventorySchema = {}; + if (!req.body.inventory) { + res.status(400).send({ + success: false, + message: "Creation of Inventory Failed, missing params", + }); + return; + } + + const inventory = await createInventory(req.body.inventory); + + if (!inventory) { + res.status(400).send({ + success: false, + message: "Creation of Inventory Failed, invalid/missing params", + }); + return; + } + inventorySchema.inventory = inventory; + + if (req.body.inventory.materials) { + const materials = createMaterials( + req.body.inventory.materials, + inventory + ); + if (!materials) { + res.status(400).send({ + success: false, + message: "Creation of Materials Failed, invalid/missing params", + }); + return; + } + + inventorySchema.inventory.materials = materials; + } + + res.send({ success: true, data: inventorySchema }); + } catch (error) { + next(error); + } + }, +}; diff --git a/src/controller/dashboard.router.js b/src/controller/dashboard.router.js new file mode 100644 index 0000000..2781589 --- /dev/null +++ b/src/controller/dashboard.router.js @@ -0,0 +1,14 @@ +const router = require("express").Router(); +const controller = require("./dashboard.controller"); + +/** + * @route /dashboard/create-warehouse-schema + */ +router.post("/create-warehouse-schema", controller.createWarehouseSchema); + +/** + * @route /dashboard/create-inventory-schema + */ +router.post("/create-inventory-schema", controller.createInventorySchema); + +module.exports = router; diff --git a/src/controller/index.js b/src/controller/index.js index 3cbe6c5..82baf2a 100644 --- a/src/controller/index.js +++ b/src/controller/index.js @@ -11,6 +11,7 @@ const areaRouter = require("./area.router"); const bayRouter = require("./bay.router"); const rowRouter = require("./row.router"); const levelRouter = require("./level.router"); +const dashboardRouter = require("./dashboard.router"); router.use("/user-role", AuthenticateMiddleware, userRoleRouter); router.use("/user-permission", AuthenticateMiddleware, userPermissionRouter); @@ -22,7 +23,7 @@ router.use("/area", areaRouter); router.use("/bay", bayRouter); router.use("/row", rowRouter); router.use("/level", levelRouter); - +router.use("/dashboard", dashboardRouter); router.get("/", (req, res) => { res.send({ success: true, message: "Hello world" }); diff --git a/src/controller/item.controller.js b/src/controller/item.controller.js index f584e80..1653df2 100644 --- a/src/controller/item.controller.js +++ b/src/controller/item.controller.js @@ -1,4 +1,6 @@ +const mongoose = require("mongoose"); const Item = require("../models/Item"); +const Material = require("../models/Material"); module.exports = { /** @@ -28,6 +30,10 @@ module.exports = { * Create a Item */ createItem: async (req, res, next) => { + let material; + if (req.body.materialId && mongoose.isValidObjectId(req.body.materialId)) { + material = await Material.findById(material); + } const item = { commonName: req.body.commonName, formalName: req.body.formalName, @@ -42,6 +48,7 @@ module.exports = { countPerPallet: req.body.countPerPallet, countPerPalletPackage: req.body.countPerPalletPackage, customAttributes: req.body.customAttributes, + material, }; if (Object.values(item).every((_) => _)) { diff --git a/src/models/Bay.js b/src/models/Bay.js index 1c69b21..ca48242 100644 --- a/src/models/Bay.js +++ b/src/models/Bay.js @@ -37,6 +37,6 @@ const schema = new mongoose.Schema( } ); -const Level = mongoose.model("Level", schema); +const Bay = mongoose.model("Bay", schema); -module.exports = Level; +module.exports = Bay; diff --git a/src/models/Item.js b/src/models/Item.js index b9056be..6835345 100644 --- a/src/models/Item.js +++ b/src/models/Item.js @@ -18,6 +18,11 @@ const schema = new mongoose.Schema( required: true, trim: true, }, + material: { + type: mongoose.Schema.Types.ObjectId, + ref: "Material", + required: true, + }, manufacturer: { type: String, required: true, diff --git a/src/models/Level.js b/src/models/Level.js index 3e7b010..43b04c0 100644 --- a/src/models/Level.js +++ b/src/models/Level.js @@ -51,6 +51,6 @@ const schema = new mongoose.Schema( } ); -const Level = mongoose.models.Level || mongoose.model("Level", schema); +const Level = mongoose.model("Level", schema); module.exports = Level; diff --git a/src/models/Sublevel.js b/src/models/Sublevel.js index 06a52f5..d5aeeff 100644 --- a/src/models/Sublevel.js +++ b/src/models/Sublevel.js @@ -67,6 +67,6 @@ const schema = new mongoose.Schema( } ); -const Level = mongoose.model("Level", schema); +const Sublevel = mongoose.model("Sublevel", schema); -module.exports = Level; +module.exports = Sublevel; From 7e09bccc5194d46ef9c87848d5ff7777fb52be5e Mon Sep 17 00:00:00 2001 From: Sathishkumar Krishnan Date: Wed, 29 Dec 2021 07:21:57 +0530 Subject: [PATCH 10/13] fix: typo --- src/controller/dashboard.controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controller/dashboard.controller.js b/src/controller/dashboard.controller.js index cd99c29..288f5b2 100644 --- a/src/controller/dashboard.controller.js +++ b/src/controller/dashboard.controller.js @@ -250,7 +250,7 @@ module.exports = { if (!req.body.warehouse) { res.status(400).send({ success: false, - message: "Creation of Inventory Failed, missing params", + message: "Creation of Warehouse Failed, missing params", }); return; } @@ -259,7 +259,7 @@ module.exports = { if (!warehouse) { res.status(400).send({ success: false, - message: "Creation of Inventory Failed, invalid/missing params", + message: "Creation of Warehouse Failed, invalid/missing params", }); return; } From edd8ff9bb254682510c67b095fc96e1488722397 Mon Sep 17 00:00:00 2001 From: Llewellyn D'souza Date: Wed, 29 Dec 2021 09:57:49 +0530 Subject: [PATCH 11/13] Updated: Warehouse image endpoint logic --- src/controller/warehouse.controller.js | 14 ++++++++++++-- src/controller/warehouse.router.js | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/controller/warehouse.controller.js b/src/controller/warehouse.controller.js index 6aaae28..01c7a4a 100644 --- a/src/controller/warehouse.controller.js +++ b/src/controller/warehouse.controller.js @@ -60,8 +60,18 @@ module.exports = { */ addWarehouseImage: async (req, res, next) => { // req.file contains the `warehouse-image` - console.dir({ file: req.file }); - res.send("ok"); + console.dir("Warehouse image uploaded:", { file: req.file }); + + const { id } = req.params; + + try { + const warehouseDetails = await Warehouse.findById(id); + warehouseDetails.imageUrl = req.file.path; + await warehouseDetails.save(); + res.send({ success: true, data: warehouseDetails }); + } catch (err) { + next(err); + } }, /** diff --git a/src/controller/warehouse.router.js b/src/controller/warehouse.router.js index 4c2e7cf..cd8bf99 100644 --- a/src/controller/warehouse.router.js +++ b/src/controller/warehouse.router.js @@ -16,7 +16,7 @@ router.post("/", controller.createWarehouse); * @route /warehouse/add-image */ router.post( - "/add-image", + "/add-image/:id", upload.single("warehouse-image"), controller.addWarehouseImage ); From e3271562d8157196c2a41abc4759853bc731b100 Mon Sep 17 00:00:00 2001 From: Llewellyn D'souza Date: Wed, 29 Dec 2021 10:01:27 +0530 Subject: [PATCH 12/13] Removed: comments and logs --- src/controller/warehouse.controller.js | 1 - src/middleware/fileUpload.js | 15 +++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/controller/warehouse.controller.js b/src/controller/warehouse.controller.js index 01c7a4a..555490b 100644 --- a/src/controller/warehouse.controller.js +++ b/src/controller/warehouse.controller.js @@ -59,7 +59,6 @@ module.exports = { * Upload an image for the warehouse */ addWarehouseImage: async (req, res, next) => { - // req.file contains the `warehouse-image` console.dir("Warehouse image uploaded:", { file: req.file }); const { id } = req.params; diff --git a/src/middleware/fileUpload.js b/src/middleware/fileUpload.js index ad27f9f..e26d9ca 100644 --- a/src/middleware/fileUpload.js +++ b/src/middleware/fileUpload.js @@ -6,26 +6,17 @@ const storage = multer.diskStorage({ cb(null, "./uploads/"); }, limits: { - // files: 1, + // files: 1, // Limit number of file uploads, if needed fileSize: 1024 * 1024, }, filename: function (req, file, cb) { cb( null, - file.fieldname + - "-" + - Date.now() + - "." + - file.originalname.split(".")[file.originalname.split(".").length - 1] + file.fieldname + "-" + Date.now() + "." + file.originalname.split(".")[file.originalname.split(".").length - 1] ); }, onFileUploadStart: function (file) { - console.log("Inside uploads"); - if ( - file.mimetype == "image/jpg" || - file.mimetype == "image/jpeg" || - file.mimetype == "image/png" - ) { + if (file.mimetype == "image/jpg" || file.mimetype == "image/jpeg" || file.mimetype == "image/png") { return true; } else { return false; From 2fec07c2885ec0e374f2d7dfa99423f9e003ad25 Mon Sep 17 00:00:00 2001 From: Llewellyn D'souza Date: Wed, 29 Dec 2021 10:09:18 +0530 Subject: [PATCH 13/13] Added: Handle invalid ID --- src/controller/warehouse.controller.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/controller/warehouse.controller.js b/src/controller/warehouse.controller.js index 555490b..968cd36 100644 --- a/src/controller/warehouse.controller.js +++ b/src/controller/warehouse.controller.js @@ -65,6 +65,10 @@ module.exports = { try { const warehouseDetails = await Warehouse.findById(id); + if (!warehouseDetails) { + res.send({ success: false, message: "ID not found" }); + return; + } warehouseDetails.imageUrl = req.file.path; await warehouseDetails.save(); res.send({ success: true, data: warehouseDetails });