|  |  |  | @ -1615,7 +1615,6 @@ exports.mastrerList = async (req, reply) => { | 
			
		
	
		
			
				
					|  |  |  |  | //     return reply.status(500).send({ error: 'Internal Server Error' });
 | 
			
		
	
		
			
				
					|  |  |  |  | //   }
 | 
			
		
	
		
			
				
					|  |  |  |  | // };
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | exports.getMasterSlaveSummary = async (req, reply) => { | 
			
		
	
		
			
				
					|  |  |  |  |   try { | 
			
		
	
		
			
				
					|  |  |  |  |     const { customerId } = req.params; | 
			
		
	
	
		
			
				
					|  |  |  | @ -1624,131 +1623,107 @@ exports.getMasterSlaveSummary = async (req, reply) => { | 
			
		
	
		
			
				
					|  |  |  |  |       return reply.status(400).send({ error: 'customerId is required' }); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const allDevices = await Insensors.find({ customerId }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  |     const masters = allDevices.filter(dev => dev.type === 'master'); | 
			
		
	
		
			
				
					|  |  |  |  |     const slaves = allDevices.filter(dev => dev.type === 'slave'); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const slaveMap = {}; | 
			
		
	
		
			
				
					|  |  |  |  |     // Fetch all masters for the customer from the Insensors schema
 | 
			
		
	
		
			
				
					|  |  |  |  |     const masters = await Insensors.find({ customerId, type: 'master' }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // Fetch orders for the customer to get masterName, location, and typeOfWater
 | 
			
		
	
		
			
				
					|  |  |  |  |     // Fetch orders for the customer to map master connections
 | 
			
		
	
		
			
				
					|  |  |  |  |     const orders = await Order.find({ customerId }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  |     const orderDetails = {};  | 
			
		
	
		
			
				
					|  |  |  |  | console.log("orders",orders.master_connections) | 
			
		
	
		
			
				
					|  |  |  |  |     // Map order information by installationId
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const orderMap = {}; | 
			
		
	
		
			
				
					|  |  |  |  |     // Mapping master hardwareId from the orders schema to masterName and location
 | 
			
		
	
		
			
				
					|  |  |  |  |     orders.forEach(order => { | 
			
		
	
		
			
				
					|  |  |  |  |       order.master_connections.forEach(connection => { | 
			
		
	
		
			
				
					|  |  |  |  |         orderDetails[connection._id] = { | 
			
		
	
		
			
				
					|  |  |  |  |           masterName: connection.master_name || 'Unknown', // masterName
 | 
			
		
	
		
			
				
					|  |  |  |  |           location: connection.location || 'Unknown',     // location
 | 
			
		
	
		
			
				
					|  |  |  |  |           typeOfWater: connection.tanks[0]?.tankLocation || 'Unknown' // typeOfWater based on tank location
 | 
			
		
	
		
			
				
					|  |  |  |  |         orderMap[connection.hardwareId] = { | 
			
		
	
		
			
				
					|  |  |  |  |           masterName: connection.master_name || 'Unknown', | 
			
		
	
		
			
				
					|  |  |  |  |           location: connection.location || 'Unknown' | 
			
		
	
		
			
				
					|  |  |  |  |         }; | 
			
		
	
		
			
				
					|  |  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     for (const slave of slaves) { | 
			
		
	
		
			
				
					|  |  |  |  |       const masterId = slave.connected_to; | 
			
		
	
		
			
				
					|  |  |  |  |       if (!slaveMap[masterId]) { | 
			
		
	
		
			
				
					|  |  |  |  |         slaveMap[masterId] = []; | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       const loraTime = slave.connected_lora_time || null; | 
			
		
	
		
			
				
					|  |  |  |  |       const loraDate = slave.connected_lora_date || null; | 
			
		
	
		
			
				
					|  |  |  |  |     const result = []; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       // Get master info from the order details map
 | 
			
		
	
		
			
				
					|  |  |  |  |       const orderInfo = orderDetails[slave.installationId] || {};  | 
			
		
	
		
			
				
					|  |  |  |  |     // Loop through each master and enrich it with data
 | 
			
		
	
		
			
				
					|  |  |  |  |     for (const master of masters) { | 
			
		
	
		
			
				
					|  |  |  |  |       const orderInfo = orderMap[master.hardwareId] || {}; // Get order info based on hardwareId
 | 
			
		
	
		
			
				
					|  |  |  |  |       const masterName = orderInfo.masterName || 'Unknown'; | 
			
		
	
		
			
				
					|  |  |  |  |       const location = orderInfo.location || 'Unknown'; | 
			
		
	
		
			
				
					|  |  |  |  |       const typeOfWater = orderInfo.typeOfWater || 'Unknown'; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       // If disconnected, update LoRa last disconnect time
 | 
			
		
	
		
			
				
					|  |  |  |  |       let loraLastDisconnect = slave.lora_last_disconnect_time || null; | 
			
		
	
		
			
				
					|  |  |  |  |       if (slave.connected_status === 'disconnected') { | 
			
		
	
		
			
				
					|  |  |  |  |         const formattedTime = `${loraDate} ${loraTime}`; | 
			
		
	
		
			
				
					|  |  |  |  |         await Insensors.updateOne( | 
			
		
	
		
			
				
					|  |  |  |  |           { hardwareId: slave.hardwareId }, | 
			
		
	
		
			
				
					|  |  |  |  |           { $set: { lora_last_disconnect_time: formattedTime } } | 
			
		
	
		
			
				
					|  |  |  |  |         ); | 
			
		
	
		
			
				
					|  |  |  |  |         loraLastDisconnect = formattedTime; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       const latestGsmData = await IotData.findOne({ hardwareId: master.hardwareId }) | 
			
		
	
		
			
				
					|  |  |  |  |         .sort({ date: -1, time: -1 }) | 
			
		
	
		
			
				
					|  |  |  |  |         .lean(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       let connectedGsmDate = null; | 
			
		
	
		
			
				
					|  |  |  |  |       let connectedGsmTime = null; | 
			
		
	
		
			
				
					|  |  |  |  |       if (latestGsmData?.date && latestGsmData?.time) { | 
			
		
	
		
			
				
					|  |  |  |  |         const indiaTime = moment.tz(latestGsmData.date, 'Asia/Kolkata'); | 
			
		
	
		
			
				
					|  |  |  |  |         connectedGsmDate = indiaTime.format('DD-MM-YYYY'); | 
			
		
	
		
			
				
					|  |  |  |  |         connectedGsmTime = latestGsmData.time; | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       const tankHeight = await getTankHeight(slave.hardwareId); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       slaveMap[masterId].push({ | 
			
		
	
		
			
				
					|  |  |  |  |         hardwareId: slave.hardwareId, | 
			
		
	
		
			
				
					|  |  |  |  |         tankName: slave.tankName || null, | 
			
		
	
		
			
				
					|  |  |  |  |         location: slave.tankLocation || null, | 
			
		
	
		
			
				
					|  |  |  |  |         connected_status: slave.connected_status || 'disconnected', | 
			
		
	
		
			
				
					|  |  |  |  |         connected_lora_time: loraTime, | 
			
		
	
		
			
				
					|  |  |  |  |         connected_lora_date: loraDate, | 
			
		
	
		
			
				
					|  |  |  |  |         lora_last_check_time: slave.lora_last_check_time || null, | 
			
		
	
		
			
				
					|  |  |  |  |         lora_last_disconnect_time: loraLastDisconnect, | 
			
		
	
		
			
				
					|  |  |  |  |         connected_to: slave.connected_to, | 
			
		
	
		
			
				
					|  |  |  |  |         masterName: masterName, | 
			
		
	
		
			
				
					|  |  |  |  |         location: location, // Adding location from the order
 | 
			
		
	
		
			
				
					|  |  |  |  |         typeOfWater: typeOfWater, // Adding typeOfWater
 | 
			
		
	
		
			
				
					|  |  |  |  |         type: slave.type || 'N/A', | 
			
		
	
		
			
				
					|  |  |  |  |         tankHeight: tankHeight || null | 
			
		
	
		
			
				
					|  |  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |       let gsmLastDisconnect = master.gsm_last_disconnect_time; | 
			
		
	
		
			
				
					|  |  |  |  |       if (master.connected_status === 'disconnected' && connectedGsmDate && connectedGsmTime) { | 
			
		
	
		
			
				
					|  |  |  |  |         const disconnectTime = `${connectedGsmDate} ${connectedGsmTime}`; | 
			
		
	
		
			
				
					|  |  |  |  |         await Insensors.updateOne({ hardwareId: master.hardwareId }, { $set: { gsm_last_disconnect_time: disconnectTime } }); | 
			
		
	
		
			
				
					|  |  |  |  |         gsmLastDisconnect = disconnectTime; | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     const response = []; | 
			
		
	
		
			
				
					|  |  |  |  |       const connectedSlaves = []; | 
			
		
	
		
			
				
					|  |  |  |  |       const slaves = await Insensors.find({ connected_to: master.hardwareId, type: 'slave' }).lean(); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     for (const master of masters) { | 
			
		
	
		
			
				
					|  |  |  |  |       const connectedSlaves = slaveMap[master.hardwareId] || []; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       let gsmLastDisconnect = master.gsm_last_disconnect_time || null; | 
			
		
	
		
			
				
					|  |  |  |  |       if (master.connected_status === 'disconnected') { | 
			
		
	
		
			
				
					|  |  |  |  |         const gsmDate = master.connected_gsm_date; | 
			
		
	
		
			
				
					|  |  |  |  |         const gsmTime = master.connected_gsm_time; | 
			
		
	
		
			
				
					|  |  |  |  |        | 
			
		
	
		
			
				
					|  |  |  |  |         if (gsmDate && gsmTime) { | 
			
		
	
		
			
				
					|  |  |  |  |           const formattedTime = `${gsmDate} ${gsmTime}`; | 
			
		
	
		
			
				
					|  |  |  |  |           await Insensors.updateOne( | 
			
		
	
		
			
				
					|  |  |  |  |             { hardwareId: master.hardwareId }, | 
			
		
	
		
			
				
					|  |  |  |  |             { $set: { gsm_last_disconnect_time: formattedTime } } | 
			
		
	
		
			
				
					|  |  |  |  |           ); | 
			
		
	
		
			
				
					|  |  |  |  |           gsmLastDisconnect = formattedTime; | 
			
		
	
		
			
				
					|  |  |  |  |       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}`; | 
			
		
	
		
			
				
					|  |  |  |  |           await Insensors.updateOne({ hardwareId: slave.hardwareId }, { $set: { lora_last_disconnect_time: disconnectTime } }); | 
			
		
	
		
			
				
					|  |  |  |  |           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, | 
			
		
	
		
			
				
					|  |  |  |  |           lora_last_disconnect_time: loraLastDisconnect, | 
			
		
	
		
			
				
					|  |  |  |  |           type: slave.type || 'slave' | 
			
		
	
		
			
				
					|  |  |  |  |         }); | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       const enriched = { | 
			
		
	
		
			
				
					|  |  |  |  |       result.push({ | 
			
		
	
		
			
				
					|  |  |  |  |         hardwareId: master.hardwareId, | 
			
		
	
		
			
				
					|  |  |  |  |         masterName: master.masterName || 'Unknown', // You can override this if you want to fetch it from orders
 | 
			
		
	
		
			
				
					|  |  |  |  |         location: master.location || 'Unknown',   // Same for location
 | 
			
		
	
		
			
				
					|  |  |  |  |         masterName, | 
			
		
	
		
			
				
					|  |  |  |  |         location, | 
			
		
	
		
			
				
					|  |  |  |  |         type: master.type || 'master', | 
			
		
	
		
			
				
					|  |  |  |  |         connected_status: master.connected_status || 'disconnected', | 
			
		
	
		
			
				
					|  |  |  |  |         connected_status: master.connected_status, | 
			
		
	
		
			
				
					|  |  |  |  |         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_disconnect_time: gsmLastDisconnect || null | 
			
		
	
		
			
				
					|  |  |  |  |       }; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       if (master.gsm_last_check_time) { | 
			
		
	
		
			
				
					|  |  |  |  |         const indiaTime = moment.tz(master.gsm_last_check_time, 'Asia/Kolkata'); | 
			
		
	
		
			
				
					|  |  |  |  |         enriched.connected_gsm_date = indiaTime.format('DD-MM-YYYY'); | 
			
		
	
		
			
				
					|  |  |  |  |         enriched.connected_gsm_time = indiaTime.format('HH:mm:ss'); | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       if (master.connected_lora_date && master.connected_lora_time) { | 
			
		
	
		
			
				
					|  |  |  |  |         enriched.connected_lora_date = master.connected_lora_date; | 
			
		
	
		
			
				
					|  |  |  |  |         enriched.connected_lora_time = master.connected_lora_time; | 
			
		
	
		
			
				
					|  |  |  |  |       } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |       response.push(enriched); | 
			
		
	
		
			
				
					|  |  |  |  |         gsm_last_disconnect_time: gsmLastDisconnect, | 
			
		
	
		
			
				
					|  |  |  |  |         connected_lora_date: master.connected_lora_date || null, | 
			
		
	
		
			
				
					|  |  |  |  |         connected_lora_time: master.connected_lora_time || null | 
			
		
	
		
			
				
					|  |  |  |  |       }); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     return reply.send({ | 
			
		
	
		
			
				
					|  |  |  |  |       status_code: 200, | 
			
		
	
		
			
				
					|  |  |  |  |       message: 'Master-slave summary retrieved successfully', | 
			
		
	
		
			
				
					|  |  |  |  |       data: response | 
			
		
	
		
			
				
					|  |  |  |  |       data: result | 
			
		
	
		
			
				
					|  |  |  |  |     }); | 
			
		
	
		
			
				
					|  |  |  |  |   } catch (err) { | 
			
		
	
		
			
				
					|  |  |  |  |     console.error('Error in getMasterSlaveSummary:', err); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   } catch (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 }) | 
			
		
	
	
		
			
				
					|  |  |  | @ -3388,4 +3363,5 @@ exports.deleteTeamMemberSupport =   async (req, reply)=> { | 
			
		
	
		
			
				
					|  |  |  |  |     console.error("Error deleting team member:", error); | 
			
		
	
		
			
				
					|  |  |  |  |     return reply.code(500).send({ error: "Internal server error" }); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | 
 |