|  |  |  | @ -3714,6 +3714,7 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => { | 
			
		
	
		
			
				
					|  |  |  |  |       }, null); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 🔸 Master status check
 | 
			
		
	
		
			
				
					|  |  |  |  |     const allMasterIotData = await IotData.find({ hardwareId: connected_to }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  |     const latestMasterRecord = getLatestDataRecord(allMasterIotData); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -3728,17 +3729,40 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => { | 
			
		
	
		
			
				
					|  |  |  |  |       if (diffInMinutes <= 2) masterConnectedStatus = "connected"; | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 🔸 Slave status check
 | 
			
		
	
		
			
				
					|  |  |  |  |     const connectedSlaves = sensors.filter( | 
			
		
	
		
			
				
					|  |  |  |  |       s => s.connected_to?.trim() === connected_to.trim() && s.type === "slave" | 
			
		
	
		
			
				
					|  |  |  |  |     ); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const slaveHardwareIds = connectedSlaves.map(s => s.tankhardwareId); | 
			
		
	
		
			
				
					|  |  |  |  |     const allSlaveIotData = await IotData.find({ hardwareId: { $in: slaveHardwareIds } }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  |     const allSlaveIotData = await IotData.find({ "tanks.tankhardwareId": { $in: slaveHardwareIds } }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 🔹 Create map of latest tank data
 | 
			
		
	
		
			
				
					|  |  |  |  |     const latestTankDataMap = {}; | 
			
		
	
		
			
				
					|  |  |  |  |     for (const record of allSlaveIotData) { | 
			
		
	
		
			
				
					|  |  |  |  |       const baseDate = record.date; | 
			
		
	
		
			
				
					|  |  |  |  |       for (const tank of record.tanks || []) { | 
			
		
	
		
			
				
					|  |  |  |  |         const tankId = tank.tankhardwareId; | 
			
		
	
		
			
				
					|  |  |  |  |         const tankDate = tank.date || baseDate; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (!tankId || !tankDate) continue; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if ( | 
			
		
	
		
			
				
					|  |  |  |  |           !latestTankDataMap[tankId] || | 
			
		
	
		
			
				
					|  |  |  |  |           new Date(tankDate) > new Date(latestTankDataMap[tankId].date) | 
			
		
	
		
			
				
					|  |  |  |  |         ) { | 
			
		
	
		
			
				
					|  |  |  |  |           latestTankDataMap[tankId] = { | 
			
		
	
		
			
				
					|  |  |  |  |             date: tankDate, | 
			
		
	
		
			
				
					|  |  |  |  |             time: tank.time, | 
			
		
	
		
			
				
					|  |  |  |  |             hardwareId: tankId | 
			
		
	
		
			
				
					|  |  |  |  |           }; | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const disconnectedSlaves = []; | 
			
		
	
		
			
				
					|  |  |  |  |     for (const slave of connectedSlaves) { | 
			
		
	
		
			
				
					|  |  |  |  |       const slaveRecords = allSlaveIotData.filter(d => d.hardwareId === slave.tankhardwareId); | 
			
		
	
		
			
				
					|  |  |  |  |       const latestSlaveRecord = getLatestDataRecord(slaveRecords); | 
			
		
	
		
			
				
					|  |  |  |  |       const latestSlaveRecord = latestTankDataMap[slave.tankhardwareId]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       let slaveStatus = "disconnected"; | 
			
		
	
		
			
				
					|  |  |  |  |       if (latestSlaveRecord?.date) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -3754,6 +3778,11 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => { | 
			
		
	
		
			
				
					|  |  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     console.log(",disconnectedSlaves",disconnectedSlaves) | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     if (disconnectedSlaves.length === 0 && masterConnectedStatus === "connected") { | 
			
		
	
		
			
				
					|  |  |  |  |       return; // ✅ No ticket needed
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const supportRecord = await Support.findOne({ supportId: "AWHYSU64" }); | 
			
		
	
		
			
				
					|  |  |  |  |     if (!supportRecord) return; | 
			
		
	
	
		
			
				
					|  |  |  | @ -3779,52 +3808,49 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => { | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const formattedNow = now.format("YYYY-MM-DD HH:mm:ss"); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // Only raise ticket if master is disconnected
 | 
			
		
	
		
			
				
					|  |  |  |  |     if ( | 
			
		
	
		
			
				
					|  |  |  |  |       masterConnectedStatus === "disconnected" && | 
			
		
	
		
			
				
					|  |  |  |  |       diffInMinutes >= 2 && | 
			
		
	
		
			
				
					|  |  |  |  |       (newSlaveHardwareIds.length > 0 || !existingMasterIssue) | 
			
		
	
		
			
				
					|  |  |  |  |     ) { | 
			
		
	
		
			
				
					|  |  |  |  |       if (!existingMasterIssue) { | 
			
		
	
		
			
				
					|  |  |  |  |         const newIssue = { | 
			
		
	
		
			
				
					|  |  |  |  |           type: "GSM or LoRa Disconnected", | 
			
		
	
		
			
				
					|  |  |  |  |           masterHardwareId: connected_to, | 
			
		
	
		
			
				
					|  |  |  |  |           hardwareId: connected_to, | 
			
		
	
		
			
				
					|  |  |  |  |           hardwareIds: newSlaveHardwareIds, | 
			
		
	
		
			
				
					|  |  |  |  |           slaveNames: newSlaveNames, | 
			
		
	
		
			
				
					|  |  |  |  |           message: `Master ${connected_to} is disconnected along with ${newSlaveHardwareIds.length} new slave(s)`, | 
			
		
	
		
			
				
					|  |  |  |  |           disconnectedAt: lastDataTime, | 
			
		
	
		
			
				
					|  |  |  |  |           lastTicketRaisedAt: formattedNow, | 
			
		
	
		
			
				
					|  |  |  |  |           resolved: false | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |         await Support.findOneAndUpdate( | 
			
		
	
		
			
				
					|  |  |  |  |           { supportId: "AWHYSU64" }, | 
			
		
	
		
			
				
					|  |  |  |  |           { $push: { issues: newIssue }, $set: { updatedAt: new Date() } } | 
			
		
	
		
			
				
					|  |  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |  |       } else { | 
			
		
	
		
			
				
					|  |  |  |  |         await Support.findOneAndUpdate( | 
			
		
	
		
			
				
					|  |  |  |  |           { supportId: "AWHYSU64" }, | 
			
		
	
		
			
				
					|  |  |  |  |           { | 
			
		
	
		
			
				
					|  |  |  |  |             $push: { | 
			
		
	
		
			
				
					|  |  |  |  |               "issues.$[elem].hardwareIds": { $each: newSlaveHardwareIds }, | 
			
		
	
		
			
				
					|  |  |  |  |               "issues.$[elem].slaveNames": { $each: newSlaveNames } | 
			
		
	
		
			
				
					|  |  |  |  |             }, | 
			
		
	
		
			
				
					|  |  |  |  |             $set: { | 
			
		
	
		
			
				
					|  |  |  |  |               "issues.$[elem].lastTicketRaisedAt": formattedNow, | 
			
		
	
		
			
				
					|  |  |  |  |               updatedAt: new Date() | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |     // 🔸 Raise new issue
 | 
			
		
	
		
			
				
					|  |  |  |  |     if (!existingMasterIssue && (masterConnectedStatus === "disconnected" || disconnectedSlaves.length > 0)) { | 
			
		
	
		
			
				
					|  |  |  |  |       const newIssue = { | 
			
		
	
		
			
				
					|  |  |  |  |         type: "GSM or LoRa Disconnected", | 
			
		
	
		
			
				
					|  |  |  |  |         masterHardwareId: connected_to, | 
			
		
	
		
			
				
					|  |  |  |  |         hardwareId: connected_to, | 
			
		
	
		
			
				
					|  |  |  |  |         hardwareIds: newSlaveHardwareIds, | 
			
		
	
		
			
				
					|  |  |  |  |         slaveNames: newSlaveNames, | 
			
		
	
		
			
				
					|  |  |  |  |         message: `Master ${connected_to} is ${masterConnectedStatus} with ${disconnectedSlaves.length} disconnected slave(s)`, | 
			
		
	
		
			
				
					|  |  |  |  |         disconnectedAt: lastDataTime, | 
			
		
	
		
			
				
					|  |  |  |  |         lastTicketRaisedAt: formattedNow, | 
			
		
	
		
			
				
					|  |  |  |  |         resolved: false | 
			
		
	
		
			
				
					|  |  |  |  |       }; | 
			
		
	
		
			
				
					|  |  |  |  |       await Support.findOneAndUpdate( | 
			
		
	
		
			
				
					|  |  |  |  |         { supportId: "AWHYSU64" }, | 
			
		
	
		
			
				
					|  |  |  |  |         { $push: { issues: newIssue }, $set: { updatedAt: new Date() } } | 
			
		
	
		
			
				
					|  |  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 🔸 Update existing issue with new disconnected slaves
 | 
			
		
	
		
			
				
					|  |  |  |  |     if (existingMasterIssue && newSlaveHardwareIds.length > 0) { | 
			
		
	
		
			
				
					|  |  |  |  |       await Support.findOneAndUpdate( | 
			
		
	
		
			
				
					|  |  |  |  |         { supportId: "AWHYSU64" }, | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |           $push: { | 
			
		
	
		
			
				
					|  |  |  |  |             "issues.$[elem].hardwareIds": { $each: newSlaveHardwareIds }, | 
			
		
	
		
			
				
					|  |  |  |  |             "issues.$[elem].slaveNames": { $each: newSlaveNames } | 
			
		
	
		
			
				
					|  |  |  |  |           }, | 
			
		
	
		
			
				
					|  |  |  |  |           { | 
			
		
	
		
			
				
					|  |  |  |  |             arrayFilters: [ | 
			
		
	
		
			
				
					|  |  |  |  |               { | 
			
		
	
		
			
				
					|  |  |  |  |                 "elem.hardwareId": connected_to, | 
			
		
	
		
			
				
					|  |  |  |  |                 "elem.type": "GSM or LoRa Disconnected", | 
			
		
	
		
			
				
					|  |  |  |  |                 "elem.resolved": false | 
			
		
	
		
			
				
					|  |  |  |  |               } | 
			
		
	
		
			
				
					|  |  |  |  |             ] | 
			
		
	
		
			
				
					|  |  |  |  |           $set: { | 
			
		
	
		
			
				
					|  |  |  |  |             "issues.$[elem].lastTicketRaisedAt": formattedNow, | 
			
		
	
		
			
				
					|  |  |  |  |             updatedAt: new Date() | 
			
		
	
		
			
				
					|  |  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |         }, | 
			
		
	
		
			
				
					|  |  |  |  |         { | 
			
		
	
		
			
				
					|  |  |  |  |           arrayFilters: [ | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |               "elem.hardwareId": connected_to, | 
			
		
	
		
			
				
					|  |  |  |  |               "elem.type": "GSM or LoRa Disconnected", | 
			
		
	
		
			
				
					|  |  |  |  |               "elem.resolved": false | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |           ] | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |       ); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |   } catch (error) { | 
			
		
	
		
			
				
					|  |  |  |  |     console.error("Error in raiseATicketLikeLogic:", error); | 
			
		
	
	
		
			
				
					|  |  |  | @ -3832,9 +3858,11 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => { | 
			
		
	
		
			
				
					|  |  |  |  | }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | cron.schedule("* * * * *", async () => { | 
			
		
	
		
			
				
					|  |  |  |  |   console.log("Running auto ticket check..."); | 
			
		
	
		
			
				
					|  |  |  |  |   const allMasters = await Insensors.find({ type: "master" }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  |   const allMasters = await Insensors.find({  }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  |   for (const master of allMasters) { | 
			
		
	
		
			
				
					|  |  |  |  |     await raiseATicketLikeLogic(master.customerId, master.hardwareId); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
	
		
			
				
					|  |  |  | @ -5294,7 +5322,7 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => { | 
			
		
	
		
			
				
					|  |  |  |  |     // 2. Filter only unresolved issues
 | 
			
		
	
		
			
				
					|  |  |  |  |     const unresolvedIssues = (supportRecord.issues || []).filter(issue => issue.resolved === false); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 3. Collect all hardwareIds (hardwareId + hardwareIds[] from unresolved issues)
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 3. Collect all unique hardwareIds (from hardwareId and hardwareIds arrays) from unresolved issues
 | 
			
		
	
		
			
				
					|  |  |  |  |     const allHardwareIds = new Set(); | 
			
		
	
		
			
				
					|  |  |  |  |     for (const issue of unresolvedIssues) { | 
			
		
	
		
			
				
					|  |  |  |  |       if (issue.hardwareId) allHardwareIds.add(issue.hardwareId.trim().toLowerCase()); | 
			
		
	
	
		
			
				
					|  |  |  | @ -5337,23 +5365,17 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => { | 
			
		
	
		
			
				
					|  |  |  |  |       const sensorConnected = sensor.connected_to?.trim().toLowerCase(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       for (const issue of unresolvedIssues) { | 
			
		
	
		
			
				
					|  |  |  |  |         const issueHw = issue.hardwareId?.trim().toLowerCase(); | 
			
		
	
		
			
				
					|  |  |  |  |         const allIssueHardwareIds = [ | 
			
		
	
		
			
				
					|  |  |  |  |           ...(issue.hardwareIds?.map(id => id?.trim().toLowerCase()) || []), | 
			
		
	
		
			
				
					|  |  |  |  |           issue.hardwareId?.trim().toLowerCase() | 
			
		
	
		
			
				
					|  |  |  |  |         ]; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if ( | 
			
		
	
		
			
				
					|  |  |  |  |           issueHw && | 
			
		
	
		
			
				
					|  |  |  |  |           (sensorHw === issueHw || sensorConnected === issueHw) | 
			
		
	
		
			
				
					|  |  |  |  |           allIssueHardwareIds.includes(sensorHw) || | 
			
		
	
		
			
				
					|  |  |  |  |           allIssueHardwareIds.includes(sensorConnected) | 
			
		
	
		
			
				
					|  |  |  |  |         ) { | 
			
		
	
		
			
				
					|  |  |  |  |           customerHardwareMap[custId].add(issue.hardwareId); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         if (Array.isArray(issue.hardwareIds)) { | 
			
		
	
		
			
				
					|  |  |  |  |           for (const id of issue.hardwareIds) { | 
			
		
	
		
			
				
					|  |  |  |  |             const idNorm = id?.trim().toLowerCase(); | 
			
		
	
		
			
				
					|  |  |  |  |             if (sensorHw === idNorm || sensorConnected === idNorm) { | 
			
		
	
		
			
				
					|  |  |  |  |               customerHardwareMap[custId].add(id); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |           } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |