diff --git a/src/controllers/tanksController.js b/src/controllers/tanksController.js index ee916bb0..9b538b13 100644 --- a/src/controllers/tanksController.js +++ b/src/controllers/tanksController.js @@ -6645,74 +6645,167 @@ const calculateConsumptionAndNotify = async () => { }; +exports.sendUserSetNotifications = async (request, reply) => { + const { customerId, notificationTime } = request.body; + try { + const user = await User.findOneAndUpdate( + { customerId }, + { notificationTime }, + { new: true, upsert: true } // Create if not exists + ); + await calculateWaterLevelAndNotify(); // This will only notify if notifications are allowed + + // Optionally, call the notification calculation function after setting the time + // if (allowNotifications) { + // await calculateWaterLevelAndNotify(); // This will only notify if notifications are allowed + // } + + return reply.send({ success: true, user }); + } catch (error) { + console.error("Error setting notification time:", error); + return reply.status(500).send({ success: false, message: "Internal server error" }); + } +} + +// const calculateWaterLevelAndNotify = async () => { +// try { +// const now = moment(); +// const sixHoursAgo = moment().subtract(6, "hours"); + +// console.log(`Calculating water level between ${sixHoursAgo.format("HH:mm A")} and ${now.format("HH:mm A")}`); + +// const tanks = await Tank.find({}); + +// for (const tank of tanks) { +// const { +// customerId, +// tankName, +// tankLocation, +// typeOfWater, +// capacity, +// waterlevel, +// waterlevel_at_midnight, +// } = tank; + +// // ✅ Fix: Remove commas before parsing numbers +// const tankCapacity = parseFloat(capacity.replace(/,/g, '')) || 0; +// const currentWaterLevel = parseFloat(waterlevel.replace(/,/g, '')) || 0; +// const midnightWaterLevel = parseFloat(waterlevel_at_midnight.replace(/,/g, '')) || 0; + +// if (tankCapacity === 0) { +// console.log(`Skipping tank ${tankName} due to zero capacity`); +// continue; +// } + +// const currentWaterLevelPercentage = ((currentWaterLevel / tankCapacity) * 100).toFixed(2); +// const waterUsedSinceMidnight = midnightWaterLevel - currentWaterLevel; +// const waterUsedPercentageSinceMidnight = ((waterUsedSinceMidnight / tankCapacity) * 100).toFixed(2); + +// const user = await User.findOne({ customerId }); +// if (!user || !user.fcmIds || user.fcmIds.length === 0) { +// console.log(`No FCM tokens for customer: ${customerId}`); +// continue; +// } + +// let notificationBody = +// `🛢️ Tank Name: ${tankName}\n` + +// `🏢 Location: ${tankLocation}\n` + +// `💧 Type of Water: ${typeOfWater}\n` + +// `Current Water Level: ${currentWaterLevel} liters (${currentWaterLevelPercentage}%)\n`; + +// await sendNotification(user.fcmIds, "Water Level Update", notificationBody); +// } + +// console.log("Water level notifications sent successfully."); +// } catch (err) { +// console.error("Error in water level calculation:", err); +// } +// }; const calculateWaterLevelAndNotify = async () => { try { const now = moment(); - const sixHoursAgo = moment().subtract(6, "hours"); + const currentTime = now.format("HH:mm"); // Current time in HH:mm format - console.log(`Calculating water level between ${sixHoursAgo.format("HH:mm A")} and ${now.format("HH:mm A")}`); + console.log(`Current time: ${currentTime}`); - const tanks = await Tank.find({}); + // Get all users who have allowed notifications + const users = await User.find({ }); - for (const tank of tanks) { - const { - customerId, - tankName, - tankLocation, - typeOfWater, - capacity, - waterlevel, - waterlevel_at_midnight, - } = tank; - - // ✅ Fix: Remove commas before parsing numbers - const tankCapacity = parseFloat(capacity.replace(/,/g, '')) || 0; - const currentWaterLevel = parseFloat(waterlevel.replace(/,/g, '')) || 0; - const midnightWaterLevel = parseFloat(waterlevel_at_midnight.replace(/,/g, '')) || 0; - - if (tankCapacity === 0) { - console.log(`Skipping tank ${tankName} due to zero capacity`); - continue; - } + // Iterate over each user + for (const user of users) { + const { customerId, notificationTime, fcmIds } = user; - const currentWaterLevelPercentage = ((currentWaterLevel / tankCapacity) * 100).toFixed(2); - const waterUsedSinceMidnight = midnightWaterLevel - currentWaterLevel; - const waterUsedPercentageSinceMidnight = ((waterUsedSinceMidnight / tankCapacity) * 100).toFixed(2); + // Check if the user's notification time matches the current time + if (currentTime === notificationTime) { + // Get tanks associated with the user + const tanks = await Tank.find({ customerId }); - const user = await User.findOne({ customerId }); - if (!user || !user.fcmIds || user.fcmIds.length === 0) { - console.log(`No FCM tokens for customer: ${customerId}`); - continue; - } + for (const tank of tanks) { + const { + tankName, + tankLocation, + typeOfWater, + capacity, + waterlevel, + waterlevel_at_midnight, + } = tank; + + // Remove commas before parsing numbers + const tankCapacity = parseFloat(capacity.replace(/,/g, '')) || 0; + const currentWaterLevel = parseFloat(waterlevel.replace(/,/g, '')) || 0; + const midnightWaterLevel = parseFloat(waterlevel_at_midnight.replace(/,/g, '')) || 0; + + if (tankCapacity === 0) { + console.log(`Skipping tank ${tankName} due to zero capacity`); + continue; + } + + const currentWaterLevelPercentage = ((currentWaterLevel / tankCapacity) * 100).toFixed(2); + const waterUsedSinceMidnight = midnightWaterLevel - currentWaterLevel; + const waterUsedPercentageSinceMidnight = ((waterUsedSinceMidnight / tankCapacity) * 100).toFixed(2); - let notificationBody = - `🛢️ Tank Name: ${tankName}\n` + - `🏢 Location: ${tankLocation}\n` + - `💧 Type of Water: ${typeOfWater}\n` + - `Current Water Level: ${currentWaterLevel} liters (${currentWaterLevelPercentage}%)\n`; + let notificationBody = + `🛢️ Tank Name: ${tankName}\n` + + `🏢 Location: ${tankLocation}\n` + + `💧 Type of Water: ${typeOfWater}\n` + + `Current Water Level: ${currentWaterLevel} liters (${currentWaterLevelPercentage}%)\n`; - await sendNotification(user.fcmIds, "Water Level Update", notificationBody); + await sendNotification(customerId, fcmIds, "Water Level Update", notificationBody); + console.log("Notification sent for tank:", tankName); + } + } } - console.log("Water level notifications sent successfully."); + console.log("Water level notifications processed."); } catch (err) { console.error("Error in water level calculation:", err); } }; + + + // Schedule notifications at 6 AM, 12 PM, 6 PM, and 12 AM -cron.schedule( - "0 6,12,18,0 * * *", // Cron expression for the required times - async () => { - console.log("Starting scheduled consumption notification task..."); - //await calculateConsumptionAndNotify(); - await calculateWaterLevelAndNotify(); - }, - { - timezone: "Asia/Kolkata", // Specify the timezone - } -); +// cron.schedule( +// "0 6,12,18,0 * * *", // Cron expression for the required times +// async () => { +// console.log("Starting scheduled consumption notification task..."); +// //await calculateConsumptionAndNotify(); +// await calculateWaterLevelAndNotify(); +// }, +// { +// timezone: "Asia/Kolkata", // Specify the timezone +// } +// ); + +// Schedule a function to run every minute +cron.schedule('* * * * *', async () => { + console.log("Checking for user notification times..."); + await calculateWaterLevelAndNotify(); +}, { + timezone: "Asia/Kolkata", // Specify the timezone +}); // const updateStopTimeFormat = async () => { // try { diff --git a/src/models/User.js b/src/models/User.js index 59438c45..65a844e2 100644 --- a/src/models/User.js +++ b/src/models/User.js @@ -132,6 +132,9 @@ const userSchema = new mongoose.Schema( type: Date, default: null, // Initially, no notifications sent }, + notificationTime: { type: String }, // Store user preferred notification time in HH:mm format + allowNotifications: { type: Boolean, default: true }, + createdAt: { type: Date, default: function () { diff --git a/src/routes/tanksRoute.js b/src/routes/tanksRoute.js index 8aa40fa0..d5709a25 100644 --- a/src/routes/tanksRoute.js +++ b/src/routes/tanksRoute.js @@ -1323,7 +1323,36 @@ module.exports = function (fastify, opts, next) { //preHandler: fastify.auth([fastify.authenticate]), handler: tanksController.updatetankstatus, }); - + fastify.route({ + method: "POST", + url: "/api/sendNotificationDaily", + schema: { + tags: ["Tank"], + summary: "This is for time based notification", + body: { + type: "object", + properties: { + customerId: { + type: "string", + + }, + notificationTime: { + type: "string", + }, + // allowNotifications: { + // type: "boolean" + // } + }, + }, + security: [ + { + basicAuth: [], + }, + ], + }, + //preHandler: fastify.auth([fastify.authenticate]), + handler: tanksController.sendUserSetNotifications, + }); fastify.route({ method: "GET",