diff --git a/src/controllers/installationController.js b/src/controllers/installationController.js index 39dc86b7..13a2e518 100644 --- a/src/controllers/installationController.js +++ b/src/controllers/installationController.js @@ -251,7 +251,7 @@ exports.assignTeamMemberToQuotation = async (request, reply) => { quotation = new Order({ installationId, quatationId: quotationId, - assignedTeamMembers: [], + assignedTeamMembers: [], // Ensure assignedTeamMembers array is initialized status: "Pending", // Default status when created }); } @@ -268,9 +268,13 @@ exports.assignTeamMemberToQuotation = async (request, reply) => { // 🔹 Update order status when a team member is assigned quotation.status = "Assigned"; // Update status - // 🔹 Save the updated quotation + // 🔹 Save the updated quotation in the Order schema await quotation.save(); + // 🔹 Update Installation schema with quotationId + installation.quatationId = quotationId; + await installation.save(); + return reply.send({ simplydata: { error: false, @@ -436,4 +440,94 @@ exports.assignTeamMemberToQuotation = async (request, reply) => { }); } }; + + + exports.getQuotationsByInstallationId = async (request, reply) => { + try { + const { installationId } = request.params; + + if (!installationId) { + return reply.status(400).send({ + simplydata: { + error: true, + message: "Installation ID is required", + }, + }); + } + + // 🔹 Fetch quotations based on installationId + const quotations = await Order.find({ installationId }); + + if (!quotations || quotations.length === 0) { + return reply.status(404).send({ + simplydata: { + error: true, + message: "No quotations found for this installation ID", + }, + }); + } + + return reply.send({ + simplydata: { + error: false, + message: "Quotations fetched successfully", + quotations, + }, + }); + } catch (err) { + console.error("Error fetching quotations:", err); + reply.status(500).send({ + simplydata: { + error: true, + message: "Internal server error", + }, + }); + } + }; + + exports.getQuotationsByInstallationAndTeamMember = async (request, reply) => { + try { + const { installationId, teamMemberId } = request.params; + + if (!installationId || !teamMemberId) { + return reply.status(400).send({ + simplydata: { + error: true, + message: "Both installationId and teamMemberId are required", + }, + }); + } + + // 🔹 Fetch quotations where installationId matches and teamMemberId is assigned + const quotations = await Order.find({ + installationId, + assignedTeamMembers: teamMemberId, + }); + + if (!quotations || quotations.length === 0) { + return reply.status(404).send({ + simplydata: { + error: true, + message: "No quotations found for this installation and team member", + }, + }); + } + + return reply.send({ + simplydata: { + error: false, + message: "Quotations fetched successfully", + quotations, + }, + }); + } catch (err) { + console.error("Error fetching quotations:", err); + reply.status(500).send({ + simplydata: { + error: true, + message: "Internal server error", + }, + }); + } + }; \ No newline at end of file diff --git a/src/controllers/tanksController.js b/src/controllers/tanksController.js index b1835507..8533bd0a 100644 --- a/src/controllers/tanksController.js +++ b/src/controllers/tanksController.js @@ -3080,22 +3080,50 @@ exports.motorAction = async (req, reply) => { const supplierTank = await Tank.findOne({ customerId, tankName: req.body.from, tankLocation: req.body.from_type.toLowerCase() }); const currentWaterLevel = parseInt(supplierTank.waterlevel, 10); const currentWaterPercentage = (currentWaterLevel / parseInt(supplierTank.capacity.replace(/,/g, ''), 10)) * 100; - + const notificationTracker = new Map(); if (new Date() >= thresholdTime || currentWaterPercentage <= lowWaterThreshold) { console.log(new Date(),"new date") console.log(thresholdTime,"thresholdTime") console.log("motor stopping because it entered this condition") // Emit the threshold time notification - eventEmitter.emit( + // eventEmitter.emit( + // "sendThresholdTimeNotification", + // customerId, + // fcmToken, + // manual_threshold_time, + // motorId, + // tankName, + // blockName + // ); + + const notificationKey = `${customerId}_${motorId}_threshold`; + + // Check if the notification has already been sent + if (!notificationTracker.get(notificationKey)) { + console.log("Sending threshold time notification..."); + + eventEmitter.emit( "sendThresholdTimeNotification", - customerId, - fcmToken, - manual_threshold_time, + customerId, + fcmToken, + manual_threshold_time, motorId, tankName, - blockName - ); + blockName + ); + + // Mark notification as sent + notificationTracker.set(notificationKey, true); + + // Optionally, reset the flag after some time (e.g., 24 hours) + setTimeout(() => { + notificationTracker.delete(notificationKey); + }, 24 * 60 * 60 * 1000); // Reset after 24 hours + } else { + console.log("Notification already sent, skipping..."); + } + const currentTime = moment().tz('Asia/Kolkata').format('DD-MMM-YYYY - HH:mm'); await Tank.updateOne( { customerId, "connections.inputConnections.motor_id": motorId }, @@ -6003,7 +6031,9 @@ const sendMotorNotifications = async () => { const inputConnection = motorTank.connections.inputConnections.find( (conn) => conn.motor_id ); - + const status = inputConnection.motor_status + //console.log("motorTank",inputConnection) +// console.log("inputConnection.motor_on_type ",inputConnection.motor_on_type ) if (!inputConnection) continue; const { customerId, blockName, tankName } = motorTank; @@ -6012,7 +6042,7 @@ const sendMotorNotifications = async () => { // 🔹 Motor Start Condition if ( - inputConnection.motor_stop_status === "2" && + inputConnection.motor_stop_status === "2" && status ===1 && inputConnection.motor_on_type === "forced_manual" && !motorTank.motor_start_notified ) { console.log("✅ Sending Motor Start Notification..."); @@ -6037,7 +6067,7 @@ const sendMotorNotifications = async () => { // 🔹 Motor Stop Condition if ( - inputConnection.motor_stop_status === "1" && + inputConnection.motor_stop_status === "1" && inputConnection.motor_on_type === "forced_manual" && status ===2 && !motorTank.motor_stop_notified ) { console.log("✅ Sending Motor Stop Notification..."); @@ -6066,7 +6096,7 @@ const sendMotorNotifications = async () => { return user?.fcmIds?.filter((token) => token) || []; }; - // Run the notification check every second + //Run the notification check every second cron.schedule("* * * * * *", async () => { await sendMotorNotifications(); }); diff --git a/src/index.js b/src/index.js index 5157cd71..f844a558 100644 --- a/src/index.js +++ b/src/index.js @@ -1021,102 +1021,110 @@ fastify.post("/api/installLogin", { }); - fastify.post("/api/teamMemberLogin", { - schema: { - description: "Login API for team members", - tags: ["Installation"], - summary: "Login as a Team Member", - body: { - type: "object", - required: ["type", "phone", "password"], - properties: { - type: { type: "string", description: "Role type of the user (e.g., 'team_member')" }, - phone: { type: "string", description: "Registered phone number of the team member" }, - password: { type: "string", description: "Password for authentication" }, - }, +fastify.post("/api/teamMemberLogin", { + schema: { + description: "Login API for team members", + tags: ["Installation"], + summary: "Login as a Team Member", + body: { + type: "object", + required: ["type", "phone", "password"], + properties: { + type: { type: "string", description: "Role type of the user (e.g., 'team_member')" }, + phone: { type: "string", description: "Registered phone number of the team member" }, + password: { type: "string", description: "Password for authentication" }, }, }, - async handler(request, reply) { - try { - const { type, phone, password } = request.body; - - // Find team member in any installation - const installation = await Install.findOne({ "team_member.team_member.phone": phone }); - - if (!installation) { - return reply.status(401).send({ - simplydata: { - error: true, - message: "Invalid phone number or password", - }, - }); - } - - // Find team member details - const teamMember = installation.team_member.team_member.find( - (member) => member.phone === phone - ); - - if (!teamMember) { - return reply.status(401).send({ - simplydata: { - error: true, - message: "Invalid phone number or password", - }, - }); - } - - // Verify password - const isPasswordValid = await bcrypt.compare(password, teamMember.password); - - if (!isPasswordValid) { - return reply.status(401).send({ - simplydata: { - error: true, - message: "Invalid phone number or password", - }, - }); - } - - // Store the `type` in the database (if not already stored) - if (!teamMember.type) { - teamMember.type = type; - await installation.save(); // Save the updated team member type - } - - // Generate JWT token - const token = fastify.jwt.sign( - { phone: teamMember.phone, role: type, installationId: installation.installationId }, - process.env.JWT_SECRET, - { expiresIn: "1h" } - ); - - return reply.send({ + }, + async handler(request, reply) { + try { + const { type, phone, password } = request.body; + + // Find the installation containing this team member + const installation = await Install.findOne({ + "team_member.team_member.phone": phone + }); + + if (!installation) { + return reply.status(401).send({ simplydata: { - error: false, - message: "Login successful", - access_token: token, - phone: teamMember.phone, - firstName: teamMember.firstName, - teamMemberId: teamMember.teamMemberId, - alternativePhone: teamMember.alternativePhone || null, - email: teamMember.email || null, - status: teamMember.status || "active", - type: teamMember.type, // Returning the stored type + error: true, + message: "Invalid phone number", }, }); - - } catch (err) { - console.error("Error logging in:", err); - reply.status(500).send({ + } + + // Find the specific team member inside the array + const teamMember = installation.team_member.team_member.find( + (member) => member.phone === phone + ); + + if (!teamMember) { + return reply.status(401).send({ simplydata: { error: true, - message: "Internal server error", + message: "Invalid phone number", }, }); } - }, - }); + + // Verify password + const isPasswordValid = await bcrypt.compare(password, teamMember.password); + + if (!isPasswordValid) { + return reply.status(401).send({ + simplydata: { + error: true, + message: "Invalid phone number or password", + }, + }); + } + + // Store the `type` in the database (if not already stored) + if (!teamMember.type) { + teamMember.type = type; + await installation.save(); // Save the updated team member type + } + + // Extract installationId from the found installation document + const installationId = installation.installationId; + + // Generate JWT token + const token = fastify.jwt.sign( + { phone: teamMember.phone, role: type, installationId }, + process.env.JWT_SECRET, + { expiresIn: "1h" } + ); + + return reply.send({ + simplydata: { + error: false, + message: "Login successful", + access_token: token, + phone: teamMember.phone, + firstName: teamMember.firstName || null, + teamMemberId: teamMember.teamMemberId, + alternativePhone: teamMember.alternativePhone || null, + email: teamMember.email || null, + status: teamMember.status || "active", + type: teamMember.type, // Returning the stored type + installationId: installationId // Now included in response + }, + }); + + } catch (err) { + console.error("Error logging in:", err); + reply.status(500).send({ + simplydata: { + error: true, + message: "Internal server error", + }, + }); + } + }, +}); + + fastify.post("/api/surveyLogin", { schema: { diff --git a/src/routes/installationRoute.js b/src/routes/installationRoute.js index 0e4f0fa0..f6d2bf96 100644 --- a/src/routes/installationRoute.js +++ b/src/routes/installationRoute.js @@ -46,6 +46,48 @@ module.exports = function (fastify, opts, next) { handler: installationController.getTeamMembers }); + fastify.get("/api/getQuations/:installationId", { + schema: { + description: "Get all quatations under a specific installation", + tags: ["Installation"], + summary: "Get all quatations under a specific installation", + params: { + type: "object", + properties: { + installationId: { + type: "string", + description: "Installation ID to fetch team members from" + } + }, + required: ["installationId"] + }, + + }, + handler: installationController.getQuotationsByInstallationId + }); + fastify.get("/api/getQuations/:installationId/:teamMemberId", { + schema: { + description: "Get all quatations under a specific installation and team member", + tags: ["Installation"], + summary: "Get all quatations under a specific installation and team member", + params: { + type: "object", + properties: { + installationId: { + type: "string", + description: "Installation ID to fetch team members from" + }, + teamMemberId: { + type: "string", + description: "teamMember ID to fetch team members from" + } + }, + // required: ["installationId"] + }, + + }, + handler: installationController.getQuotationsByInstallationAndTeamMember + }); fastify.post("/api/assignTeammember/:installationId", { schema: { description: "Assign a team member to an installation's quotation",