|
|
|
@ -5685,6 +5685,186 @@ exports.raiseATicketSlave = async (req, reply) => {
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// exports.getDisconnectedIssuesBySupportId = async (req, reply) => {
|
|
|
|
|
// try {
|
|
|
|
|
// const { supportId, customerId } = req.params;
|
|
|
|
|
|
|
|
|
|
// if (!supportId || !customerId) {
|
|
|
|
|
// return reply.code(400).send({ error: "supportId and customerId are required" });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const supportRecord = await Support.findOne({ supportId }).lean();
|
|
|
|
|
// if (!supportRecord) {
|
|
|
|
|
// return reply.code(404).send({ message: "No support record found for this supportId and customerId" });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const allIssues = supportRecord.issues || [];
|
|
|
|
|
// const hardwareSet = new Set();
|
|
|
|
|
|
|
|
|
|
// for (const issue of allIssues) {
|
|
|
|
|
// if (issue.hardwareId) hardwareSet.add(issue.hardwareId);
|
|
|
|
|
// if (issue.masterHardwareId) hardwareSet.add(issue.masterHardwareId);
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const hardwareIds = [...hardwareSet];
|
|
|
|
|
|
|
|
|
|
// const sensors = await Insensors.find({
|
|
|
|
|
// customerId,
|
|
|
|
|
// $or: [
|
|
|
|
|
// { hardwareId: { $in: hardwareIds } },
|
|
|
|
|
// { tankhardwareId: { $in: hardwareIds } }
|
|
|
|
|
// ]
|
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
|
|
// const sensorMap = {};
|
|
|
|
|
// for (const sensor of sensors) {
|
|
|
|
|
// if (sensor.hardwareId) sensorMap[sensor.hardwareId] = sensor;
|
|
|
|
|
// if (sensor.tankhardwareId) sensorMap[sensor.tankhardwareId] = sensor;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const orders = await Order.find({ customerId }).lean();
|
|
|
|
|
|
|
|
|
|
// const orderMap = {};
|
|
|
|
|
// for (const order of orders) {
|
|
|
|
|
// (order.master_connections || []).forEach(conn => {
|
|
|
|
|
// if (conn.hardwareId) {
|
|
|
|
|
// orderMap[conn.hardwareId] = {
|
|
|
|
|
// masterName: conn.master_name || null,
|
|
|
|
|
// location: conn.location || null
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const slaveOrderMap = {};
|
|
|
|
|
// for (const order of orders) {
|
|
|
|
|
// (order.tank_connections || []).forEach(conn => {
|
|
|
|
|
// if (conn.hardwareId) {
|
|
|
|
|
// slaveOrderMap[conn.hardwareId] = {
|
|
|
|
|
// location: conn.location || null,
|
|
|
|
|
// typeOfWater: conn.typeOfWater || null
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const masterMap = {};
|
|
|
|
|
// const now = moment.tz("Asia/Kolkata");
|
|
|
|
|
|
|
|
|
|
// for (const issue of allIssues) {
|
|
|
|
|
// const masterId = issue.masterHardwareId || issue.hardwareId;
|
|
|
|
|
// const masterSensor = sensorMap[masterId];
|
|
|
|
|
// if (!masterSensor || masterSensor.type !== "master") continue;
|
|
|
|
|
|
|
|
|
|
// const latestMasterData = await IotData.findOne({ hardwareId: masterSensor.hardwareId }).sort({ date: -1 }).lean();
|
|
|
|
|
|
|
|
|
|
// let gsmConnected = false;
|
|
|
|
|
// if (latestMasterData?.date) {
|
|
|
|
|
// const gsmTime = moment.tz(latestMasterData.date, "Asia/Kolkata");
|
|
|
|
|
// gsmConnected = now.diff(gsmTime, "minutes") <= 1;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// if (!masterMap[masterSensor.hardwareId]) {
|
|
|
|
|
// const enriched = orderMap[masterSensor.hardwareId] || {};
|
|
|
|
|
// masterMap[masterSensor.hardwareId] = {
|
|
|
|
|
// hardwareId: masterSensor.hardwareId,
|
|
|
|
|
// masterName: enriched.masterName || masterSensor.masterName || "",
|
|
|
|
|
// location: enriched.location || masterSensor.location || "",
|
|
|
|
|
// type: "master",
|
|
|
|
|
// connected_status: gsmConnected ? "connected" : "disconnected",
|
|
|
|
|
// gsm_last_check_time: masterSensor.gsm_last_check_time,
|
|
|
|
|
// gsm_last_disconnect_time: masterSensor.gsm_last_disconnect_time,
|
|
|
|
|
// connected_gsm_date: masterSensor.connected_gsm_date,
|
|
|
|
|
// connected_gsm_time: masterSensor.connected_gsm_time,
|
|
|
|
|
// connected_lora_date: masterSensor.connected_lora_date,
|
|
|
|
|
// connected_lora_time: masterSensor.connected_lora_time,
|
|
|
|
|
// support_gsm_last_check_time: masterSensor.support_gsm_last_check_time,
|
|
|
|
|
// support_lora_last_check_time: masterSensor.support_lora_last_check_time,
|
|
|
|
|
// team_member_support_gsm_last_check_time: masterSensor.team_member_support_gsm_last_check_time,
|
|
|
|
|
// team_member_support_lora_last_check_time: masterSensor.team_member_support_lora_last_check_time,
|
|
|
|
|
// connected_slave_count: 0,
|
|
|
|
|
// connected_slaves: []
|
|
|
|
|
// };
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const master = masterMap[masterSensor.hardwareId];
|
|
|
|
|
// const connectedSlaves = await Insensors.find({
|
|
|
|
|
// connected_to: masterSensor.hardwareId,
|
|
|
|
|
// type: "slave",
|
|
|
|
|
// customerId
|
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
|
|
// const slaveSet = new Set(master.connected_slaves.map(s => s.hardwareId));
|
|
|
|
|
|
|
|
|
|
// for (const slave of connectedSlaves) {
|
|
|
|
|
// const slaveHardwareId = slave.tankhardwareId || slave.hardwareId;
|
|
|
|
|
// if (slaveSet.has(slaveHardwareId)) continue;
|
|
|
|
|
// slaveSet.add(slaveHardwareId);
|
|
|
|
|
|
|
|
|
|
// const tankInfo = await Tank.findOne({
|
|
|
|
|
// $or: [
|
|
|
|
|
// { hardwareId: slaveHardwareId },
|
|
|
|
|
// { tankhardwareId: slaveHardwareId }
|
|
|
|
|
// ]
|
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
|
|
// const slaveOrderInfo = slaveOrderMap[slaveHardwareId] || {};
|
|
|
|
|
|
|
|
|
|
// const matchedTank = latestMasterData?.tanks?.find(t => t.tankhardwareId === slaveHardwareId);
|
|
|
|
|
// let loraConnected = false;
|
|
|
|
|
// if (matchedTank?.date && matchedTank.tankHeight !== "0") {
|
|
|
|
|
// const loraTime = moment.tz(matchedTank.date, "Asia/Kolkata");
|
|
|
|
|
// loraConnected = now.diff(loraTime, "minutes") <= 1;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const slaveEnriched = {
|
|
|
|
|
// hardwareId: slaveHardwareId,
|
|
|
|
|
// tankName: slave.tankName || tankInfo?.tankName || "",
|
|
|
|
|
// location: slave.location || tankInfo?.tankLocation || slaveOrderInfo.location || "",
|
|
|
|
|
// connected_status: loraConnected ? "connected" : "disconnected",
|
|
|
|
|
// connected_lora_time: slave.connected_lora_time,
|
|
|
|
|
// connected_lora_date: slave.connected_lora_date,
|
|
|
|
|
// lora_last_check_time: slave.lora_last_check_time,
|
|
|
|
|
// lora_last_disconnect_time: slave.lora_last_disconnect_time,
|
|
|
|
|
// connected_to: slave.connected_to,
|
|
|
|
|
// masterName: master.masterName,
|
|
|
|
|
// type: "slave",
|
|
|
|
|
// typeOfWater: slave.typeOfWater || tankInfo?.typeOfWater || slaveOrderInfo.typeOfWater || "",
|
|
|
|
|
// tankHeight: slave.tankHeight,
|
|
|
|
|
// support_lora_last_check_time: slave.support_lora_last_check_time,
|
|
|
|
|
// team_member_support_lora_last_check_time: slave.team_member_support_lora_last_check_time
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
// master.connected_slaves.push(slaveEnriched);
|
|
|
|
|
// master.connected_slave_count++;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // 🔍 Filter comments by customerId
|
|
|
|
|
// const comments = (supportRecord.comments || [])
|
|
|
|
|
// .filter(c => c.customerId === customerId)
|
|
|
|
|
// .map(c => ({
|
|
|
|
|
// text: c.text,
|
|
|
|
|
// commentsTime: moment(c.createdAt).tz("Asia/Kolkata").format("DD-MM-YYYY HH:mm")
|
|
|
|
|
// }));
|
|
|
|
|
|
|
|
|
|
// for (const master of Object.values(masterMap)) {
|
|
|
|
|
// master.comments = comments;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
|
// status_code: 200,
|
|
|
|
|
// supportId,
|
|
|
|
|
// customerId,
|
|
|
|
|
// totalMasters: Object.keys(masterMap).length,
|
|
|
|
|
// disconnectedIssues: Object.values(masterMap)
|
|
|
|
|
// });
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// console.error("Error fetching disconnected issues:", error);
|
|
|
|
|
// return reply.code(500).send({ error: "Internal server error" });
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
exports.getDisconnectedIssuesBySupportId = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
|
const { supportId, customerId } = req.params;
|
|
|
|
@ -5764,6 +5944,19 @@ exports.getDisconnectedIssuesBySupportId = async (req, reply) => {
|
|
|
|
|
gsmConnected = now.diff(gsmTime, "minutes") <= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get latest lastTicketRaisedAt for this master
|
|
|
|
|
const relatedIssues = allIssues.filter(
|
|
|
|
|
i =>
|
|
|
|
|
i.hardwareId === masterSensor.hardwareId ||
|
|
|
|
|
i.masterHardwareId === masterSensor.hardwareId
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const lastTicketRaisedAt = relatedIssues.reduce((latest, issue) => {
|
|
|
|
|
if (!issue.lastTicketRaisedAt) return latest;
|
|
|
|
|
const current = new Date(issue.lastTicketRaisedAt);
|
|
|
|
|
return !latest || current > new Date(latest) ? issue.lastTicketRaisedAt : latest;
|
|
|
|
|
}, null);
|
|
|
|
|
|
|
|
|
|
if (!masterMap[masterSensor.hardwareId]) {
|
|
|
|
|
const enriched = orderMap[masterSensor.hardwareId] || {};
|
|
|
|
|
masterMap[masterSensor.hardwareId] = {
|
|
|
|
@ -5783,7 +5976,8 @@ exports.getDisconnectedIssuesBySupportId = async (req, reply) => {
|
|
|
|
|
team_member_support_gsm_last_check_time: masterSensor.team_member_support_gsm_last_check_time,
|
|
|
|
|
team_member_support_lora_last_check_time: masterSensor.team_member_support_lora_last_check_time,
|
|
|
|
|
connected_slave_count: 0,
|
|
|
|
|
connected_slaves: []
|
|
|
|
|
connected_slaves: [],
|
|
|
|
|
lastTicketRaisedAt: lastTicketRaisedAt
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -5817,6 +6011,17 @@ exports.getDisconnectedIssuesBySupportId = async (req, reply) => {
|
|
|
|
|
loraConnected = now.diff(loraTime, "minutes") <= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get latest lastTicketRaisedAt for this slave
|
|
|
|
|
const slaveRelatedIssues = allIssues.filter(
|
|
|
|
|
i => i.hardwareId === slaveHardwareId
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const slaveLastTicketRaisedAt = slaveRelatedIssues.reduce((latest, issue) => {
|
|
|
|
|
if (!issue.lastTicketRaisedAt) return latest;
|
|
|
|
|
const current = new Date(issue.lastTicketRaisedAt);
|
|
|
|
|
return !latest || current > new Date(latest) ? issue.lastTicketRaisedAt : latest;
|
|
|
|
|
}, null);
|
|
|
|
|
|
|
|
|
|
const slaveEnriched = {
|
|
|
|
|
hardwareId: slaveHardwareId,
|
|
|
|
|
tankName: slave.tankName || tankInfo?.tankName || "",
|
|
|
|
@ -5832,7 +6037,8 @@ exports.getDisconnectedIssuesBySupportId = async (req, reply) => {
|
|
|
|
|
typeOfWater: slave.typeOfWater || tankInfo?.typeOfWater || slaveOrderInfo.typeOfWater || "",
|
|
|
|
|
tankHeight: slave.tankHeight,
|
|
|
|
|
support_lora_last_check_time: slave.support_lora_last_check_time,
|
|
|
|
|
team_member_support_lora_last_check_time: slave.team_member_support_lora_last_check_time
|
|
|
|
|
team_member_support_lora_last_check_time: slave.team_member_support_lora_last_check_time,
|
|
|
|
|
lastTicketRaisedAt: slaveLastTicketRaisedAt
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
master.connected_slaves.push(slaveEnriched);
|
|
|
|
@ -5840,7 +6046,7 @@ exports.getDisconnectedIssuesBySupportId = async (req, reply) => {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 🔍 Filter comments by customerId
|
|
|
|
|
// Filter comments by customerId
|
|
|
|
|
const comments = (supportRecord.comments || [])
|
|
|
|
|
.filter(c => c.customerId === customerId)
|
|
|
|
|
.map(c => ({
|
|
|
|
@ -6562,8 +6768,50 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
customerId: { $in: Object.keys(customerHardwareMap) }
|
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
|
|
// const customerResults = customerDetails.map((customer) => {
|
|
|
|
|
// const affectedHardwareSet = customerHardwareMap[customer.customerId] || new Set();
|
|
|
|
|
// return {
|
|
|
|
|
// customerId: customer.customerId,
|
|
|
|
|
// buildingName: customer.buildingName || "",
|
|
|
|
|
// location: customer.location || "",
|
|
|
|
|
// username: customer.username || "",
|
|
|
|
|
// firstName: customer.profile?.firstName || "",
|
|
|
|
|
// lastName: customer.profile?.lastName || "",
|
|
|
|
|
// phone: customer.phone || user.profile?.contactNumber || "",
|
|
|
|
|
// email: customer.emails?.[0]?.email || "",
|
|
|
|
|
// phoneVerified: customer.phoneVerified || false,
|
|
|
|
|
// address1: customer.profile?.address1 || "",
|
|
|
|
|
// address2: customer.profile?.address2 || "",
|
|
|
|
|
// city: customer.profile?.city || "",
|
|
|
|
|
// latitude: customer.latitude,
|
|
|
|
|
// longitude: customer.longitude,
|
|
|
|
|
// totalHardwareIdsCount: affectedHardwareSet.size,
|
|
|
|
|
// hardwareIds: [...affectedHardwareSet]
|
|
|
|
|
// };
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
const customerResults = customerDetails.map((customer) => {
|
|
|
|
|
const affectedHardwareSet = customerHardwareMap[customer.customerId] || new Set();
|
|
|
|
|
const affectedLowerSet = new Set([...affectedHardwareSet].map(id => id.toLowerCase().trim()));
|
|
|
|
|
|
|
|
|
|
// Get all unresolved issues related to this customer's affected hardwareIds
|
|
|
|
|
const customerIssues = unresolvedIssues.filter(issue => {
|
|
|
|
|
const allIssueHardwareIds = [
|
|
|
|
|
...(issue.hardwareIds?.map(id => id?.trim().toLowerCase()) || []),
|
|
|
|
|
issue.hardwareId?.trim().toLowerCase()
|
|
|
|
|
].filter(Boolean);
|
|
|
|
|
return allIssueHardwareIds.some(hw => affectedLowerSet.has(hw));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Get the latest lastTicketRaisedAt from the issues
|
|
|
|
|
const lastTicketRaisedAt = customerIssues.reduce((latest, issue) => {
|
|
|
|
|
const issueTime = new Date(issue.lastTicketRaisedAt);
|
|
|
|
|
if (!isNaN(issueTime)) {
|
|
|
|
|
return (!latest || issueTime > new Date(latest)) ? issue.lastTicketRaisedAt : latest;
|
|
|
|
|
}
|
|
|
|
|
return latest;
|
|
|
|
|
}, null);
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
customerId: customer.customerId,
|
|
|
|
|
buildingName: customer.buildingName || "",
|
|
|
|
@ -6571,7 +6819,7 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
username: customer.username || "",
|
|
|
|
|
firstName: customer.profile?.firstName || "",
|
|
|
|
|
lastName: customer.profile?.lastName || "",
|
|
|
|
|
phone: customer.phone || user.profile?.contactNumber || "",
|
|
|
|
|
phone: customer.phone || customer.profile?.contactNumber || "",
|
|
|
|
|
email: customer.emails?.[0]?.email || "",
|
|
|
|
|
phoneVerified: customer.phoneVerified || false,
|
|
|
|
|
address1: customer.profile?.address1 || "",
|
|
|
|
@ -6580,10 +6828,12 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
latitude: customer.latitude,
|
|
|
|
|
longitude: customer.longitude,
|
|
|
|
|
totalHardwareIdsCount: affectedHardwareSet.size,
|
|
|
|
|
hardwareIds: [...affectedHardwareSet]
|
|
|
|
|
hardwareIds: [...affectedHardwareSet],
|
|
|
|
|
lastTicketRaisedAt: lastTicketRaisedAt || null
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reply.code(200).send({
|
|
|
|
|
success: true,
|
|
|
|
|
totalCustomers: customerResults.length,
|
|
|
|
|