|
|
|
@ -5320,6 +5320,164 @@ exports.getRemoveConnectedMastersWithSlaves = async (req, reply) => {
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
// try {
|
|
|
|
|
// const { supportId } = req.params;
|
|
|
|
|
|
|
|
|
|
// if (!supportId) {
|
|
|
|
|
// return reply.code(400).send({ error: "supportId is required" });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // 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. Filter only unresolved issues
|
|
|
|
|
// const unresolvedIssues = (supportRecord.issues || []).filter(issue => issue.resolved === false);
|
|
|
|
|
|
|
|
|
|
// // 3. Collect all unique hardwareIds (from hardwareId and hardwareIds arrays) from unresolved issues
|
|
|
|
|
// const allHardwareIds = new Set();
|
|
|
|
|
// for (const issue of unresolvedIssues) {
|
|
|
|
|
// 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 (allHardwareIds.size === 0) {
|
|
|
|
|
// return reply.code(404).send({ message: "No unresolved hardware IDs found in issues" });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const hardwareIdsArray = Array.from(allHardwareIds);
|
|
|
|
|
// console.log("hardwareIdsArray",hardwareIdsArray)
|
|
|
|
|
// // 4. Find disconnected insensors using connected_to match
|
|
|
|
|
// const disconnectedSensors = await Insensors.find({
|
|
|
|
|
// connected_to: { $in: hardwareIdsArray }
|
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
|
|
// if (!disconnectedSensors.length) {
|
|
|
|
|
// return reply.code(404).send({ message: "No disconnected issues found" });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // 5. Get unique customerIds from disconnected sensors
|
|
|
|
|
// const customerIds = [...new Set(disconnectedSensors.map(s => s.customerId))];
|
|
|
|
|
// const customers = await User.find({ customerId: { $in: customerIds } }).lean();
|
|
|
|
|
|
|
|
|
|
// // 6. 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();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// const sensorHw = sensor.tankhardwareId?.trim().toLowerCase();
|
|
|
|
|
// const sensorConnected = sensor.connected_to?.trim().toLowerCase();
|
|
|
|
|
|
|
|
|
|
// for (const issue of unresolvedIssues) {
|
|
|
|
|
// const allIssueHardwareIds = [
|
|
|
|
|
// ...(issue.hardwareIds?.map(id => id?.trim().toLowerCase()) || []),
|
|
|
|
|
// issue.hardwareId?.trim().toLowerCase()
|
|
|
|
|
// ];
|
|
|
|
|
|
|
|
|
|
// if (
|
|
|
|
|
// allIssueHardwareIds.includes(sensorHw) ||
|
|
|
|
|
// allIssueHardwareIds.includes(sensorConnected)
|
|
|
|
|
// ) {
|
|
|
|
|
// customerHardwareMap[custId].add(issue.hardwareId);
|
|
|
|
|
// }
|
|
|
|
|
// console.log("allIssueHardwareIds",allIssueHardwareIds)
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // 7. Build final response
|
|
|
|
|
// const response = [];
|
|
|
|
|
|
|
|
|
|
// for (const user of customers) {
|
|
|
|
|
// const custId = user.customerId;
|
|
|
|
|
// const hardwareIdSet = customerHardwareMap[custId] || new Set();
|
|
|
|
|
|
|
|
|
|
// // Extract latest unresolved issue-specific lastTicketRaisedAt
|
|
|
|
|
// const relatedIssues = unresolvedIssues.filter(issue => {
|
|
|
|
|
// const issueHw = issue.hardwareId?.trim().toLowerCase();
|
|
|
|
|
// const hardwareIds = issue.hardwareIds?.map(id => id?.trim().toLowerCase()) || [];
|
|
|
|
|
// const allIds = [issueHw, ...hardwareIds];
|
|
|
|
|
// console.log("allIds",allIds)
|
|
|
|
|
// console.log("Array.from(hardwareIdSet).some(hw => allIds.includes(hw?.trim().toLowerCase()))",Array.from(hardwareIdSet).some(hw => allIds.includes(hw?.trim().toLowerCase())))
|
|
|
|
|
// return Array.from(hardwareIdSet).some(hw => allIds.includes(hw?.trim().toLowerCase()));
|
|
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
// //console.log("relatedIssues",relatedIssues)
|
|
|
|
|
// 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,
|
|
|
|
|
// username: user.username || "",
|
|
|
|
|
// firstName: user.profile?.firstName || "",
|
|
|
|
|
// lastName: user.profile?.lastName || "",
|
|
|
|
|
// phone: user.phone || user.profile?.contactNumber || "",
|
|
|
|
|
// email: user.emails?.[0]?.email || "",
|
|
|
|
|
// phoneVerified: user.phoneVerified || false,
|
|
|
|
|
// address1: user.profile?.address1 || "",
|
|
|
|
|
// address2: user.profile?.address2 || "",
|
|
|
|
|
// city: user.profile?.city || "",
|
|
|
|
|
// state: user.profile?.state || "",
|
|
|
|
|
// country: user.profile?.country || "",
|
|
|
|
|
// zip: user.profile?.zip || "",
|
|
|
|
|
// notes: user.profile?.notes || "",
|
|
|
|
|
// latitude: user.latitude,
|
|
|
|
|
// longitude: user.longitude,
|
|
|
|
|
// fcmIds: (user.fcmIds || []).filter(fcm => typeof fcm === "string" && fcm.startsWith("d")),
|
|
|
|
|
// installationId: user.installationId || "",
|
|
|
|
|
// notificationPreferences: {
|
|
|
|
|
// allowNotifications: user.allowNotifications || false,
|
|
|
|
|
// automaticStartAndStopNotify: user.automaticStartAndStopNotify || false,
|
|
|
|
|
// manualStartAndStopNotify: user.manualStartAndStopNotify || false,
|
|
|
|
|
// criticalLowWaterAlert: user.criticalLowWaterAlert || false,
|
|
|
|
|
// lowWaterAlert: user.lowWaterAlert || false,
|
|
|
|
|
// notificationPreference: user.notificationPreference || "never"
|
|
|
|
|
// },
|
|
|
|
|
// surveyStatus: user.survey_status || "pending",
|
|
|
|
|
// buildingName: user.buildingName,
|
|
|
|
|
// stripePaymentStatus: user.stripePaymentStatus || false,
|
|
|
|
|
// stripeSubscriptionStatus: user.stripeSubscriptionStatus || false,
|
|
|
|
|
// createdAt: user.createdAt,
|
|
|
|
|
// updatedAt: user.updatedAt,
|
|
|
|
|
// lastTicketRaisedAt: latestIssueTime ? moment(latestIssueTime).format("YYYY-MM-DD HH:mm:ss") : null,
|
|
|
|
|
// totalHardwareIdsCount: hardwareIdSet.size
|
|
|
|
|
// }
|
|
|
|
|
// });
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
|
// status_code: 200,
|
|
|
|
|
// data: response
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// console.error("Error fetching disconnected customer details:", error);
|
|
|
|
|
// return reply.code(500).send({ error: "Internal server error" });
|
|
|
|
|
// }
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
|
const { supportId } = req.params;
|
|
|
|
@ -5328,143 +5486,85 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
return reply.code(400).send({ error: "supportId is required" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 1. Fetch support record
|
|
|
|
|
// 1. Get the support record by supportId
|
|
|
|
|
const supportRecord = await Support.findOne({ supportId }).lean();
|
|
|
|
|
if (!supportRecord) {
|
|
|
|
|
return reply.code(404).send({ message: "No support record found for this supportId" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. Filter only unresolved issues
|
|
|
|
|
const unresolvedIssues = (supportRecord.issues || []).filter(issue => issue.resolved === false);
|
|
|
|
|
|
|
|
|
|
// 3. Collect all unique hardwareIds (from hardwareId and hardwareIds arrays) from unresolved issues
|
|
|
|
|
const allHardwareIds = new Set();
|
|
|
|
|
for (const issue of unresolvedIssues) {
|
|
|
|
|
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());
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// 2. Extract all hardwareIds from issues
|
|
|
|
|
const hardwareIds = [];
|
|
|
|
|
for (const issue of supportRecord.issues) {
|
|
|
|
|
if (issue.hardwareId) hardwareIds.push(issue.hardwareId);
|
|
|
|
|
if (Array.isArray(issue.hardwareIds)) hardwareIds.push(...issue.hardwareIds);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (allHardwareIds.size === 0) {
|
|
|
|
|
return reply.code(404).send({ message: "No unresolved hardware IDs found in issues" });
|
|
|
|
|
if (hardwareIds.length === 0) {
|
|
|
|
|
return reply.code(404).send({ message: "No hardware IDs found in issues" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const hardwareIdsArray = Array.from(allHardwareIds);
|
|
|
|
|
console.log("hardwareIdsArray",hardwareIdsArray)
|
|
|
|
|
// 4. Find disconnected insensors using connected_to match
|
|
|
|
|
// 3. Find disconnected Insensors
|
|
|
|
|
const disconnectedSensors = await Insensors.find({
|
|
|
|
|
connected_to: { $in: hardwareIdsArray }
|
|
|
|
|
$or: [
|
|
|
|
|
// { hardwareId: { $in: hardwareIds } },
|
|
|
|
|
{ connected_to: { $in: hardwareIds } }
|
|
|
|
|
],
|
|
|
|
|
connected_status: "disconnected"
|
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
|
|
if (!disconnectedSensors.length) {
|
|
|
|
|
if (disconnectedSensors.length === 0) {
|
|
|
|
|
return reply.code(404).send({ message: "No disconnected issues found" });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 5. Get unique customerIds from disconnected sensors
|
|
|
|
|
// 4. Get all unique customerIds
|
|
|
|
|
const customerIds = [...new Set(disconnectedSensors.map(s => s.customerId))];
|
|
|
|
|
const customers = await User.find({ customerId: { $in: customerIds } }).lean();
|
|
|
|
|
|
|
|
|
|
// 6. 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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const sensorHw = sensor.tankhardwareId?.trim().toLowerCase();
|
|
|
|
|
const sensorConnected = sensor.connected_to?.trim().toLowerCase();
|
|
|
|
|
|
|
|
|
|
for (const issue of unresolvedIssues) {
|
|
|
|
|
const allIssueHardwareIds = [
|
|
|
|
|
...(issue.hardwareIds?.map(id => id?.trim().toLowerCase()) || []),
|
|
|
|
|
issue.hardwareId?.trim().toLowerCase()
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
allIssueHardwareIds.includes(sensorHw) ||
|
|
|
|
|
allIssueHardwareIds.includes(sensorConnected)
|
|
|
|
|
) {
|
|
|
|
|
customerHardwareMap[custId].add(issue.hardwareId);
|
|
|
|
|
}
|
|
|
|
|
console.log("allIssueHardwareIds",allIssueHardwareIds)
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 7. Build final response
|
|
|
|
|
const response = [];
|
|
|
|
|
|
|
|
|
|
// 5. Map unique customers
|
|
|
|
|
const uniqueCustomerMap = {};
|
|
|
|
|
for (const user of customers) {
|
|
|
|
|
const custId = user.customerId;
|
|
|
|
|
const hardwareIdSet = customerHardwareMap[custId] || new Set();
|
|
|
|
|
|
|
|
|
|
// Extract latest unresolved issue-specific lastTicketRaisedAt
|
|
|
|
|
const relatedIssues = unresolvedIssues.filter(issue => {
|
|
|
|
|
const issueHw = issue.hardwareId?.trim().toLowerCase();
|
|
|
|
|
const hardwareIds = issue.hardwareIds?.map(id => id?.trim().toLowerCase()) || [];
|
|
|
|
|
const allIds = [issueHw, ...hardwareIds];
|
|
|
|
|
console.log("allIds",allIds)
|
|
|
|
|
console.log("Array.from(hardwareIdSet).some(hw => allIds.includes(hw?.trim().toLowerCase()))",Array.from(hardwareIdSet).some(hw => allIds.includes(hw?.trim().toLowerCase())))
|
|
|
|
|
return Array.from(hardwareIdSet).some(hw => allIds.includes(hw?.trim().toLowerCase()));
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
//console.log("relatedIssues",relatedIssues)
|
|
|
|
|
let latestIssueTime = null;
|
|
|
|
|
for (const issue of relatedIssues) {
|
|
|
|
|
if (issue.lastTicketRaisedAt) {
|
|
|
|
|
const issueTime = new Date(issue.lastTicketRaisedAt);
|
|
|
|
|
if (!latestIssueTime || issueTime > latestIssueTime) {
|
|
|
|
|
latestIssueTime = issueTime;
|
|
|
|
|
if (!uniqueCustomerMap[user.customerId]) {
|
|
|
|
|
uniqueCustomerMap[user.customerId] = {
|
|
|
|
|
customer: {
|
|
|
|
|
customerId: user.customerId,
|
|
|
|
|
username: user.username || "",
|
|
|
|
|
firstName: user.profile?.firstName || "",
|
|
|
|
|
lastName: user.profile?.lastName || "",
|
|
|
|
|
phone: user.phone || user.profile?.contactNumber || "",
|
|
|
|
|
email: user.emails?.[0]?.email || "",
|
|
|
|
|
phoneVerified: user.phoneVerified || false,
|
|
|
|
|
address1: user.profile?.address1 || "",
|
|
|
|
|
address2: user.profile?.address2 || "",
|
|
|
|
|
city: user.profile?.city || "",
|
|
|
|
|
state: user.profile?.state || "",
|
|
|
|
|
country: user.profile?.country || "",
|
|
|
|
|
zip: user.profile?.zip || "",
|
|
|
|
|
notes: user.profile?.notes || "",
|
|
|
|
|
latitude: user.latitude,
|
|
|
|
|
longitude: user.longitude,
|
|
|
|
|
fcmIds: (user.fcmIds || []).filter(fcm => typeof fcm === "string" && fcm.startsWith("d")),
|
|
|
|
|
installationId: user.installationId || "",
|
|
|
|
|
notificationPreferences: {
|
|
|
|
|
allowNotifications: user.allowNotifications || false,
|
|
|
|
|
automaticStartAndStopNotify: user.automaticStartAndStopNotify || false,
|
|
|
|
|
manualStartAndStopNotify: user.manualStartAndStopNotify || false,
|
|
|
|
|
criticalLowWaterAlert: user.criticalLowWaterAlert || false,
|
|
|
|
|
lowWaterAlert: user.lowWaterAlert || false,
|
|
|
|
|
notificationPreference: user.notificationPreference || "never"
|
|
|
|
|
},
|
|
|
|
|
surveyStatus: user.survey_status || "pending",
|
|
|
|
|
buildingName: user.buildingName,
|
|
|
|
|
stripePaymentStatus: user.stripePaymentStatus || false,
|
|
|
|
|
stripeSubscriptionStatus: user.stripeSubscriptionStatus || false,
|
|
|
|
|
createdAt: user.createdAt,
|
|
|
|
|
updatedAt: user.updatedAt
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response.push({
|
|
|
|
|
customer: {
|
|
|
|
|
customerId: custId,
|
|
|
|
|
username: user.username || "",
|
|
|
|
|
firstName: user.profile?.firstName || "",
|
|
|
|
|
lastName: user.profile?.lastName || "",
|
|
|
|
|
phone: user.phone || user.profile?.contactNumber || "",
|
|
|
|
|
email: user.emails?.[0]?.email || "",
|
|
|
|
|
phoneVerified: user.phoneVerified || false,
|
|
|
|
|
address1: user.profile?.address1 || "",
|
|
|
|
|
address2: user.profile?.address2 || "",
|
|
|
|
|
city: user.profile?.city || "",
|
|
|
|
|
state: user.profile?.state || "",
|
|
|
|
|
country: user.profile?.country || "",
|
|
|
|
|
zip: user.profile?.zip || "",
|
|
|
|
|
notes: user.profile?.notes || "",
|
|
|
|
|
latitude: user.latitude,
|
|
|
|
|
longitude: user.longitude,
|
|
|
|
|
fcmIds: (user.fcmIds || []).filter(fcm => typeof fcm === "string" && fcm.startsWith("d")),
|
|
|
|
|
installationId: user.installationId || "",
|
|
|
|
|
notificationPreferences: {
|
|
|
|
|
allowNotifications: user.allowNotifications || false,
|
|
|
|
|
automaticStartAndStopNotify: user.automaticStartAndStopNotify || false,
|
|
|
|
|
manualStartAndStopNotify: user.manualStartAndStopNotify || false,
|
|
|
|
|
criticalLowWaterAlert: user.criticalLowWaterAlert || false,
|
|
|
|
|
lowWaterAlert: user.lowWaterAlert || false,
|
|
|
|
|
notificationPreference: user.notificationPreference || "never"
|
|
|
|
|
},
|
|
|
|
|
surveyStatus: user.survey_status || "pending",
|
|
|
|
|
buildingName: user.buildingName,
|
|
|
|
|
stripePaymentStatus: user.stripePaymentStatus || false,
|
|
|
|
|
stripeSubscriptionStatus: user.stripeSubscriptionStatus || false,
|
|
|
|
|
createdAt: user.createdAt,
|
|
|
|
|
updatedAt: user.updatedAt,
|
|
|
|
|
lastTicketRaisedAt: latestIssueTime ? moment(latestIssueTime).format("YYYY-MM-DD HH:mm:ss") : null,
|
|
|
|
|
totalHardwareIdsCount: hardwareIdSet.size
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const response = Object.values(uniqueCustomerMap);
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
status_code: 200,
|
|
|
|
|
data: response
|
|
|
|
@ -5481,8 +5581,6 @@ exports.getDisconnectedCustomerDetails = async (req, reply) => {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getDisconnectedCustomerDetailsByTeamMemberId = async (req, reply) => {
|
|
|
|
|
try {
|
|
|
|
|
const { support_teamMemberId } = req.params;
|
|
|
|
|