|
|
|
@ -2310,142 +2310,142 @@ const sendNotification = async (hw_Id, customerId, fcmIds, title, body) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Function to send notifications
|
|
|
|
|
const sendDailyConsumptionNotification = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const now = new Date();
|
|
|
|
|
const currentTime = moment(now).format("HH:mm"); // e.g., "09:30"
|
|
|
|
|
const currentDate = moment(now).format("DD-MMM-YYYY"); // e.g., "28-Feb-2025"
|
|
|
|
|
|
|
|
|
|
console.log(`🕒 Checking users for scheduled notifications at ${currentTime}`);
|
|
|
|
|
|
|
|
|
|
// Fetch unique users who have enabled notifications for the current time
|
|
|
|
|
const users = await User.find({
|
|
|
|
|
allowNotifications: true,
|
|
|
|
|
notificationTime: currentTime,
|
|
|
|
|
}).select("customerId fcmIds lastNotificationSent").lean();
|
|
|
|
|
|
|
|
|
|
// Ensure unique customers only
|
|
|
|
|
const uniqueUsers = users.filter((user, index, self) =>
|
|
|
|
|
index === self.findIndex((u) => u.customerId === user.customerId)
|
|
|
|
|
);
|
|
|
|
|
// const sendDailyConsumptionNotification = async () => {
|
|
|
|
|
// try {
|
|
|
|
|
// const now = new Date();
|
|
|
|
|
// const currentTime = moment(now).format("HH:mm"); // e.g., "09:30"
|
|
|
|
|
// const currentDate = moment(now).format("DD-MMM-YYYY"); // e.g., "28-Feb-2025"
|
|
|
|
|
|
|
|
|
|
if (uniqueUsers.length === 0) {
|
|
|
|
|
console.log("⏳ No users have notifications scheduled for this time.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// console.log(`🕒 Checking users for scheduled notifications at ${currentTime}`);
|
|
|
|
|
|
|
|
|
|
for (const user of uniqueUsers) {
|
|
|
|
|
const { customerId, fcmIds, lastNotificationSent } = user;
|
|
|
|
|
// // Fetch unique users who have enabled notifications for the current time
|
|
|
|
|
// const users = await User.find({
|
|
|
|
|
// allowNotifications: true,
|
|
|
|
|
// notificationTime: currentTime,
|
|
|
|
|
// }).select("customerId fcmIds lastNotificationSent").lean();
|
|
|
|
|
|
|
|
|
|
// Ensure user has valid FCM tokens
|
|
|
|
|
if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
|
|
|
|
|
console.log(`⚠️ No valid FCM tokens for customer ID: ${customerId}`);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// // Ensure unique customers only
|
|
|
|
|
// const uniqueUsers = users.filter((user, index, self) =>
|
|
|
|
|
// index === self.findIndex((u) => u.customerId === user.customerId)
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// Remove duplicate and trim tokens
|
|
|
|
|
const uniqueTokens = [...new Set(fcmIds.map(token => token.trim()))];
|
|
|
|
|
// if (uniqueUsers.length === 0) {
|
|
|
|
|
// console.log("⏳ No users have notifications scheduled for this time.");
|
|
|
|
|
// return;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// Check if notification should be sent based on lastNotificationSent
|
|
|
|
|
const lastSent = new Date(lastNotificationSent || 0);
|
|
|
|
|
if (now - lastSent < 24 * 60 * 60 * 1000) {
|
|
|
|
|
console.log(`⏳ Skipping notification for ${customerId}, already sent in the last 24 hours.`);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// for (const user of uniqueUsers) {
|
|
|
|
|
// const { customerId, fcmIds, lastNotificationSent } = user;
|
|
|
|
|
|
|
|
|
|
// Fetch last 24-hour consumption data
|
|
|
|
|
const startTime = moment(now).subtract(1, "days").format("DD-MMM-YYYY - HH:mm");
|
|
|
|
|
const endTime = moment(now).format("DD-MMM-YYYY - HH:mm");
|
|
|
|
|
// // Ensure user has valid FCM tokens
|
|
|
|
|
// if (!Array.isArray(fcmIds) || fcmIds.length === 0) {
|
|
|
|
|
// console.log(`⚠️ No valid FCM tokens for customer ID: ${customerId}`);
|
|
|
|
|
// continue;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
console.log(`📅 Fetching consumption for ${customerId} from ${startTime} to ${endTime}`);
|
|
|
|
|
// // Remove duplicate and trim tokens
|
|
|
|
|
// const uniqueTokens = [...new Set(fcmIds.map(token => token.trim()))];
|
|
|
|
|
|
|
|
|
|
const consumptions = await TankConsumptionOriginalSchema.find({
|
|
|
|
|
customerId,
|
|
|
|
|
time: { $gte: startTime, $lt: endTime },
|
|
|
|
|
});
|
|
|
|
|
// // Check if notification should be sent based on lastNotificationSent
|
|
|
|
|
// const lastSent = new Date(lastNotificationSent || 0);
|
|
|
|
|
// if (now - lastSent < 24 * 60 * 60 * 1000) {
|
|
|
|
|
// console.log(`⏳ Skipping notification for ${customerId}, already sent in the last 24 hours.`);
|
|
|
|
|
// continue;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (consumptions.length === 0) {
|
|
|
|
|
console.log(`❌ No consumption data found for ${customerId}`);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// // Fetch last 24-hour consumption data
|
|
|
|
|
// const startTime = moment(now).subtract(1, "days").format("DD-MMM-YYYY - HH:mm");
|
|
|
|
|
// const endTime = moment(now).format("DD-MMM-YYYY - HH:mm");
|
|
|
|
|
|
|
|
|
|
// Standardized mapping for water types
|
|
|
|
|
const typeMapping = {
|
|
|
|
|
"bore water": "Bore Water",
|
|
|
|
|
"bore": "Bore Water",
|
|
|
|
|
"drinking": "Drinking Water",
|
|
|
|
|
"drink": "Drinking Water",
|
|
|
|
|
"DRINK": "Drinking Water"
|
|
|
|
|
};
|
|
|
|
|
// console.log(`📅 Fetching consumption for ${customerId} from ${startTime} to ${endTime}`);
|
|
|
|
|
|
|
|
|
|
// Calculate consumption per water type
|
|
|
|
|
let totalConsumption = 0;
|
|
|
|
|
let consumptionByType = {};
|
|
|
|
|
// const consumptions = await TankConsumptionOriginalSchema.find({
|
|
|
|
|
// customerId,
|
|
|
|
|
// time: { $gte: startTime, $lt: endTime },
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
for (const record of consumptions) {
|
|
|
|
|
let { typeofwater, consumption } = record;
|
|
|
|
|
typeofwater = (typeofwater || "").trim().toLowerCase(); // Normalize case
|
|
|
|
|
const standardType = typeMapping[typeofwater] || typeofwater; // Use mapped name or original
|
|
|
|
|
// if (consumptions.length === 0) {
|
|
|
|
|
// console.log(`❌ No consumption data found for ${customerId}`);
|
|
|
|
|
// continue;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
const consumptionValue = parseInt(consumption, 10) || 0;
|
|
|
|
|
if (!consumptionByType[standardType]) {
|
|
|
|
|
consumptionByType[standardType] = 0;
|
|
|
|
|
}
|
|
|
|
|
// // Standardized mapping for water types
|
|
|
|
|
// const typeMapping = {
|
|
|
|
|
// "bore water": "Bore Water",
|
|
|
|
|
// "bore": "Bore Water",
|
|
|
|
|
// "drinking": "Drinking Water",
|
|
|
|
|
// "drink": "Drinking Water",
|
|
|
|
|
// "DRINK": "Drinking Water"
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// // Calculate consumption per water type
|
|
|
|
|
// let totalConsumption = 0;
|
|
|
|
|
// let consumptionByType = {};
|
|
|
|
|
|
|
|
|
|
// for (const record of consumptions) {
|
|
|
|
|
// let { typeofwater, consumption } = record;
|
|
|
|
|
// typeofwater = (typeofwater || "").trim().toLowerCase(); // Normalize case
|
|
|
|
|
// const standardType = typeMapping[typeofwater] || typeofwater; // Use mapped name or original
|
|
|
|
|
|
|
|
|
|
// const consumptionValue = parseInt(consumption, 10) || 0;
|
|
|
|
|
// if (!consumptionByType[standardType]) {
|
|
|
|
|
// consumptionByType[standardType] = 0;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
consumptionByType[standardType] += consumptionValue;
|
|
|
|
|
totalConsumption += consumptionValue;
|
|
|
|
|
}
|
|
|
|
|
// consumptionByType[standardType] += consumptionValue;
|
|
|
|
|
// totalConsumption += consumptionValue;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// Prepare notification message
|
|
|
|
|
let notificationBody = `🚰 Water Consumption Report for ${currentDate}:\n`;
|
|
|
|
|
// // Prepare notification message
|
|
|
|
|
// let notificationBody = `🚰 Water Consumption Report for ${currentDate}:\n`;
|
|
|
|
|
|
|
|
|
|
for (const type in consumptionByType) {
|
|
|
|
|
const percentage = totalConsumption ? ((consumptionByType[type] / totalConsumption) * 100).toFixed(2) : 0;
|
|
|
|
|
notificationBody += `\n💧 Type: ${type}\n` +
|
|
|
|
|
`Total Consumption: ${consumptionByType[type]} liters (${percentage}%)\n`;
|
|
|
|
|
}
|
|
|
|
|
// for (const type in consumptionByType) {
|
|
|
|
|
// const percentage = totalConsumption ? ((consumptionByType[type] / totalConsumption) * 100).toFixed(2) : 0;
|
|
|
|
|
// notificationBody += `\n💧 Type: ${type}\n` +
|
|
|
|
|
// `Total Consumption: ${consumptionByType[type]} liters (${percentage}%)\n`;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
console.log(`📩 Preparing notification for ${customerId}:`, notificationBody);
|
|
|
|
|
// console.log(`📩 Preparing notification for ${customerId}:`, notificationBody);
|
|
|
|
|
|
|
|
|
|
// Update lastNotificationSent before sending
|
|
|
|
|
await User.updateOne(
|
|
|
|
|
{ customerId },
|
|
|
|
|
{ $set: { lastNotificationSent: new Date() } }
|
|
|
|
|
);
|
|
|
|
|
// // Update lastNotificationSent before sending
|
|
|
|
|
// await User.updateOne(
|
|
|
|
|
// { customerId },
|
|
|
|
|
// { $set: { lastNotificationSent: new Date() } }
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// Send notification to FCM tokens
|
|
|
|
|
const notificationPromises = uniqueTokens.map(async (token) => {
|
|
|
|
|
try {
|
|
|
|
|
await admin.messaging().send({
|
|
|
|
|
notification: { title: "Daily Water Consumption Report", body: notificationBody },
|
|
|
|
|
token,
|
|
|
|
|
data: { target: "/tank_levels" },
|
|
|
|
|
});
|
|
|
|
|
// // Send notification to FCM tokens
|
|
|
|
|
// const notificationPromises = uniqueTokens.map(async (token) => {
|
|
|
|
|
// try {
|
|
|
|
|
// await admin.messaging().send({
|
|
|
|
|
// notification: { title: "Daily Water Consumption Report", body: notificationBody },
|
|
|
|
|
// token,
|
|
|
|
|
// data: { target: "/tank_levels" },
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
console.log(`✅ Notification sent to token: ${token}`);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error(`❌ Failed to send notification to token: ${token}`, error);
|
|
|
|
|
// console.log(`✅ Notification sent to token: ${token}`);
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// console.error(`❌ Failed to send notification to token: ${token}`, error);
|
|
|
|
|
|
|
|
|
|
if (error.code === "messaging/registration-token-not-registered") {
|
|
|
|
|
await User.updateOne({ customerId }, { $pull: { fcmIds: token } });
|
|
|
|
|
console.log(`🚫 Removed invalid token: ${token}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
// if (error.code === "messaging/registration-token-not-registered") {
|
|
|
|
|
// await User.updateOne({ customerId }, { $pull: { fcmIds: token } });
|
|
|
|
|
// console.log(`🚫 Removed invalid token: ${token}`);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
await Promise.all(notificationPromises);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("❌ Error sending daily consumption notifications:", error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// await Promise.all(notificationPromises);
|
|
|
|
|
// }
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// console.error("❌ Error sending daily consumption notifications:", error);
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
cron.schedule("* * * * *", async () => {
|
|
|
|
|
console.log("🔄 Running daily consumption notification check...");
|
|
|
|
|
await sendDailyConsumptionNotification();
|
|
|
|
|
}, {
|
|
|
|
|
timezone: "Asia/Kolkata",
|
|
|
|
|
});
|
|
|
|
|
// cron.schedule("* * * * *", async () => {
|
|
|
|
|
// console.log("🔄 Running daily consumption notification check...");
|
|
|
|
|
// await sendDailyConsumptionNotification();
|
|
|
|
|
// }, {
|
|
|
|
|
// timezone: "Asia/Kolkata",
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -7012,74 +7012,74 @@ console.log("this is for testing autopush,line located in tankscontroller")
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const calculateDailyConsumptionAndNotify = async () => {
|
|
|
|
|
try {
|
|
|
|
|
const today = moment().startOf("day");
|
|
|
|
|
const yesterday = moment(today).subtract(1, "days");
|
|
|
|
|
|
|
|
|
|
// Fetch all active users
|
|
|
|
|
const activeUsers = await User.find({});
|
|
|
|
|
// const calculateDailyConsumptionAndNotify = async () => {
|
|
|
|
|
// try {
|
|
|
|
|
// const today = moment().startOf("day");
|
|
|
|
|
// const yesterday = moment(today).subtract(1, "days");
|
|
|
|
|
|
|
|
|
|
for (const user of activeUsers) {
|
|
|
|
|
const { customerId, fcmIds } = user;
|
|
|
|
|
// // Fetch all active users
|
|
|
|
|
// const activeUsers = await User.find({});
|
|
|
|
|
|
|
|
|
|
// Fetch daily consumption for the customer
|
|
|
|
|
const consumptions = await TankConsumptionOriginalSchema.find({
|
|
|
|
|
customerId,
|
|
|
|
|
time: {
|
|
|
|
|
$gte: yesterday.format("DD-MMM-YYYY - HH:mm"),
|
|
|
|
|
$lt: today.format("DD-MMM-YYYY - HH:mm"),
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
// for (const user of activeUsers) {
|
|
|
|
|
// const { customerId, fcmIds } = user;
|
|
|
|
|
|
|
|
|
|
// Calculate total consumption and capacities based on water type
|
|
|
|
|
let totalBoreConsumption = 0;
|
|
|
|
|
let totalDrinkingConsumption = 0;
|
|
|
|
|
let totalBoreCapacity = 0;
|
|
|
|
|
let totalDrinkingCapacity = 0;
|
|
|
|
|
// // Fetch daily consumption for the customer
|
|
|
|
|
// const consumptions = await TankConsumptionOriginalSchema.find({
|
|
|
|
|
// customerId,
|
|
|
|
|
// time: {
|
|
|
|
|
// $gte: yesterday.format("DD-MMM-YYYY - HH:mm"),
|
|
|
|
|
// $lt: today.format("DD-MMM-YYYY - HH:mm"),
|
|
|
|
|
// },
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
for (const record of consumptions) {
|
|
|
|
|
const typeOfWater = record.typeOfWater; // Assuming this field exists
|
|
|
|
|
const consumption = parseInt(record.consumption, 10);
|
|
|
|
|
const capacity = parseInt(record.capacity, 10); // Assuming capacity field exists
|
|
|
|
|
|
|
|
|
|
if (typeOfWater === "bore" || typeOfWater === "Bore Water") {
|
|
|
|
|
totalBoreConsumption += consumption;
|
|
|
|
|
totalBoreCapacity += capacity;
|
|
|
|
|
} else if (typeOfWater === "drinking" || typeOfWater === "Drinking Water") {
|
|
|
|
|
totalDrinkingConsumption += consumption;
|
|
|
|
|
totalDrinkingCapacity += capacity;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// // Calculate total consumption and capacities based on water type
|
|
|
|
|
// let totalBoreConsumption = 0;
|
|
|
|
|
// let totalDrinkingConsumption = 0;
|
|
|
|
|
// let totalBoreCapacity = 0;
|
|
|
|
|
// let totalDrinkingCapacity = 0;
|
|
|
|
|
|
|
|
|
|
// Calculate percentages
|
|
|
|
|
const boreConsumptionPercentage = totalBoreCapacity
|
|
|
|
|
? ((totalBoreConsumption / totalBoreCapacity) * 100).toFixed(2)
|
|
|
|
|
: 0;
|
|
|
|
|
// for (const record of consumptions) {
|
|
|
|
|
// const typeOfWater = record.typeOfWater; // Assuming this field exists
|
|
|
|
|
// const consumption = parseInt(record.consumption, 10);
|
|
|
|
|
// const capacity = parseInt(record.capacity, 10); // Assuming capacity field exists
|
|
|
|
|
|
|
|
|
|
// if (typeOfWater === "bore" || typeOfWater === "Bore Water") {
|
|
|
|
|
// totalBoreConsumption += consumption;
|
|
|
|
|
// totalBoreCapacity += capacity;
|
|
|
|
|
// } else if (typeOfWater === "drinking" || typeOfWater === "Drinking Water") {
|
|
|
|
|
// totalDrinkingConsumption += consumption;
|
|
|
|
|
// totalDrinkingCapacity += capacity;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
const drinkingConsumptionPercentage = totalDrinkingCapacity
|
|
|
|
|
? ((totalDrinkingConsumption / totalDrinkingCapacity) * 100).toFixed(2)
|
|
|
|
|
: 0;
|
|
|
|
|
// // Calculate percentages
|
|
|
|
|
// const boreConsumptionPercentage = totalBoreCapacity
|
|
|
|
|
// ? ((totalBoreConsumption / totalBoreCapacity) * 100).toFixed(2)
|
|
|
|
|
// : 0;
|
|
|
|
|
|
|
|
|
|
// Prepare notification body
|
|
|
|
|
const reportDate = yesterday.format("DD-MMM-YYYY");
|
|
|
|
|
let notificationBody = `Daily Water Consumption Report for ${reportDate}:\n`;
|
|
|
|
|
notificationBody += `Total Bore Consumption: ${totalBoreConsumption} liters\n`;
|
|
|
|
|
notificationBody += `Bore Water Consumption Percentage: ${boreConsumptionPercentage}%\n`;
|
|
|
|
|
notificationBody += `Total Drinking Consumption: ${totalDrinkingConsumption} liters\n`;
|
|
|
|
|
notificationBody += `Drinking Water Consumption Percentage: ${drinkingConsumptionPercentage}%\n`;
|
|
|
|
|
// const drinkingConsumptionPercentage = totalDrinkingCapacity
|
|
|
|
|
// ? ((totalDrinkingConsumption / totalDrinkingCapacity) * 100).toFixed(2)
|
|
|
|
|
// : 0;
|
|
|
|
|
|
|
|
|
|
// Send notification if FCM IDs are present
|
|
|
|
|
if (fcmIds && fcmIds.length > 0) {
|
|
|
|
|
await sendNotification(fcmIds, "Daily Water Consumption Report", notificationBody);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// // Prepare notification body
|
|
|
|
|
// const reportDate = yesterday.format("DD-MMM-YYYY");
|
|
|
|
|
// let notificationBody = `Daily Water Consumption Report for ${reportDate}:\n`;
|
|
|
|
|
// notificationBody += `Total Bore Consumption: ${totalBoreConsumption} liters\n`;
|
|
|
|
|
// notificationBody += `Bore Water Consumption Percentage: ${boreConsumptionPercentage}%\n`;
|
|
|
|
|
// notificationBody += `Total Drinking Consumption: ${totalDrinkingConsumption} liters\n`;
|
|
|
|
|
// notificationBody += `Drinking Water Consumption Percentage: ${drinkingConsumptionPercentage}%\n`;
|
|
|
|
|
|
|
|
|
|
// // Send notification if FCM IDs are present
|
|
|
|
|
// if (fcmIds && fcmIds.length > 0) {
|
|
|
|
|
// await sendNotification(fcmIds, "Daily Water Consumption Report", notificationBody);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
console.log("Daily consumption notifications sent successfully.");
|
|
|
|
|
} catch (err) {
|
|
|
|
|
console.error("Error sending daily consumption notifications:", err);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
// console.log("Daily consumption notifications sent successfully.");
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
// console.error("Error sending daily consumption notifications:", err);
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// Schedule the cron job to run daily at 9 AM
|
|
|
|
|
// cron.schedule(
|
|
|
|
|