|
|
|
@ -2984,7 +2984,7 @@ exports.getIotDataByCustomerAndHardwareId = async (req, reply) => {
|
|
|
|
|
// const slaveNames = disconnectedSlaves.map(s => s.slaveName);
|
|
|
|
|
|
|
|
|
|
// // Check if disconnection is at least 15 minutes old
|
|
|
|
|
// if (diffInMinutes >= 15) {
|
|
|
|
|
// if (diffInMinutes >= 1) {
|
|
|
|
|
// issuesToAdd.push({
|
|
|
|
|
// type: "GSM or LoRa Disconnected",
|
|
|
|
|
// masterHardwareId: connected_to,
|
|
|
|
@ -3039,160 +3039,480 @@ exports.getIotDataByCustomerAndHardwareId = async (req, reply) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// exports.raiseATicket = async (req, reply) => {
|
|
|
|
|
// try {
|
|
|
|
|
// const { customerId, connected_to } = req.params;
|
|
|
|
|
|
|
|
|
|
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" });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (!customerId || !connected_to) {
|
|
|
|
|
return reply.code(400).send({ error: "customerId and connected_to are required" });
|
|
|
|
|
}
|
|
|
|
|
// // Fetch all sensors and orders for the customer
|
|
|
|
|
// const sensors = await Insensors.find({ customerId }).lean();
|
|
|
|
|
// const orders = await Order.find({ customerId }).lean();
|
|
|
|
|
|
|
|
|
|
const sensors = await Insensors.find({ customerId });
|
|
|
|
|
// if (!sensors.length) {
|
|
|
|
|
// return reply.code(404).send({ message: "No sensors found for this customer." });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (!sensors.length) {
|
|
|
|
|
return reply.code(404).send({ message: "No sensors found for this customer." });
|
|
|
|
|
}
|
|
|
|
|
// // Find master sensor matching connected_to
|
|
|
|
|
// 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 masterSensor = sensors.find(s => s.hardwareId?.trim() === connected_to.trim() && s.type === "master");
|
|
|
|
|
// // Map orders for quick lookup of masterName and location
|
|
|
|
|
// const orderMap = {};
|
|
|
|
|
// orders.forEach(order => {
|
|
|
|
|
// order.master_connections.forEach(conn => {
|
|
|
|
|
// orderMap[conn.hardwareId] = {
|
|
|
|
|
// masterName: conn.master_name || null,
|
|
|
|
|
// location: conn.location || null
|
|
|
|
|
// };
|
|
|
|
|
// });
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
if (!masterSensor) {
|
|
|
|
|
return reply.code(404).send({ message: "Master hardwareId not found." });
|
|
|
|
|
}
|
|
|
|
|
// const now = moment.tz("Asia/Kolkata");
|
|
|
|
|
|
|
|
|
|
const latestMasterRecord = await IotData.findOne({ hardwareId: connected_to }).sort({ date: -1 }).lean();
|
|
|
|
|
// // Helper to get the latest record from multiple IoT data docs
|
|
|
|
|
// function getLatestDataRecord(records) {
|
|
|
|
|
// if (!records || records.length === 0) return null;
|
|
|
|
|
// return records.reduce((latest, record) => {
|
|
|
|
|
// if (!latest) return record;
|
|
|
|
|
// return new Date(record.date) > new Date(latest.date) ? record : latest;
|
|
|
|
|
// }, null);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (!latestMasterRecord) {
|
|
|
|
|
return reply.code(404).send({ message: "No IoT data found for this hardwareId." });
|
|
|
|
|
}
|
|
|
|
|
// // Fetch all IoT data for the master (no date limit here, adjust if needed)
|
|
|
|
|
// const allMasterIotData = await IotData.find({ hardwareId: connected_to }).lean();
|
|
|
|
|
// const latestMasterRecord = getLatestDataRecord(allMasterIotData);
|
|
|
|
|
|
|
|
|
|
const now = moment.tz("Asia/Kolkata");
|
|
|
|
|
const indiaTime = moment.tz(latestMasterRecord.date, "Asia/Kolkata");
|
|
|
|
|
const diffInMinutesMaster = now.diff(indiaTime, "minutes");
|
|
|
|
|
// let masterConnectedStatus = "disconnected";
|
|
|
|
|
// let lastDataTime = "No data";
|
|
|
|
|
// let diffInMinutes = null;
|
|
|
|
|
|
|
|
|
|
const masterDisconnected = diffInMinutesMaster > 1 ? [{
|
|
|
|
|
hardwareId: connected_to,
|
|
|
|
|
masterName: masterSensor.tankName || "Unknown Master",
|
|
|
|
|
connected_status: "disconnected",
|
|
|
|
|
last_seen_minutes_ago: diffInMinutesMaster
|
|
|
|
|
}] : [];
|
|
|
|
|
// if (latestMasterRecord?.date) {
|
|
|
|
|
// const indiaTime = moment.tz(latestMasterRecord.date, "Asia/Kolkata");
|
|
|
|
|
// diffInMinutes = now.diff(indiaTime, "minutes");
|
|
|
|
|
// lastDataTime = indiaTime.format("DD-MM-YYYY HH:mm:ss");
|
|
|
|
|
// if (diffInMinutes <= 1) masterConnectedStatus = "connected"; // within 1 minute considered connected
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
const connectedSlaves = sensors.filter(sensor =>
|
|
|
|
|
sensor.connected_to?.trim() === connected_to.trim() &&
|
|
|
|
|
sensor.type === "slave"
|
|
|
|
|
);
|
|
|
|
|
// // Find slaves connected to this master
|
|
|
|
|
// const connectedSlaves = sensors.filter(
|
|
|
|
|
// s => s.connected_to?.trim() === connected_to.trim() && s.type === "slave"
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
const disconnectedSlaves = [];
|
|
|
|
|
const slaveStatusList = [];
|
|
|
|
|
// const slaveHardwareIds = connectedSlaves.map(s => s.tankhardwareId);
|
|
|
|
|
|
|
|
|
|
for (const slave of connectedSlaves) {
|
|
|
|
|
const slaveId = slave.tankhardwareId?.trim();
|
|
|
|
|
const matchedTank = latestMasterRecord.tanks.find(tank => tank.tankhardwareId === slaveId);
|
|
|
|
|
// // Fetch all IoT data for slaves
|
|
|
|
|
// const allSlaveIotData = await IotData.find({ hardwareId: { $in: slaveHardwareIds } }).lean();
|
|
|
|
|
|
|
|
|
|
let isDisconnected = true;
|
|
|
|
|
let loraDiffInMinutes = null;
|
|
|
|
|
// const formattedSlaves = [];
|
|
|
|
|
// const disconnectedSlaves = [];
|
|
|
|
|
|
|
|
|
|
if (matchedTank && matchedTank.date) {
|
|
|
|
|
const tankTime = moment.tz(matchedTank.date, "Asia/Kolkata");
|
|
|
|
|
loraDiffInMinutes = now.diff(tankTime, "minutes");
|
|
|
|
|
// for (const slave of connectedSlaves) {
|
|
|
|
|
// const slaveRecords = allSlaveIotData.filter(d => d.hardwareId === slave.tankhardwareId);
|
|
|
|
|
// const latestSlaveRecord = getLatestDataRecord(slaveRecords);
|
|
|
|
|
|
|
|
|
|
if (loraDiffInMinutes <= 1) {
|
|
|
|
|
isDisconnected = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// let slaveStatus = "disconnected";
|
|
|
|
|
// let lastSlaveDataTime = "No data";
|
|
|
|
|
// let slaveDiff = null;
|
|
|
|
|
|
|
|
|
|
const slaveInfo = {
|
|
|
|
|
hardwareId: connected_to,
|
|
|
|
|
slaveHardwareId: slaveId,
|
|
|
|
|
slaveName: slave.tankName || "Unknown Slave",
|
|
|
|
|
connected_status: isDisconnected ? "disconnected" : "connected",
|
|
|
|
|
last_seen_minutes_ago: loraDiffInMinutes
|
|
|
|
|
// if (latestSlaveRecord?.date) {
|
|
|
|
|
// const slaveTime = moment.tz(latestSlaveRecord.date, "Asia/Kolkata");
|
|
|
|
|
// slaveDiff = now.diff(slaveTime, "minutes");
|
|
|
|
|
// lastSlaveDataTime = slaveTime.format("DD-MM-YYYY HH:mm:ss");
|
|
|
|
|
// if (slaveDiff <= 1) slaveStatus = "connected";
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// if (slaveStatus === "disconnected") {
|
|
|
|
|
// disconnectedSlaves.push({
|
|
|
|
|
// slaveHardwareId: slave.tankhardwareId,
|
|
|
|
|
// slaveName: slave.tankName || "Unknown Slave"
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// formattedSlaves.push({
|
|
|
|
|
// hardwareId: slave.hardwareId,
|
|
|
|
|
// slaveName: slave.tankName || null,
|
|
|
|
|
// location: slave.tankLocation || null,
|
|
|
|
|
// type: "slave",
|
|
|
|
|
// connected_status: slaveStatus,
|
|
|
|
|
// last_data_time: lastSlaveDataTime,
|
|
|
|
|
// diff_in_minutes: slaveDiff
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const issuesToAdd = [];
|
|
|
|
|
|
|
|
|
|
// // Raise ticket only if master is disconnected and disconnection is at least 1 minute old
|
|
|
|
|
// if (masterConnectedStatus === "disconnected") {
|
|
|
|
|
// const existingMasterTicket = await Support.findOne({
|
|
|
|
|
// "issues.hardwareId": connected_to,
|
|
|
|
|
// "issues.type": "GSM or LoRa Disconnected"
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// if (!existingMasterTicket && diffInMinutes >= 1) {
|
|
|
|
|
// const slaveHardwareIds = disconnectedSlaves.map(s => s.slaveHardwareId);
|
|
|
|
|
// const slaveNames = disconnectedSlaves.map(s => s.slaveName);
|
|
|
|
|
|
|
|
|
|
// issuesToAdd.push({
|
|
|
|
|
// type: "GSM or LoRa Disconnected",
|
|
|
|
|
// masterHardwareId: connected_to,
|
|
|
|
|
// hardwareId: connected_to,
|
|
|
|
|
// hardwareIds: slaveHardwareIds,
|
|
|
|
|
// slaveNames,
|
|
|
|
|
// message: `Master ${connected_to} is disconnected along with ${slaveHardwareIds.length} slave(s)`,
|
|
|
|
|
// disconnectedAt: lastDataTime // optional
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// if (issuesToAdd.length > 0) {
|
|
|
|
|
// const supportRecord = await Support.findOne({ supportId: "AWHYSU64" });
|
|
|
|
|
|
|
|
|
|
// if (supportRecord) {
|
|
|
|
|
// await Support.findOneAndUpdate(
|
|
|
|
|
// { supportId: "AWHYSU64" },
|
|
|
|
|
// {
|
|
|
|
|
// $push: { issues: { $each: issuesToAdd } },
|
|
|
|
|
// $set: {
|
|
|
|
|
// updatedAt: new Date(),
|
|
|
|
|
// lastTicketRaisedAt: moment().tz("Asia/Kolkata").format("YYYY-MM-DD HH:mm:ss")
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const masterDetails = {
|
|
|
|
|
// hardwareId: connected_to,
|
|
|
|
|
// masterName: masterSensor.masterName || orderMap[connected_to]?.masterName || null,
|
|
|
|
|
// location: masterSensor.location || orderMap[connected_to]?.location || null,
|
|
|
|
|
// type: "master",
|
|
|
|
|
// connected_status: masterConnectedStatus,
|
|
|
|
|
// last_data_time: lastDataTime,
|
|
|
|
|
// diff_in_minutes: diffInMinutes
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
|
// status_code: 200,
|
|
|
|
|
// message: "Checked connection and raised ticket if needed.",
|
|
|
|
|
// master: masterDetails,
|
|
|
|
|
// connected_slaves: formattedSlaves
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// } 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;
|
|
|
|
|
|
|
|
|
|
// 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.tankhardwareId?.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" });
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
try {
|
|
|
|
|
if (!customerId || !connected_to) return;
|
|
|
|
|
|
|
|
|
|
const sensors = await Insensors.find({ customerId }).lean();
|
|
|
|
|
const orders = await Order.find({ customerId }).lean();
|
|
|
|
|
|
|
|
|
|
if (!sensors.length) return;
|
|
|
|
|
|
|
|
|
|
const masterSensor = sensors.find(
|
|
|
|
|
s => s.hardwareId?.trim() === connected_to.trim() && s.type === "master"
|
|
|
|
|
);
|
|
|
|
|
if (!masterSensor) return;
|
|
|
|
|
|
|
|
|
|
const orderMap = {};
|
|
|
|
|
orders.forEach(order => {
|
|
|
|
|
order.master_connections.forEach(conn => {
|
|
|
|
|
orderMap[conn.hardwareId] = {
|
|
|
|
|
masterName: conn.master_name || null,
|
|
|
|
|
location: conn.location || null
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
slaveStatusList.push(slaveInfo);
|
|
|
|
|
const now = moment.tz("Asia/Kolkata");
|
|
|
|
|
|
|
|
|
|
if (isDisconnected) {
|
|
|
|
|
disconnectedSlaves.push(slaveInfo);
|
|
|
|
|
function getLatestDataRecord(records) {
|
|
|
|
|
if (!records || records.length === 0) return null;
|
|
|
|
|
return records.reduce((latest, record) => {
|
|
|
|
|
if (!latest) return record;
|
|
|
|
|
return new Date(record.date) > new Date(latest.date) ? record : latest;
|
|
|
|
|
}, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const allMasterIotData = await IotData.find({ hardwareId: connected_to }).lean();
|
|
|
|
|
const latestMasterRecord = getLatestDataRecord(allMasterIotData);
|
|
|
|
|
|
|
|
|
|
let masterConnectedStatus = "disconnected";
|
|
|
|
|
let lastDataTime = "No data";
|
|
|
|
|
let diffInMinutes = null;
|
|
|
|
|
|
|
|
|
|
if (latestMasterRecord?.date) {
|
|
|
|
|
const indiaTime = moment.tz(latestMasterRecord.date, "Asia/Kolkata");
|
|
|
|
|
diffInMinutes = now.diff(indiaTime, "minutes");
|
|
|
|
|
lastDataTime = indiaTime.format("DD-MM-YYYY HH:mm:ss");
|
|
|
|
|
if (diffInMinutes <= 1) masterConnectedStatus = "connected";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const issuesToAdd = [];
|
|
|
|
|
const connectedSlaves = sensors.filter(
|
|
|
|
|
s => s.connected_to?.trim() === connected_to.trim() && s.type === "slave"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (masterDisconnected.length > 0) {
|
|
|
|
|
const existingGsmIssue = await Support.findOne({
|
|
|
|
|
"issues.hardwareId": connected_to,
|
|
|
|
|
"issues.type": "GSM Disconnected"
|
|
|
|
|
});
|
|
|
|
|
const slaveHardwareIds = connectedSlaves.map(s => s.tankhardwareId);
|
|
|
|
|
const allSlaveIotData = await IotData.find({ hardwareId: { $in: slaveHardwareIds } }).lean();
|
|
|
|
|
|
|
|
|
|
if (!existingGsmIssue) {
|
|
|
|
|
issuesToAdd.push({
|
|
|
|
|
type: "GSM Disconnected",
|
|
|
|
|
hardwareId: connected_to,
|
|
|
|
|
message: `Master GSM disconnected - ${connected_to}`
|
|
|
|
|
const disconnectedSlaves = [];
|
|
|
|
|
|
|
|
|
|
for (const slave of connectedSlaves) {
|
|
|
|
|
const slaveRecords = allSlaveIotData.filter(d => d.hardwareId === slave.tankhardwareId);
|
|
|
|
|
const latestSlaveRecord = getLatestDataRecord(slaveRecords);
|
|
|
|
|
|
|
|
|
|
let slaveStatus = "disconnected";
|
|
|
|
|
let slaveDiff = null;
|
|
|
|
|
|
|
|
|
|
if (latestSlaveRecord?.date) {
|
|
|
|
|
const slaveTime = moment.tz(latestSlaveRecord.date, "Asia/Kolkata");
|
|
|
|
|
slaveDiff = now.diff(slaveTime, "minutes");
|
|
|
|
|
if (slaveDiff <= 1) slaveStatus = "connected";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (slaveStatus === "disconnected") {
|
|
|
|
|
disconnectedSlaves.push({
|
|
|
|
|
slaveHardwareId: slave.tankhardwareId,
|
|
|
|
|
slaveName: slave.tankName || "Unknown Slave"
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newHardwareIds = [];
|
|
|
|
|
const supportRecord = await Support.findOne({ supportId: "AWHYSU64" });
|
|
|
|
|
if (!supportRecord) return;
|
|
|
|
|
|
|
|
|
|
const existingIssues = supportRecord.issues || [];
|
|
|
|
|
|
|
|
|
|
const existingMasterIssue = existingIssues.find(
|
|
|
|
|
issue =>
|
|
|
|
|
issue.hardwareId === connected_to &&
|
|
|
|
|
issue.type === "GSM or LoRa Disconnected"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const alreadyReportedSlaves = new Set(
|
|
|
|
|
existingMasterIssue?.hardwareIds || []
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const newSlaveHardwareIds = [];
|
|
|
|
|
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);
|
|
|
|
|
if (!alreadyReportedSlaves.has(slave.slaveHardwareId)) {
|
|
|
|
|
newSlaveHardwareIds.push(slave.slaveHardwareId);
|
|
|
|
|
newSlaveNames.push(slave.slaveName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (newHardwareIds.length > 0) {
|
|
|
|
|
issuesToAdd.push({
|
|
|
|
|
type: "LoRa Disconnected",
|
|
|
|
|
if (masterConnectedStatus === "disconnected" && diffInMinutes >= 1 && (newSlaveHardwareIds.length > 0 || !existingMasterIssue)) {
|
|
|
|
|
const newIssue = {
|
|
|
|
|
type: "GSM or LoRa Disconnected",
|
|
|
|
|
masterHardwareId: connected_to,
|
|
|
|
|
hardwareIds: newHardwareIds,
|
|
|
|
|
hardwareId: connected_to,
|
|
|
|
|
hardwareIds: newSlaveHardwareIds,
|
|
|
|
|
slaveNames: newSlaveNames,
|
|
|
|
|
message: `Slaves LoRa disconnected under master ${connected_to}`
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (issuesToAdd.length > 0) {
|
|
|
|
|
const supportRecord = await Support.findOne({ supportId: "AWHYSU64" });
|
|
|
|
|
message: `Master ${connected_to} is disconnected along with ${newSlaveHardwareIds.length} new slave(s)`,
|
|
|
|
|
disconnectedAt: lastDataTime
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (supportRecord) {
|
|
|
|
|
await Support.findOneAndUpdate(
|
|
|
|
|
{ _id: supportRecord._id },
|
|
|
|
|
{ supportId: "AWHYSU64" },
|
|
|
|
|
{
|
|
|
|
|
$push: {
|
|
|
|
|
issues: { $each: issuesToAdd }
|
|
|
|
|
$push: existingMasterIssue ? {
|
|
|
|
|
"issues.$[elem].hardwareIds": { $each: newSlaveHardwareIds },
|
|
|
|
|
"issues.$[elem].slaveNames": { $each: newSlaveNames }
|
|
|
|
|
} : {
|
|
|
|
|
issues: newIssue
|
|
|
|
|
},
|
|
|
|
|
updatedAt: new Date()
|
|
|
|
|
$set: {
|
|
|
|
|
updatedAt: new Date(),
|
|
|
|
|
lastTicketRaisedAt: now.format("YYYY-MM-DD HH:mm:ss")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{ new: true }
|
|
|
|
|
existingMasterIssue
|
|
|
|
|
? { arrayFilters: [{ "elem.hardwareId": connected_to, "elem.type": "GSM or LoRa Disconnected" }] }
|
|
|
|
|
: {}
|
|
|
|
|
);
|
|
|
|
|
} 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" });
|
|
|
|
|
console.error("Error in raiseATicketLikeLogic:", error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const cron = require("node-cron");
|
|
|
|
|
|
|
|
|
|
cron.schedule("* * * * *", async () => {
|
|
|
|
|
console.log("Running auto ticket check...");
|
|
|
|
|
|
|
|
|
|
const allMasters = await Insensors.find({ type: "master" }).lean();
|
|
|
|
|
for (const master of allMasters) {
|
|
|
|
|
await raiseATicketLikeLogic(master.customerId, master.hardwareId);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
exports.raiseATicketBuildingDetails = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
@ -4477,47 +4797,90 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
return reply.code(400).send({ error: "supportId is required" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1. Get the support record by supportId
|
|
|
|
|
// 1. Fetch support record
|
|
|
|
|
const supportRecord = await Support.findOne({ supportId }).lean();
|
|
|
|
|
if (!supportRecord) {
|
|
|
|
|
return reply.code(404).send({ message: "No support record found for this supportId" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. Extract all hardwareIds from issues
|
|
|
|
|
const hardwareIds = [];
|
|
|
|
|
// 2. Collect all hardwareIds (hardwareId + hardwareIds[])
|
|
|
|
|
const allHardwareIds = new Set();
|
|
|
|
|
for (const issue of supportRecord.issues) {
|
|
|
|
|
if (issue.hardwareId) hardwareIds.push(issue.hardwareId);
|
|
|
|
|
if (Array.isArray(issue.hardwareIds)) hardwareIds.push(...issue.hardwareIds);
|
|
|
|
|
if (issue.hardwareId) allHardwareIds.add(issue.hardwareId.trim().toLowerCase());
|
|
|
|
|
if (Array.isArray(issue.hardwareIds)) {
|
|
|
|
|
issue.hardwareIds.forEach(id => {
|
|
|
|
|
if (typeof id === "string") allHardwareIds.add(id.trim().toLowerCase());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hardwareIds.length === 0) {
|
|
|
|
|
if (allHardwareIds.size === 0) {
|
|
|
|
|
return reply.code(404).send({ message: "No hardware IDs found in issues" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. Find disconnected Insensors
|
|
|
|
|
const hardwareIdsArray = Array.from(allHardwareIds);
|
|
|
|
|
|
|
|
|
|
// 3. Find disconnected insensors using connected_to match (normalize connected_to)
|
|
|
|
|
const disconnectedSensors = await Insensors.find({
|
|
|
|
|
$or: [
|
|
|
|
|
// { hardwareId: { $in: hardwareIds } },
|
|
|
|
|
{ connected_to: { $in: hardwareIds } }
|
|
|
|
|
],
|
|
|
|
|
// connected_status: "disconnected"
|
|
|
|
|
connected_to: { $in: hardwareIdsArray }
|
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
|
|
if (disconnectedSensors.length === 0) {
|
|
|
|
|
if (!disconnectedSensors.length) {
|
|
|
|
|
return reply.code(404).send({ message: "No disconnected issues found" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. Get all unique customerIds
|
|
|
|
|
// 4. Get unique customerIds from disconnected sensors
|
|
|
|
|
const customerIds = [...new Set(disconnectedSensors.map(s => s.customerId))];
|
|
|
|
|
const customers = await User.find({ customerId: { $in: customerIds } }).lean();
|
|
|
|
|
|
|
|
|
|
// 5. Map unique customers
|
|
|
|
|
const uniqueCustomerMap = {};
|
|
|
|
|
// 5. For each customer, calculate total unique hardwareIds involved in their disconnected sensors
|
|
|
|
|
const customerHardwareMap = {};
|
|
|
|
|
|
|
|
|
|
for (const sensor of disconnectedSensors) {
|
|
|
|
|
const custId = sensor.customerId;
|
|
|
|
|
if (!customerHardwareMap[custId]) {
|
|
|
|
|
customerHardwareMap[custId] = new Set();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Normalize sensor hardwareId and connected_to for safe comparisons
|
|
|
|
|
const sensorHw = sensor.tankhardwareId?.trim().toLowerCase();
|
|
|
|
|
const sensorConnected = sensor.connected_to?.trim().toLowerCase();
|
|
|
|
|
console.log("sensorHw",sensorHw)
|
|
|
|
|
console.log("sensorConnected",sensorConnected)
|
|
|
|
|
|
|
|
|
|
for (const issue of supportRecord.issues) {
|
|
|
|
|
const issueHw = issue.hardwareId?.trim().toLowerCase();
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
issueHw &&
|
|
|
|
|
(sensorHw === issueHw || sensorConnected === issueHw)
|
|
|
|
|
) {
|
|
|
|
|
console.log(`Adding hardwareId ${issue.hardwareId} for customer ${custId}`);
|
|
|
|
|
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) {
|
|
|
|
|
console.log(`Adding hardwareId ${id} for customer ${custId}`);
|
|
|
|
|
customerHardwareMap[custId].add(id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 6. Build final response
|
|
|
|
|
const response = [];
|
|
|
|
|
|
|
|
|
|
for (const user of customers) {
|
|
|
|
|
if (!uniqueCustomerMap[user.customerId]) {
|
|
|
|
|
uniqueCustomerMap[user.customerId] = {
|
|
|
|
|
const custId = user.customerId;
|
|
|
|
|
const hardwareIdSet = customerHardwareMap[custId] || new Set();
|
|
|
|
|
|
|
|
|
|
response.push({
|
|
|
|
|
customer: {
|
|
|
|
|
customerId: user.customerId,
|
|
|
|
|
customerId: custId,
|
|
|
|
|
username: user.username || "",
|
|
|
|
|
firstName: user.profile?.firstName || "",
|
|
|
|
|
lastName: user.profile?.lastName || "",
|
|
|
|
@ -4548,14 +4911,13 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
stripePaymentStatus: user.stripePaymentStatus || false,
|
|
|
|
|
stripeSubscriptionStatus: user.stripeSubscriptionStatus || false,
|
|
|
|
|
createdAt: user.createdAt,
|
|
|
|
|
updatedAt: user.updatedAt
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
updatedAt: user.updatedAt,
|
|
|
|
|
lastTicketRaisedAt: supportRecord.lastTicketRaisedAt || null,
|
|
|
|
|
totalHardwareIdsCount: hardwareIdSet.size
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const response = Object.values(uniqueCustomerMap);
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
status_code: 200,
|
|
|
|
|
data: response
|
|
|
|
@ -4567,6 +4929,10 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getDisconnectedCustomerDetailsByTeamMemberId = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
|
const { support_teamMemberId } = req.params;
|
|
|
|
|