|
|
|
@ -600,7 +600,6 @@ exports.assignTeamMemberToQuotation = async (request, reply) => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const latestRecord = iotData[0];
|
|
|
|
|
|
|
|
|
|
const indiaTime = moment.tz(latestRecord.date, "Asia/Kolkata");
|
|
|
|
|
const connected_gsm_date = indiaTime.format("DD-MM-YYYY");
|
|
|
|
|
const connected_gsm_time = indiaTime.format("HH:mm:ss");
|
|
|
|
@ -609,10 +608,8 @@ exports.assignTeamMemberToQuotation = async (request, reply) => {
|
|
|
|
|
const diffInMinutes = now.diff(indiaTime, "minutes");
|
|
|
|
|
const isGSMConnected = diffInMinutes <= 1;
|
|
|
|
|
const gsmStatus = isGSMConnected ? "connected" : "disconnected";
|
|
|
|
|
|
|
|
|
|
const gsmLastCheckTime = now.format("DD-MM-YYYY HH:mm:ss");
|
|
|
|
|
|
|
|
|
|
// Update Insensors by hardwareId (corrected filter)
|
|
|
|
|
await Insensors.findOneAndUpdate(
|
|
|
|
|
{ hardwareId },
|
|
|
|
|
{
|
|
|
|
@ -625,7 +622,6 @@ exports.assignTeamMemberToQuotation = async (request, reply) => {
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Annotate tanks with LoRa connection status based on tank date
|
|
|
|
|
const tanksWithConnectionStatus = latestRecord.tanks.map(tank => {
|
|
|
|
|
const tankMoment = moment.tz(tank.date, "Asia/Kolkata");
|
|
|
|
|
const tankDiff = now.diff(tankMoment, "minutes");
|
|
|
|
@ -636,6 +632,12 @@ exports.assignTeamMemberToQuotation = async (request, reply) => {
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 🔁 Raise ticket if applicable
|
|
|
|
|
const sensor = await Insensors.findOne({ hardwareId }).lean();
|
|
|
|
|
if (sensor?.customerId) {
|
|
|
|
|
await raiseATicketLikeLogic(sensor.customerId, hardwareId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
status_code: 200,
|
|
|
|
|
message: "Success",
|
|
|
|
@ -658,6 +660,7 @@ exports.assignTeamMemberToQuotation = async (request, reply) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getByHardwareIdSupport = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
|
const { hardwareId } = req.params;
|
|
|
|
@ -678,7 +681,6 @@ exports.getByHardwareIdSupport = async (req, reply) => {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const latestRecord = iotData[0];
|
|
|
|
|
|
|
|
|
|
const indiaTime = moment.tz(latestRecord.date, "Asia/Kolkata");
|
|
|
|
|
const connected_gsm_date = indiaTime.format("DD-MM-YYYY");
|
|
|
|
|
const connected_gsm_time = indiaTime.format("HH:mm:ss");
|
|
|
|
@ -687,10 +689,8 @@ exports.getByHardwareIdSupport = async (req, reply) => {
|
|
|
|
|
const diffInMinutes = now.diff(indiaTime, "minutes");
|
|
|
|
|
const isGSMConnected = diffInMinutes <= 1;
|
|
|
|
|
const gsmStatus = isGSMConnected ? "connected" : "disconnected";
|
|
|
|
|
const gsmLastCheckTime = now.format("DD-MM-YYYY HH:mm:ss");
|
|
|
|
|
|
|
|
|
|
const gsmLastCheckTime = now.format("DD-MM-YYYY HH:mm:ss"); // formatted current time
|
|
|
|
|
|
|
|
|
|
// ✅ Update slaves connected to this master hardwareId
|
|
|
|
|
await Insensors.updateMany(
|
|
|
|
|
{ connected_to: hardwareId },
|
|
|
|
|
{
|
|
|
|
@ -703,7 +703,6 @@ exports.getByHardwareIdSupport = async (req, reply) => {
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// ✅ Update the master device itself (if it's a master)
|
|
|
|
|
await Insensors.updateOne(
|
|
|
|
|
{ hardwareId },
|
|
|
|
|
{
|
|
|
|
@ -716,7 +715,6 @@ exports.getByHardwareIdSupport = async (req, reply) => {
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// ✅ Annotate tanks with LoRa connection status
|
|
|
|
|
const tanksWithConnectionStatus = latestRecord.tanks.map(tank => {
|
|
|
|
|
const tankMoment = moment.tz(tank.date, "Asia/Kolkata");
|
|
|
|
|
const tankDiff = now.diff(tankMoment, "minutes");
|
|
|
|
@ -727,7 +725,12 @@ exports.getByHardwareIdSupport = async (req, reply) => {
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// ✅ Response
|
|
|
|
|
// 🔁 Raise ticket if applicable
|
|
|
|
|
const sensor = await Insensors.findOne({ hardwareId }).lean();
|
|
|
|
|
if (sensor?.customerId) {
|
|
|
|
|
await raiseATicketLikeLogic(sensor.customerId, hardwareId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
status_code: 200,
|
|
|
|
|
message: "Success",
|
|
|
|
@ -750,6 +753,7 @@ exports.getByHardwareIdSupport = async (req, reply) => {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getByHardwareIdSupportTeamMember = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
|
const { hardwareId } = req.params;
|
|
|
|
@ -3503,13 +3507,186 @@ 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 <= 2) 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 <= 2) 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 || [];
|
|
|
|
|
|
|
|
|
|
// // Find existing unresolved issue
|
|
|
|
|
// const existingMasterIssue = existingIssues.find(
|
|
|
|
|
// issue =>
|
|
|
|
|
// issue.hardwareId === connected_to &&
|
|
|
|
|
// issue.type === "GSM or LoRa Disconnected" &&
|
|
|
|
|
// issue.resolved !== true // <-- only unresolved
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const formattedNow = now.format("YYYY-MM-DD HH:mm:ss");
|
|
|
|
|
|
|
|
|
|
// if (
|
|
|
|
|
// masterConnectedStatus === "disconnected" &&
|
|
|
|
|
// diffInMinutes >= 2 &&
|
|
|
|
|
// (newSlaveHardwareIds.length > 0 || !existingMasterIssue)
|
|
|
|
|
// ) {
|
|
|
|
|
// if (!existingMasterIssue) {
|
|
|
|
|
// // Create new issue with resolved: false
|
|
|
|
|
// 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 // <--- add resolved flag here
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// await Support.findOneAndUpdate(
|
|
|
|
|
// { supportId: "AWHYSU64" },
|
|
|
|
|
// {
|
|
|
|
|
// $push: { issues: newIssue },
|
|
|
|
|
// $set: { updatedAt: new Date() }
|
|
|
|
|
// }
|
|
|
|
|
// );
|
|
|
|
|
// } else {
|
|
|
|
|
// // Update existing unresolved issue only
|
|
|
|
|
// await Support.findOneAndUpdate(
|
|
|
|
|
// { supportId: "AWHYSU64" },
|
|
|
|
|
// {
|
|
|
|
|
// $push: {
|
|
|
|
|
// "issues.$[elem].hardwareIds": { $each: newSlaveHardwareIds },
|
|
|
|
|
// "issues.$[elem].slaveNames": { $each: newSlaveNames }
|
|
|
|
|
// },
|
|
|
|
|
// $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);
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
const cron = require("node-cron");
|
|
|
|
|
|
|
|
|
|
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(
|
|
|
|
@ -3559,17 +3736,14 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
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");
|
|
|
|
|
const slaveDiff = now.diff(slaveTime, "minutes");
|
|
|
|
|
if (slaveDiff <= 2) slaveStatus = "connected";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3585,19 +3759,14 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
if (!supportRecord) return;
|
|
|
|
|
|
|
|
|
|
const existingIssues = supportRecord.issues || [];
|
|
|
|
|
|
|
|
|
|
// Find existing unresolved issue
|
|
|
|
|
const existingMasterIssue = existingIssues.find(
|
|
|
|
|
issue =>
|
|
|
|
|
issue.hardwareId === connected_to &&
|
|
|
|
|
issue.type === "GSM or LoRa Disconnected" &&
|
|
|
|
|
issue.resolved !== true // <-- only unresolved
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const alreadyReportedSlaves = new Set(
|
|
|
|
|
existingMasterIssue?.hardwareIds || []
|
|
|
|
|
issue.resolved !== true
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const alreadyReportedSlaves = new Set(existingMasterIssue?.hardwareIds || []);
|
|
|
|
|
const newSlaveHardwareIds = [];
|
|
|
|
|
const newSlaveNames = [];
|
|
|
|
|
|
|
|
|
@ -3610,13 +3779,13 @@ 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) {
|
|
|
|
|
// Create new issue with resolved: false
|
|
|
|
|
const newIssue = {
|
|
|
|
|
type: "GSM or LoRa Disconnected",
|
|
|
|
|
masterHardwareId: connected_to,
|
|
|
|
@ -3626,18 +3795,13 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
message: `Master ${connected_to} is disconnected along with ${newSlaveHardwareIds.length} new slave(s)`,
|
|
|
|
|
disconnectedAt: lastDataTime,
|
|
|
|
|
lastTicketRaisedAt: formattedNow,
|
|
|
|
|
resolved: false // <--- add resolved flag here
|
|
|
|
|
resolved: false
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
await Support.findOneAndUpdate(
|
|
|
|
|
{ supportId: "AWHYSU64" },
|
|
|
|
|
{
|
|
|
|
|
$push: { issues: newIssue },
|
|
|
|
|
$set: { updatedAt: new Date() }
|
|
|
|
|
}
|
|
|
|
|
{ $push: { issues: newIssue }, $set: { updatedAt: new Date() } }
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
// Update existing unresolved issue only
|
|
|
|
|
await Support.findOneAndUpdate(
|
|
|
|
|
{ supportId: "AWHYSU64" },
|
|
|
|
|
{
|
|
|
|
@ -3652,7 +3816,11 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
arrayFilters: [
|
|
|
|
|
{ "elem.hardwareId": connected_to, "elem.type": "GSM or LoRa Disconnected", "elem.resolved": false }
|
|
|
|
|
{
|
|
|
|
|
"elem.hardwareId": connected_to,
|
|
|
|
|
"elem.type": "GSM or LoRa Disconnected",
|
|
|
|
|
"elem.resolved": false
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
@ -3664,17 +3832,15 @@ const raiseATicketLikeLogic = async (customerId, connected_to) => {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 {
|
|
|
|
|
const { customerId, connected_to, installationId } = req.params;
|
|
|
|
|