|
|
|
@ -3364,6 +3364,145 @@ exports.getIotDataByCustomerAndHardwareId = async (req, reply) => {
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
// };
|
|
|
|
|
// });
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// const now = moment.tz("Asia/Kolkata");
|
|
|
|
|
|
|
|
|
|
// 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 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 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 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) {
|
|
|
|
|
// if (!alreadyReportedSlaves.has(slave.slaveHardwareId)) {
|
|
|
|
|
// newSlaveHardwareIds.push(slave.slaveHardwareId);
|
|
|
|
|
// newSlaveNames.push(slave.slaveName);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// if (masterConnectedStatus === "disconnected" && diffInMinutes >= 1 && (newSlaveHardwareIds.length > 0 || !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
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// await Support.findOneAndUpdate(
|
|
|
|
|
// { supportId: "AWHYSU64" },
|
|
|
|
|
// {
|
|
|
|
|
// $push: existingMasterIssue ? {
|
|
|
|
|
// "issues.$[elem].hardwareIds": { $each: newSlaveHardwareIds },
|
|
|
|
|
// "issues.$[elem].slaveNames": { $each: newSlaveNames }
|
|
|
|
|
// } : {
|
|
|
|
|
// issues: newIssue
|
|
|
|
|
// },
|
|
|
|
|
// $set: {
|
|
|
|
|
// updatedAt: new Date(),
|
|
|
|
|
// lastTicketRaisedAt: now.format("YYYY-MM-DD HH:mm:ss")
|
|
|
|
|
// }
|
|
|
|
|
// },
|
|
|
|
|
// existingMasterIssue
|
|
|
|
|
// ? { arrayFilters: [{ "elem.hardwareId": connected_to, "elem.type": "GSM or LoRa Disconnected" }] }
|
|
|
|
|
// : {}
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// console.error("Error in raiseATicketLikeLogic:", error);
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
try {
|
|
|
|
|
if (!customerId || !connected_to) return;
|
|
|
|
@ -3467,42 +3606,61 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (masterConnectedStatus === "disconnected" && diffInMinutes >= 1 && (newSlaveHardwareIds.length > 0 || !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
|
|
|
|
|
};
|
|
|
|
|
const formattedNow = now.format("YYYY-MM-DD HH:mm:ss");
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
masterConnectedStatus === "disconnected" &&
|
|
|
|
|
diffInMinutes >= 1 &&
|
|
|
|
|
(newSlaveHardwareIds.length > 0 || !existingMasterIssue)
|
|
|
|
|
) {
|
|
|
|
|
if (!existingMasterIssue) {
|
|
|
|
|
// Create new issue
|
|
|
|
|
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 // <-- NEW FIELD
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await Support.findOneAndUpdate(
|
|
|
|
|
{ supportId: "AWHYSU64" },
|
|
|
|
|
{
|
|
|
|
|
$push: existingMasterIssue ? {
|
|
|
|
|
"issues.$[elem].hardwareIds": { $each: newSlaveHardwareIds },
|
|
|
|
|
"issues.$[elem].slaveNames": { $each: newSlaveNames }
|
|
|
|
|
} : {
|
|
|
|
|
issues: newIssue
|
|
|
|
|
await Support.findOneAndUpdate(
|
|
|
|
|
{ supportId: "AWHYSU64" },
|
|
|
|
|
{
|
|
|
|
|
$push: { issues: newIssue },
|
|
|
|
|
$set: { updatedAt: new Date() }
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
// Update existing issue
|
|
|
|
|
await Support.findOneAndUpdate(
|
|
|
|
|
{ supportId: "AWHYSU64" },
|
|
|
|
|
{
|
|
|
|
|
$push: {
|
|
|
|
|
"issues.$[elem].hardwareIds": { $each: newSlaveHardwareIds },
|
|
|
|
|
"issues.$[elem].slaveNames": { $each: newSlaveNames }
|
|
|
|
|
},
|
|
|
|
|
$set: {
|
|
|
|
|
"issues.$[elem].lastTicketRaisedAt": formattedNow,
|
|
|
|
|
updatedAt: new Date()
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
$set: {
|
|
|
|
|
updatedAt: new Date(),
|
|
|
|
|
lastTicketRaisedAt: now.format("YYYY-MM-DD HH:mm:ss")
|
|
|
|
|
{
|
|
|
|
|
arrayFilters: [
|
|
|
|
|
{ "elem.hardwareId": connected_to, "elem.type": "GSM or LoRa Disconnected" }
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
existingMasterIssue
|
|
|
|
|
? { arrayFilters: [{ "elem.hardwareId": connected_to, "elem.type": "GSM or LoRa Disconnected" }] }
|
|
|
|
|
: {}
|
|
|
|
|
);
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("Error in raiseATicketLikeLogic:", error);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const cron = require("node-cron");
|
|
|
|
|
|
|
|
|
|
cron.schedule("* * * * *", async () => {
|
|
|
|
@ -4842,11 +5000,8 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
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();
|
|
|
|
@ -4855,7 +5010,6 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
issueHw &&
|
|
|
|
|
(sensorHw === issueHw || sensorConnected === issueHw)
|
|
|
|
|
) {
|
|
|
|
|
console.log(`Adding hardwareId ${issue.hardwareId} for customer ${custId}`);
|
|
|
|
|
customerHardwareMap[custId].add(issue.hardwareId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -4863,7 +5017,6 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -4878,6 +5031,24 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
const custId = user.customerId;
|
|
|
|
|
const hardwareIdSet = customerHardwareMap[custId] || new Set();
|
|
|
|
|
|
|
|
|
|
// Extract latest issue-specific lastTicketRaisedAt
|
|
|
|
|
const relatedIssues = supportRecord.issues.filter(issue => {
|
|
|
|
|
const issueHw = issue.hardwareId?.trim().toLowerCase();
|
|
|
|
|
const hardwareIds = issue.hardwareIds?.map(id => id?.trim().toLowerCase()) || [];
|
|
|
|
|
const allIds = [issueHw, ...hardwareIds];
|
|
|
|
|
return Array.from(hardwareIdSet).some(hw => allIds.includes(hw?.trim().toLowerCase()));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
let latestIssueTime = null;
|
|
|
|
|
for (const issue of relatedIssues) {
|
|
|
|
|
if (issue.lastTicketRaisedAt) {
|
|
|
|
|
const issueTime = new Date(issue.lastTicketRaisedAt);
|
|
|
|
|
if (!latestIssueTime || issueTime > latestIssueTime) {
|
|
|
|
|
latestIssueTime = issueTime;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response.push({
|
|
|
|
|
customer: {
|
|
|
|
|
customerId: custId,
|
|
|
|
@ -4912,7 +5083,7 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
stripeSubscriptionStatus: user.stripeSubscriptionStatus || false,
|
|
|
|
|
createdAt: user.createdAt,
|
|
|
|
|
updatedAt: user.updatedAt,
|
|
|
|
|
lastTicketRaisedAt: supportRecord.lastTicketRaisedAt || null,
|
|
|
|
|
lastTicketRaisedAt: latestIssueTime ? moment(latestIssueTime).format("YYYY-MM-DD HH:mm:ss") : null,
|
|
|
|
|
totalHardwareIdsCount: hardwareIdSet.size
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
@ -4933,6 +5104,7 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getDisconnectedCustomerDetailsByTeamMemberId = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
|
const { support_teamMemberId } = req.params;
|
|
|
|
|