|
|
@ -6410,6 +6410,106 @@ exports.getDisconnectedMoveCustomerDetails = async (req, reply) => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getResolvedCustomerDetails = async (req, reply) => {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const { supportId } = req.params;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!supportId) {
|
|
|
|
|
|
|
|
return reply.code(400).send({ error: "supportId is required" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const supportRecord = await Support.findOne({ supportId }).lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!supportRecord) {
|
|
|
|
|
|
|
|
return reply.code(404).send({ message: "No support record found for this supportId" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
console.log("✅ Support Record:", JSON.stringify(supportRecord, null, 2));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const resolvedIssues = supportRecord.resolvedIssues || [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!Array.isArray(resolvedIssues) || resolvedIssues.length === 0) {
|
|
|
|
|
|
|
|
return reply.code(404).send({ message: "No resolved issues to process" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const resolvedHardwareIds = [];
|
|
|
|
|
|
|
|
for (const issue of resolvedIssues) {
|
|
|
|
|
|
|
|
if (issue.hardwareId) resolvedHardwareIds.push(issue.hardwareId);
|
|
|
|
|
|
|
|
if (Array.isArray(issue.hardwareIds)) resolvedHardwareIds.push(...issue.hardwareIds);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (resolvedHardwareIds.length === 0) {
|
|
|
|
|
|
|
|
return reply.code(404).send({ message: "No hardware IDs in resolved issues" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const sensors = await Insensors.find({
|
|
|
|
|
|
|
|
$or: [
|
|
|
|
|
|
|
|
{ hardwareId: { $in: resolvedHardwareIds } },
|
|
|
|
|
|
|
|
{ connected_to: { $in: resolvedHardwareIds } }
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (sensors.length === 0) {
|
|
|
|
|
|
|
|
return reply.code(404).send({ message: "No sensors found for resolved hardware" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const customerIds = [...new Set(sensors.map(s => s.customerId))];
|
|
|
|
|
|
|
|
const customers = await User.find({ customerId: { $in: customerIds } }).lean();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const uniqueCustomerMap = {};
|
|
|
|
|
|
|
|
for (const user of customers) {
|
|
|
|
|
|
|
|
const cid = user.customerId;
|
|
|
|
|
|
|
|
if (!uniqueCustomerMap[cid]) {
|
|
|
|
|
|
|
|
uniqueCustomerMap[cid] = {
|
|
|
|
|
|
|
|
customer: {
|
|
|
|
|
|
|
|
customerId: cid,
|
|
|
|
|
|
|
|
username: user.username || "",
|
|
|
|
|
|
|
|
firstName: user.profile?.firstName || user.firstName || "",
|
|
|
|
|
|
|
|
lastName: user.profile?.lastName || user.lastName || "",
|
|
|
|
|
|
|
|
phone: user.phone || user.profile?.contactNumber || user.alternativeNumber || "",
|
|
|
|
|
|
|
|
email: user.emails?.[0]?.email || user.email || "",
|
|
|
|
|
|
|
|
phoneVerified: user.phoneVerified || false,
|
|
|
|
|
|
|
|
address1: user.profile?.address1 || user.address1 || "",
|
|
|
|
|
|
|
|
address2: user.profile?.address2 || user.address2 || "",
|
|
|
|
|
|
|
|
city: user.profile?.city || user.city || "",
|
|
|
|
|
|
|
|
state: user.profile?.state || user.state || "",
|
|
|
|
|
|
|
|
country: user.profile?.country || user.country || "",
|
|
|
|
|
|
|
|
zip: user.profile?.zip || "",
|
|
|
|
|
|
|
|
notes: user.profile?.notes || "",
|
|
|
|
|
|
|
|
latitude: user.latitude || 0,
|
|
|
|
|
|
|
|
longitude: user.longitude || 0,
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
|
|
|
|
status_code: 200,
|
|
|
|
|
|
|
|
data: Object.values(uniqueCustomerMap)
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
|
|
console.error("❌ Error fetching resolved customer details:", error);
|
|
|
|
|
|
|
|
return reply.code(500).send({ error: "Internal server error" });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// const bcrypt = require("bcrypt");
|
|
|
|
// const bcrypt = require("bcrypt");
|
|
|
|
|
|
|
|
|
|
|
@ -7674,7 +7774,7 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
(issue) => issue.hardwareId === hardwareId
|
|
|
|
(issue) => issue.hardwareId === hardwareId
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// We want to get the issue object (prefer from categorizedIssues, else resolvedIssues)
|
|
|
|
// Get the issue object from categorized or resolved
|
|
|
|
let issue =
|
|
|
|
let issue =
|
|
|
|
categorizedIndex !== -1
|
|
|
|
categorizedIndex !== -1
|
|
|
|
? support.categorizedIssues[categorizedIndex]
|
|
|
|
? support.categorizedIssues[categorizedIndex]
|
|
|
@ -7690,10 +7790,12 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
|
|
|
|
|
|
|
|
const masterHardwareId = issue.masterHardwareId || issue.hardwareId;
|
|
|
|
const masterHardwareId = issue.masterHardwareId || issue.hardwareId;
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch master and slaves connection status
|
|
|
|
// Fetch master and slaves
|
|
|
|
const master = await Insensors.findOne({ hardwareId: masterHardwareId }).lean();
|
|
|
|
const master = await Insensors.findOne({ hardwareId: masterHardwareId }).lean();
|
|
|
|
if (!master) {
|
|
|
|
if (!master) {
|
|
|
|
return reply.code(404).send({ message: `Master device not found with hardwareId ${masterHardwareId}` });
|
|
|
|
return reply
|
|
|
|
|
|
|
|
.code(404)
|
|
|
|
|
|
|
|
.send({ message: `Master device not found with hardwareId ${masterHardwareId}` });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const slaves = await Insensors.find({ connected_to: masterHardwareId }).lean();
|
|
|
|
const slaves = await Insensors.find({ connected_to: masterHardwareId }).lean();
|
|
|
@ -7703,9 +7805,10 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
slaves.every((s) => s.connected_status === "connected");
|
|
|
|
slaves.every((s) => s.connected_status === "connected");
|
|
|
|
|
|
|
|
|
|
|
|
if (allConnected) {
|
|
|
|
if (allConnected) {
|
|
|
|
// If all connected, move to resolvedIssues if not already there
|
|
|
|
// If fully connected
|
|
|
|
|
|
|
|
|
|
|
|
if (resolvedIndex === -1) {
|
|
|
|
if (resolvedIndex === -1) {
|
|
|
|
// Add to resolvedIssues
|
|
|
|
// Add to resolvedIssues only if not already present
|
|
|
|
support.resolvedIssues.push({
|
|
|
|
support.resolvedIssues.push({
|
|
|
|
type: issue.type,
|
|
|
|
type: issue.type,
|
|
|
|
hardwareId: issue.hardwareId,
|
|
|
|
hardwareId: issue.hardwareId,
|
|
|
@ -7715,7 +7818,14 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
originalMovedAt: issue.movedAt || null,
|
|
|
|
originalMovedAt: issue.movedAt || null,
|
|
|
|
movedToCategory: true,
|
|
|
|
movedToCategory: true,
|
|
|
|
slaveName: issue.slaveName || null,
|
|
|
|
slaveName: issue.slaveName || null,
|
|
|
|
|
|
|
|
currentlyResolved: true,
|
|
|
|
|
|
|
|
invalidatedAt: null,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
// If already in resolvedIssues, just mark as currently resolved again
|
|
|
|
|
|
|
|
support.resolvedIssues[resolvedIndex].currentlyResolved = true;
|
|
|
|
|
|
|
|
support.resolvedIssues[resolvedIndex].invalidatedAt = null;
|
|
|
|
|
|
|
|
support.resolvedIssues[resolvedIndex].resolvedAt = nowTime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Remove from categorizedIssues if present
|
|
|
|
// Remove from categorizedIssues if present
|
|
|
@ -7726,15 +7836,16 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
await support.save();
|
|
|
|
await support.save();
|
|
|
|
return reply.send({ message: "Issue moved to resolved category successfully" });
|
|
|
|
return reply.send({ message: "Issue moved to resolved category successfully" });
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Some device disconnected — move or keep in categorizedIssues with "Escalation" category
|
|
|
|
// One or more devices still disconnected
|
|
|
|
|
|
|
|
|
|
|
|
// Remove from resolvedIssues if present (issue is no longer resolved)
|
|
|
|
// Mark in resolvedIssues as not currently resolved, don't remove it
|
|
|
|
if (resolvedIndex !== -1) {
|
|
|
|
if (resolvedIndex !== -1) {
|
|
|
|
support.resolvedIssues.splice(resolvedIndex, 1);
|
|
|
|
support.resolvedIssues[resolvedIndex].currentlyResolved = false;
|
|
|
|
|
|
|
|
support.resolvedIssues[resolvedIndex].invalidatedAt = nowTime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (categorizedIndex === -1) {
|
|
|
|
if (categorizedIndex === -1) {
|
|
|
|
// Not in categorizedIssues — add it now
|
|
|
|
// Not in categorized — add with Escalation category
|
|
|
|
support.categorizedIssues.push({
|
|
|
|
support.categorizedIssues.push({
|
|
|
|
type: issue.type,
|
|
|
|
type: issue.type,
|
|
|
|
hardwareId: issue.hardwareId,
|
|
|
|
hardwareId: issue.hardwareId,
|
|
|
@ -7745,7 +7856,7 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
slaveName: issue.slaveName || null,
|
|
|
|
slaveName: issue.slaveName || null,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Already in categorizedIssues — update category to "Escalation" if different
|
|
|
|
// Already in categorized — update if category not "Escalation"
|
|
|
|
if (support.categorizedIssues[categorizedIndex].category !== "Escalation") {
|
|
|
|
if (support.categorizedIssues[categorizedIndex].category !== "Escalation") {
|
|
|
|
support.categorizedIssues[categorizedIndex].category = "Escalation";
|
|
|
|
support.categorizedIssues[categorizedIndex].category = "Escalation";
|
|
|
|
support.categorizedIssues[categorizedIndex].movedAt = nowTime;
|
|
|
|
support.categorizedIssues[categorizedIndex].movedAt = nowTime;
|
|
|
@ -7753,11 +7864,9 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
await support.save();
|
|
|
|
await support.save();
|
|
|
|
return reply.send({
|
|
|
|
return reply.send({
|
|
|
|
message:
|
|
|
|
message: "Master or some slaves are disconnected. Issue moved/kept in escalation category.",
|
|
|
|
"Master or some slaves are disconnected. Issue moved/kept in escalation category.",
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
} catch (err) {
|
|
|
@ -7765,3 +7874,4 @@ exports.resolvedIssuesForSupport = async (req, reply) => {
|
|
|
|
return reply.code(500).send({ error: "Internal Server Error" });
|
|
|
|
return reply.code(500).send({ error: "Internal Server Error" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|