diff --git a/src/controllers/installationController.js b/src/controllers/installationController.js index 3bff9d81..7a3f7b21 100644 --- a/src/controllers/installationController.js +++ b/src/controllers/installationController.js @@ -1725,20 +1725,20 @@ exports.mastrerList = async (req, reply) => { // }; + exports.getMasterSlaveSummary = async (req, reply) => { try { const { customerId } = req.params; if (!customerId) { - return reply.status(400).send({ error: 'customerId is required' }); + return reply.status(400).send({ error: "customerId is required" }); } - // Fetch all masters for the customer - const masters = await Insensors.find({ customerId, type: 'master' }).lean(); + // Fetch all master devices for the customer + const masters = await Insensors.find({ customerId, type: "master" }).lean(); // Fetch orders to map hardwareId to masterName/location const orders = await Order.find({ customerId }).lean(); - const orderMap = {}; orders.forEach(order => { order.master_connections.forEach(connection => { @@ -1754,64 +1754,132 @@ exports.getMasterSlaveSummary = async (req, reply) => { for (const master of masters) { const orderInfo = orderMap[master.hardwareId] || {}; - // Prefer values from Insensors; fallback to orderMap + // Use Insensors values first, fallback to orders const masterName = master.masterName || orderInfo.masterName || null; const location = master.location || orderInfo.location || null; + // ➤ Fetch the latest GSM data for the master device const latestGsmData = await IotData.findOne({ hardwareId: master.hardwareId }) .sort({ date: -1, time: -1 }) .lean(); let connectedGsmDate = null; let connectedGsmTime = null; + let gsmStatus = "unknown"; + let gsmLastCheckTime = null; + let gsmLastDisconnect = master.gsm_last_disconnect_time || null; + if (latestGsmData?.date && latestGsmData?.time) { - const indiaTime = moment.tz(latestGsmData.date, 'Asia/Kolkata'); - connectedGsmDate = indiaTime.format('DD-MM-YYYY'); + const indiaTime = moment.tz(latestGsmData.date, "Asia/Kolkata"); + connectedGsmDate = indiaTime.format("DD-MM-YYYY"); connectedGsmTime = latestGsmData.time; + + const now = moment.tz("Asia/Kolkata"); + const diffInMinutes = now.diff(indiaTime, "minutes"); + + gsmStatus = diffInMinutes <= 1 ? "connected" : "disconnected"; + gsmLastCheckTime = now.format("DD-MM-YYYY HH:mm:ss"); + + // If disconnected, update the disconnect time based on the latest GSM data + if (gsmStatus === "disconnected" && !gsmLastDisconnect) { + gsmLastDisconnect = `${connectedGsmDate} ${connectedGsmTime}`; + } + + // ✅ Update master record with latest GSM info + await Insensors.updateOne( + { hardwareId: master.hardwareId }, + { + $set: { + connected_status: gsmStatus, + connected_gsm_date: connectedGsmDate, + connected_gsm_time: connectedGsmTime, + gsm_last_check_time: gsmLastCheckTime, + gsm_last_disconnect_time: gsmLastDisconnect // Update the disconnect time + } + } + ); } - let gsmLastDisconnect = master.gsm_last_disconnect_time; - if (master.connected_status === 'disconnected' && connectedGsmDate && connectedGsmTime) { - const disconnectTime = `${connectedGsmDate} ${connectedGsmTime}`; + // ➤ Save GSM disconnect time if status is disconnected and gsmLastDisconnect is set + if (gsmStatus === "disconnected" && gsmLastDisconnect) { await Insensors.updateOne( { hardwareId: master.hardwareId }, - { $set: { gsm_last_disconnect_time: disconnectTime } } + { $set: { gsm_last_disconnect_time: gsmLastDisconnect } } ); - gsmLastDisconnect = disconnectTime; } + // ➤ Now handle slaves const connectedSlaves = []; - const slaves = await Insensors.find({ connected_to: master.hardwareId, type: 'slave' }).lean(); + const slaves = await Insensors.find({ connected_to: master.hardwareId, type: "slave" }).lean(); for (const slave of slaves) { const slaveIot = await IotData.findOne({ hardwareId: slave.hardwareId }) .sort({ date: -1, time: -1 }) .lean(); - - const loraDate = - slave.connected_lora_date || - (slaveIot?.date ? moment.tz(slaveIot.date, 'Asia/Kolkata').format('DD-MM-YYYY') : null); - const loraTime = slave.connected_lora_time || slaveIot?.time || null; - - let loraLastDisconnect = slave.lora_last_disconnect_time; - if (slave.connected_status === 'disconnected' && loraDate && loraTime) { - const disconnectTime = `${loraDate} ${loraTime}`; + + let connectedLoraDate = null; + let connectedLoraTime = null; + let loraStatus = "unknown"; + let loraLastCheckTime = null; + let loraLastDisconnect = slave.lora_last_disconnect_time || null; + + if (slaveIot?.date && slaveIot?.time) { + const indiaTime = moment.tz(`${slaveIot.date} ${slaveIot.time}`, "Asia/Kolkata"); + connectedLoraDate = indiaTime.format("DD-MM-YYYY"); + connectedLoraTime = slaveIot.time; + + const now = moment.tz("Asia/Kolkata"); + const diff = now.diff(indiaTime, "minutes"); + + loraStatus = diff <= 1 ? "connected" : "disconnected"; + loraLastCheckTime = now.format("DD-MM-YYYY HH:mm:ss"); + + // Update slave record with new values + await Insensors.updateOne( + { hardwareId: slave.hardwareId }, + { + $set: { + connected_status: loraStatus, + connected_lora_date: connectedLoraDate, + connected_lora_time: connectedLoraTime, + lora_last_check_time: loraLastCheckTime + } + } + ); + + // Save disconnect time if applicable + if (loraStatus === "disconnected") { + const disconnectTime = `${connectedLoraDate} ${connectedLoraTime}`; + await Insensors.updateOne( + { hardwareId: slave.hardwareId }, + { $set: { lora_last_disconnect_time: disconnectTime } } + ); + loraLastDisconnect = disconnectTime; + } + } else { + // If no IoT data is found, mark explicitly as disconnected + loraStatus = "disconnected"; + loraLastDisconnect = loraLastDisconnect || null; await Insensors.updateOne( { hardwareId: slave.hardwareId }, - { $set: { lora_last_disconnect_time: disconnectTime } } + { + $set: { + connected_status: loraStatus, + lora_last_disconnect_time: loraLastDisconnect + } + } ); - loraLastDisconnect = disconnectTime; } - + connectedSlaves.push({ hardwareId: slave.hardwareId, - tankName: slave.tankName, - location: slave.tankLocation, - connected_status: slave.connected_status, - connected_lora_date: loraDate, - connected_lora_time: loraTime, + tankName: slave.tankName || null, + location: slave.tankLocation || null, + connected_status: loraStatus, + connected_lora_date: connectedLoraDate, + connected_lora_time: connectedLoraTime, lora_last_disconnect_time: loraLastDisconnect, - type: slave.type || 'slave' + type: slave.type || "slave" }); } @@ -1819,13 +1887,13 @@ exports.getMasterSlaveSummary = async (req, reply) => { hardwareId: master.hardwareId, masterName, location, - type: master.type || 'master', - connected_status: master.connected_status, + type: master.type || "master", + connected_status: gsmStatus, connected_slave_count: connectedSlaves.length, connected_slaves: connectedSlaves, connected_gsm_date: connectedGsmDate, connected_gsm_time: connectedGsmTime, - gsm_last_check_time: master.gsm_last_check_time || null, + gsm_last_check_time: gsmLastCheckTime, gsm_last_disconnect_time: gsmLastDisconnect, connected_lora_date: master.connected_lora_date || null, connected_lora_time: master.connected_lora_time || null @@ -1834,17 +1902,18 @@ exports.getMasterSlaveSummary = async (req, reply) => { return reply.send({ status_code: 200, - message: 'Master-slave summary retrieved successfully', + message: "Master-slave summary retrieved successfully", data: result }); - } catch (error) { - console.error('Error in getMasterSlaveSummary:', error); - return reply.status(500).send({ error: 'Internal Server Error' }); + console.error("Error in getMasterSlaveSummary:", error); + return reply.status(500).send({ error: "Internal Server Error" }); } }; + + // 🔍 Helper to get tankHeight from latest IotData record async function getTankHeight(hardwareId) { const iotData = await IotData.findOne({ 'tanks.tankhardwareId': hardwareId }) @@ -2547,145 +2616,6 @@ exports.getIotDataByCustomerAndHardwareId = async (req, reply) => { //const moment = require("moment-timezone"); -// exports.raiseATicket = async (req, reply) => { -// try { -// const { customerId, connected_to } = req.params; - -// if (!customerId || !connected_to) { -// return reply.code(400).send({ error: "customerId and connected_to are required" }); -// } - -// const sensors = await Insensors.find({ customerId }); - -// if (!sensors.length) { -// return reply.code(404).send({ message: "No sensors found for this customer." }); -// } - -// const masterSensor = sensors.find(s => s.hardwareId?.trim() === connected_to.trim() && s.type === "master"); - -// if (!masterSensor) { -// return reply.code(404).send({ message: "Master hardwareId not found." }); -// } - -// const latestMasterRecord = await IotData.findOne({ hardwareId: connected_to }).sort({ date: -1 }).lean(); - -// if (!latestMasterRecord) { -// return reply.code(404).send({ message: "No IoT data found for this hardwareId." }); -// } - -// const indiaTime = moment.tz(latestMasterRecord.date, "Asia/Kolkata"); -// const now = moment.tz("Asia/Kolkata"); -// const diffInMinutesMaster = now.diff(indiaTime, "minutes"); - -// const masterDisconnected = diffInMinutesMaster > 1 ? [{ -// hardwareId: connected_to, -// masterName: masterSensor.tankName || masterSensor.tankName || "Unknown Master", -// // disconnectedAt: now.format("DD-MM-YYYY HH:mm:ss") -// }] : []; - -// const connectedSlaves = sensors.filter(sensor => -// sensor.connected_to?.trim() === connected_to.trim() && -// sensor.type === "slave" -// ); - -// const disconnectedSlaves = []; - -// for (const slave of connectedSlaves) { -// const slaveId = slave.hardwareId?.trim(); -// const matchedTank = latestMasterRecord.tanks.find(tank => tank.tankhardwareId === slaveId); - -// if (matchedTank && matchedTank.date) { -// const tankTime = moment.tz(matchedTank.date, "Asia/Kolkata"); -// const loraDiffInMinutes = now.diff(tankTime, "minutes"); - -// if (loraDiffInMinutes > 1) { -// disconnectedSlaves.push({ -// hardwareId: connected_to, -// slaveHardwareId: slaveId, -// slaveName: slave.tankName || "Unknown Slave" -// }); -// } -// } -// } - -// const issuesToAdd = []; - -// if (masterDisconnected.length > 0) { -// const existingGsmIssue = await Support.findOne({ -// "issues.hardwareId": connected_to, -// "issues.type": "GSM Disconnected" -// }); - -// if (!existingGsmIssue) { -// issuesToAdd.push({ -// type: "GSM Disconnected", -// hardwareId: connected_to, -// message: `Master GSM disconnected - ${connected_to}`, -// //disconnectedAt: now.format("DD-MM-YYYY HH:mm:ss") -// }); -// } -// } - -// // Check for already existing slave issues -// const newHardwareIds = []; -// const newSlaveNames = []; - -// for (const slave of disconnectedSlaves) { -// const existingSlaveIssue = await Support.findOne({ -// "issues.hardwareIds": slave.slaveHardwareId, -// "issues.masterHardwareId": connected_to, -// "issues.type": "LoRa Disconnected" -// }); - -// if (!existingSlaveIssue) { -// newHardwareIds.push(slave.slaveHardwareId); -// newSlaveNames.push(slave.slaveName); -// } -// } - -// if (newHardwareIds.length > 0) { -// issuesToAdd.push({ -// type: "LoRa Disconnected", -// masterHardwareId: connected_to, -// hardwareIds: newHardwareIds, -// slaveNames: newSlaveNames, -// message: `Slaves LoRa disconnected under master ${connected_to}`, -// // disconnectedAt: now.format("DD-MM-YYYY HH:mm:ss") -// }); -// } - -// if (issuesToAdd.length > 0) { -// const supportRecord = await Support.findOne({ supportId: "AWHYSU64" }); - -// if (supportRecord) { -// await Support.findOneAndUpdate( -// { _id: supportRecord._id }, -// { -// $push: { -// issues: { $each: issuesToAdd } -// }, -// updatedAt: new Date() -// }, -// { new: true } -// ); -// } else { -// console.error("Support record not found for supportId AWHYSU64"); -// } -// } - -// return reply.send({ -// status_code: 200, -// message: "Checked connection and updated support if needed.", -// masterDisconnected, -// disconnectedSlaves -// }); - -// } catch (error) { -// console.error("Error raising ticket:", error); -// return reply.code(500).send({ error: "Internal server error" }); -// } -// }; - exports.raiseATicket = async (req, reply) => { try { const { customerId, connected_to } = req.params; @@ -2712,54 +2642,39 @@ exports.raiseATicket = async (req, reply) => { return reply.code(404).send({ message: "No IoT data found for this hardwareId." }); } - const now = moment.tz("Asia/Kolkata"); const indiaTime = moment.tz(latestMasterRecord.date, "Asia/Kolkata"); + const now = moment.tz("Asia/Kolkata"); const diffInMinutesMaster = now.diff(indiaTime, "minutes"); const masterDisconnected = diffInMinutesMaster > 1 ? [{ hardwareId: connected_to, - masterName: masterSensor.tankName || "Unknown Master", - connected_status: "disconnected", - last_seen_minutes_ago: diffInMinutesMaster + masterName: masterSensor.tankName || masterSensor.tankName || "Unknown Master", + // disconnectedAt: now.format("DD-MM-YYYY HH:mm:ss") }] : []; - const connectedSlaves = sensors.filter(sensor => + const connectedSlaves = sensors.filter(sensor => sensor.connected_to?.trim() === connected_to.trim() && sensor.type === "slave" ); const disconnectedSlaves = []; - const slaveStatusList = []; for (const slave of connectedSlaves) { const slaveId = slave.hardwareId?.trim(); const matchedTank = latestMasterRecord.tanks.find(tank => tank.tankhardwareId === slaveId); - let isDisconnected = true; - let loraDiffInMinutes = null; - if (matchedTank && matchedTank.date) { const tankTime = moment.tz(matchedTank.date, "Asia/Kolkata"); - loraDiffInMinutes = now.diff(tankTime, "minutes"); + const loraDiffInMinutes = now.diff(tankTime, "minutes"); - if (loraDiffInMinutes <= 1) { - isDisconnected = false; + if (loraDiffInMinutes > 1) { + disconnectedSlaves.push({ + hardwareId: connected_to, + slaveHardwareId: slaveId, + slaveName: slave.tankName || "Unknown Slave" + }); } } - - const slaveInfo = { - hardwareId: connected_to, - slaveHardwareId: slaveId, - slaveName: slave.tankName || "Unknown Slave", - connected_status: isDisconnected ? "disconnected" : "connected", - last_seen_minutes_ago: loraDiffInMinutes - }; - - slaveStatusList.push(slaveInfo); - - if (isDisconnected) { - disconnectedSlaves.push(slaveInfo); - } } const issuesToAdd = []; @@ -2774,11 +2689,13 @@ exports.raiseATicket = async (req, reply) => { issuesToAdd.push({ type: "GSM Disconnected", hardwareId: connected_to, - message: `Master GSM disconnected - ${connected_to}` + message: `Master GSM disconnected - ${connected_to}`, + //disconnectedAt: now.format("DD-MM-YYYY HH:mm:ss") }); } } + // Check for already existing slave issues const newHardwareIds = []; const newSlaveNames = []; @@ -2801,7 +2718,8 @@ exports.raiseATicket = async (req, reply) => { masterHardwareId: connected_to, hardwareIds: newHardwareIds, slaveNames: newSlaveNames, - message: `Slaves LoRa disconnected under master ${connected_to}` + message: `Slaves LoRa disconnected under master ${connected_to}`, + // disconnectedAt: now.format("DD-MM-YYYY HH:mm:ss") }); } @@ -2828,8 +2746,7 @@ exports.raiseATicket = async (req, reply) => { status_code: 200, message: "Checked connection and updated support if needed.", masterDisconnected, - disconnectedSlaves, - connectedSlaves: slaveStatusList + disconnectedSlaves }); } catch (error) { @@ -2838,6 +2755,158 @@ exports.raiseATicket = async (req, reply) => { } }; +// exports.raiseATicket = async (req, reply) => { +// try { +// const { customerId, connected_to } = req.params; + +// if (!customerId || !connected_to) { +// return reply.code(400).send({ error: "customerId and connected_to are required" }); +// } + +// const sensors = await Insensors.find({ customerId }); + +// if (!sensors.length) { +// return reply.code(404).send({ message: "No sensors found for this customer." }); +// } + +// const masterSensor = sensors.find(s => s.hardwareId?.trim() === connected_to.trim() && s.type === "master"); + +// if (!masterSensor) { +// return reply.code(404).send({ message: "Master hardwareId not found." }); +// } + +// const latestMasterRecord = await IotData.findOne({ hardwareId: connected_to }).sort({ date: -1 }).lean(); + +// if (!latestMasterRecord) { +// return reply.code(404).send({ message: "No IoT data found for this hardwareId." }); +// } + +// const now = moment.tz("Asia/Kolkata"); +// const indiaTime = moment.tz(latestMasterRecord.date, "Asia/Kolkata"); +// const diffInMinutesMaster = now.diff(indiaTime, "minutes"); + +// const masterDisconnected = diffInMinutesMaster > 1 ? [{ +// hardwareId: connected_to, +// masterName: masterSensor.tankName || "Unknown Master", +// connected_status: "disconnected", +// last_seen_minutes_ago: diffInMinutesMaster +// }] : []; + +// const connectedSlaves = sensors.filter(sensor => +// sensor.connected_to?.trim() === connected_to.trim() && +// sensor.type === "slave" +// ); + +// const disconnectedSlaves = []; +// const slaveStatusList = []; + +// for (const slave of connectedSlaves) { +// const slaveId = slave.hardwareId?.trim(); +// const matchedTank = latestMasterRecord.tanks.find(tank => tank.tankhardwareId === slaveId); + +// let isDisconnected = true; +// let loraDiffInMinutes = null; + +// if (matchedTank && matchedTank.date) { +// const tankTime = moment.tz(matchedTank.date, "Asia/Kolkata"); +// loraDiffInMinutes = now.diff(tankTime, "minutes"); + +// if (loraDiffInMinutes <= 1) { +// isDisconnected = false; +// } +// } + +// const slaveInfo = { +// hardwareId: connected_to, +// slaveHardwareId: slaveId, +// slaveName: slave.tankName || "Unknown Slave", +// connected_status: isDisconnected ? "disconnected" : "connected", +// last_seen_minutes_ago: loraDiffInMinutes +// }; + +// slaveStatusList.push(slaveInfo); + +// if (isDisconnected) { +// disconnectedSlaves.push(slaveInfo); +// } +// } + +// const issuesToAdd = []; + +// if (masterDisconnected.length > 0) { +// const existingGsmIssue = await Support.findOne({ +// "issues.hardwareId": connected_to, +// "issues.type": "GSM Disconnected" +// }); + +// if (!existingGsmIssue) { +// issuesToAdd.push({ +// type: "GSM Disconnected", +// hardwareId: connected_to, +// message: `Master GSM disconnected - ${connected_to}` +// }); +// } +// } + +// const newHardwareIds = []; +// const newSlaveNames = []; + +// for (const slave of disconnectedSlaves) { +// const existingSlaveIssue = await Support.findOne({ +// "issues.hardwareIds": slave.slaveHardwareId, +// "issues.masterHardwareId": connected_to, +// "issues.type": "LoRa Disconnected" +// }); + +// if (!existingSlaveIssue) { +// newHardwareIds.push(slave.slaveHardwareId); +// newSlaveNames.push(slave.slaveName); +// } +// } + +// if (newHardwareIds.length > 0) { +// issuesToAdd.push({ +// type: "LoRa Disconnected", +// masterHardwareId: connected_to, +// hardwareIds: newHardwareIds, +// slaveNames: newSlaveNames, +// message: `Slaves LoRa disconnected under master ${connected_to}` +// }); +// } + +// if (issuesToAdd.length > 0) { +// const supportRecord = await Support.findOne({ supportId: "AWHYSU64" }); + +// if (supportRecord) { +// await Support.findOneAndUpdate( +// { _id: supportRecord._id }, +// { +// $push: { +// issues: { $each: issuesToAdd } +// }, +// updatedAt: new Date() +// }, +// { new: true } +// ); +// } else { +// console.error("Support record not found for supportId AWHYSU64"); +// } +// } + +// return reply.send({ +// status_code: 200, +// message: "Checked connection and updated support if needed.", +// masterDisconnected, +// disconnectedSlaves, +// connectedSlaves: slaveStatusList +// }); + +// } catch (error) { +// console.error("Error raising ticket:", error); +// return reply.code(500).send({ error: "Internal server error" }); +// } +// }; + exports.raiseATicketBuildingDetails = async (req, reply) => { diff --git a/src/controllers/storeController.js b/src/controllers/storeController.js index 20621ae4..cbcf2f24 100644 --- a/src/controllers/storeController.js +++ b/src/controllers/storeController.js @@ -2515,7 +2515,7 @@ exports.getOrdersByInstallationId = async (req, reply) => { return reply.status(400).send({ error: "installationId is required" }); } - // Fetch orders by installationId + // Fetch orders with the matching installationId const orders = await Order.find({ installationId }); if (!orders.length) { @@ -2526,30 +2526,23 @@ exports.getOrdersByInstallationId = async (req, reply) => { }); } - // Filter unique customerId + installationId combinations - const seen = new Set(); - const uniqueOrders = orders.filter(order => { - const key = `${order.customerId}_${order.installationId}`; - if (seen.has(key)) return false; - seen.add(key); - return true; - }); - - // Fetch details for each unique order + // Fetch customer details & allocated sensors for each order const ordersWithDetails = await Promise.all( - uniqueOrders.map(async (order) => { + orders.map(async (order) => { + // Fetch customer details const customer = await User.findOne({ customerId: order.customerId }).lean(); + // Fetch allocated sensors for this customer const allocatedSensors = await Insensors.find({ - installationId, - customerId: order.customerId, - status: "blocked", + storeId: order.storeId, + customerId: order.customerId, // Match only sensors allocated to this customer + status: "blocked", // Only fetch sensors that are allocated (blocked) }).lean(); return { ...order.toObject(), - customer: customer || null, - allocated_sensors: allocatedSensors, + customer: customer || null, // Include customer details or null if not found + allocated_sensors: allocatedSensors, // List of allocated sensors }; }) ); @@ -2566,6 +2559,7 @@ exports.getOrdersByInstallationId = async (req, reply) => { }; + exports.getallocatedsensorstouser= async (req, reply) => { try { const { customerId } = req.params;