From 8738d709fe768741ab459a1f39577f58fb4a508f Mon Sep 17 00:00:00 2001 From: Shaurya Date: Thu, 26 Sep 2024 01:19:58 +0530 Subject: [PATCH 1/2] User Schema Update --- controllers/onestopUserController.js | 1 + helpers/constants.js | 2 +- models/userModel.js | 9 ++++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/controllers/onestopUserController.js b/controllers/onestopUserController.js index 7fab817..6d1758a 100644 --- a/controllers/onestopUserController.js +++ b/controllers/onestopUserController.js @@ -140,6 +140,7 @@ exports.updateOnestopUserValidate = [ .exists() .isInt({min: 1000000000, max: 9999999999}), body("linkedin", "linkedin is required").optional(), + body("cycleReg", "Cycle Registration number is required").optional(), ]; exports.updateOnestopUser = asyncHandler(async (req, res) => { diff --git a/helpers/constants.js b/helpers/constants.js index f341640..991e2b2 100644 --- a/helpers/constants.js +++ b/helpers/constants.js @@ -14,7 +14,7 @@ exports.allIITGHostelsGC = ["Brahmaputra", "Kameng", "Dihing", "Barak", "Kapili" exports.allIITGWomenHostels = ["Married Scholars (Women)", "Subansiri", "Dhansiri", "Disang (Women)"]; exports.allIITGTechClubs = ["Coding Club", "CnA Club", "E-Cell", "Robotics Club", "Aeromodelling Club", "Automobile Club", "Electronics Club", "IITG.AI", "Gamedev and ESports", "Equinox", "FEC", "Whitespace", "Acumen", "4i Labs"]; exports.allIITGWelfareClubs = ["Academic Initiatives Club", "Rights and Responsibilities Club", "Red Ribbon Club", "Youth Empowerment Club", "Saathi", "Social Service Club", "Substance Abuse Awareness Club"]; -exports.allIITGHostels = ["LOHIT", "BRAHMAPUTRA", "DISANG", "KAMENG", "BARAK", "MANAS", "DIHING", "UMIAM", "SIANG", "KAPILI", "DHANSIRI", "SUBANSIRI", "MSH", "GAURANG", "DIBANG"]; +exports.allIITGHostels = ["LOHIT", "BRAHMAPUTRA", "DISANG", "KAMENG", "BARAK", "MANAS", "DIHING", "UMIAM", "SIANG", "KAPILI", "DHANSIRI", "SUBANSIRI", "MSH", "GAURANG", "DIBANG", "NON-HOSTELLER"]; exports.allIITGGymkhanaBoards = { "Sports Board": "sportsec@iitg.ac.in", "Students Web Committee (SWC)": "swc@iitg.ac.in", diff --git a/models/userModel.js b/models/userModel.js index b387338..5704cfa 100644 --- a/models/userModel.js +++ b/models/userModel.js @@ -33,7 +33,6 @@ const NotifPrefSchema = new mongoose.Schema({ required: true } }); - const userSchema = new mongoose.Schema({ name: { type: String, @@ -90,6 +89,14 @@ const userSchema = new mongoose.Schema({ notifPref: { type: NotifPrefSchema, default: defaultNotifCategoriesMap + }, + cycleReg: { + type: String, + maxLength: 20 + }, + subscribedMess: { + type: String, + enum: allIITGHostels } }); From 7cd6580f25d1abcf2b3f08de0b9a3020180e6eee Mon Sep 17 00:00:00 2001 From: Shaurya Date: Fri, 27 Sep 2024 23:34:15 +0530 Subject: [PATCH 2/2] updated messmenu resource --- admin_panel/resources/messMenu.resource.js | 91 +++++++++++++++++++++- package-lock.json | 34 ++++++++ package.json | 2 + 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/admin_panel/resources/messMenu.resource.js b/admin_panel/resources/messMenu.resource.js index 90269de..aa5e0a5 100644 --- a/admin_panel/resources/messMenu.resource.js +++ b/admin_panel/resources/messMenu.resource.js @@ -1,9 +1,15 @@ const messMenu = require("../../models/messMenuModel"); const verifyRoles = require("../utils"); const roles = require("../roles"); +const multer = require('multer'); // For file uploads +const fs = require('fs'); +const csvParser = require('csv-parser'); let allowedRoles = [roles.SUPERADMIN, roles.MESS]; +// Set up multer for file uploads +const upload = multer({ dest: 'uploads/' }); + module.exports = { resource: messMenu, options: { @@ -16,7 +22,90 @@ module.exports = { new: { isAccessible: ({ currentAdmin }) => verifyRoles(currentAdmin, allowedRoles) }, filter: { isAccessible: ({ currentAdmin }) => verifyRoles(currentAdmin, allowedRoles) }, edit: { isAccessible: ({ currentAdmin }) => verifyRoles(currentAdmin, allowedRoles) }, - delete: { isAccessible: ({ currentAdmin }) => verifyRoles(currentAdmin, allowedRoles) } + delete: { isAccessible: ({ currentAdmin }) => verifyRoles(currentAdmin, allowedRoles) }, + uploadCSV: { + actionType: 'resource', + icon: 'Document', + isAccessible: ({ currentAdmin }) => verifyRoles(currentAdmin, allowedRoles), + handler: async (request, response, context) => { + if (request.method === 'post') { + const file = request.payload.file; + const results = []; + + fs.createReadStream(file.path) + .pipe(csvParser()) + .on('data', (data) => results.push(data)) + .on('end', async () => { + try { + const hostelData = {}; + + results.forEach((row) => { + const { hostel, day, meal, mealDescription, startTiming, endTiming } = row; + if (!hostelData[hostel]) { + hostelData[hostel] = {}; + } + + if (!hostelData[hostel][day]) { + hostelData[hostel][day] = { breakfast: null, lunch: null, dinner: null }; + } + + const mealData = { + mealDescription, + startTiming: new Date(startTiming), + endTiming: new Date(endTiming), + }; + + hostelData[hostel][day][meal] = mealData; + }); + + for (const hostel in hostelData) { + const menu = hostelData[hostel]; + + await messMenu.findOneAndUpdate( + { hostel }, + { + hostel, + monday: menu.monday, + tuesday: menu.tuesday, + wednesday: menu.wednesday, + thursday: menu.thursday, + friday: menu.friday, + saturday: menu.saturday, + sunday: menu.sunday, + }, + { upsert: true, new: true } + ); + } + + fs.unlinkSync(file.path); + + return { + notice: { + message: 'CSV uploaded and menu updated successfully!', + type: 'success', + }, + }; + } catch (error) { + console.error(error); + return { + notice: { + message: 'Error processing CSV file!', + type: 'error', + }, + }; + } + }); + } + + return { + notice: { + message: 'Upload CSV file to update mess menu.', + type: 'info', + }, + }; + }, + component: AdminJS.bundle('../../components/upload-csv'), + } } } }; diff --git a/package-lock.json b/package-lock.json index 98aa89a..471c0c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "bcrypt": "^5.1.0", "connect-mongodb-session": "^3.1.1", "cookie-parser": "^1.4.6", + "csv-parser": "^3.0.0", "csvtojson": "^2.0.10", "dotenv": "^16.0.3", "ejs": "^3.1.9", @@ -24,6 +25,7 @@ "express-session": "^1.17.3", "express-validator": "^7.0.1", "firebase-admin": "^11.5.0", + "fs": "^0.0.1-security", "images-scraper": "^6.4.2", "jsonwebtoken": "^9.0.0", "mongoose": "^7.0.2", @@ -6323,6 +6325,20 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "node_modules/csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/csvtojson": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", @@ -7301,6 +7317,11 @@ "node": ">= 0.6" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -17499,6 +17520,14 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, + "csv-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.0.0.tgz", + "integrity": "sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==", + "requires": { + "minimist": "^1.2.0" + } + }, "csvtojson": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", @@ -18233,6 +18262,11 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", diff --git a/package.json b/package.json index 965a422..abbde7d 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "bcrypt": "^5.1.0", "connect-mongodb-session": "^3.1.1", "cookie-parser": "^1.4.6", + "csv-parser": "^3.0.0", "csvtojson": "^2.0.10", "dotenv": "^16.0.3", "ejs": "^3.1.9", @@ -37,6 +38,7 @@ "express-session": "^1.17.3", "express-validator": "^7.0.1", "firebase-admin": "^11.5.0", + "fs": "^0.0.1-security", "images-scraper": "^6.4.2", "jsonwebtoken": "^9.0.0", "mongoose": "^7.0.2",