From cdb6afd11d112f01f592d0e9bbb05fc81e84d9fc Mon Sep 17 00:00:00 2001 From: Bhaskar Date: Thu, 27 Mar 2025 17:45:59 +0530 Subject: [PATCH] elecrticty work and plumbing work pictures apis --- src/controllers/installationController.js | 46 +++++++-- src/index.js | 118 +++++++++++++++++++++- src/models/store.js | 61 ++++++++++- src/routes/installationRoute.js | 47 +++++++-- 4 files changed, 250 insertions(+), 22 deletions(-) diff --git a/src/controllers/installationController.js b/src/controllers/installationController.js index 5c8fc203..de78f043 100644 --- a/src/controllers/installationController.js +++ b/src/controllers/installationController.js @@ -3,7 +3,7 @@ const bcrypt = require('bcrypt'); const jwt = require('jsonwebtoken'); const customJwtAuth = require("../customAuthJwt"); const { Deparments } = require("../models/Department"); -const { Install, SensorStock, SensorQuotation, Order, Insensors, MasterSlaveData } = require("../models/store"); +const { Install, SensorStock, SensorQuotation, Order, Insensors, MasterSlaveData, ElectrictyWorkPictures, PlumbingWorkPictures } = require("../models/store"); const { Counter } = require("../models/User"); const { IotData, Tank } = require("../models/tanks"); const fastify = require("fastify")({ @@ -674,45 +674,75 @@ exports.getAllocatedSensorsByTank = async (req, reply) => { } }; + exports.createMasterSlaveData = async (req, reply) => { try { - const { installationId } = req.params; + const { installationId } = req.params; const { type, + customerId, hardwareId, batchno, masterId, tankName, tankLocation, materialRecived, - electicityWork, + electricityWork, plumbingWork, loraCheck - } = req.body; + } = req.body; if (!installationId || !hardwareId || !masterId) { return reply.status(400).send({ message: "installationId, hardwareId, and masterId are required." }); } + // 🔹 Fetch stored electricity work pictures + const electricityWorkData = await ElectrictyWorkPictures.findOne({ + installationId, + customerId + }); + + const electricityWorkPictures = electricityWorkData + ? electricityWorkData.pictureUrl.map(pic => ({ url: pic.url, uploadedAt: new Date() })) + : []; + + // 🔹 Fetch stored plumbing work pictures + const plumbingWorkData = await PlumbingWorkPictures.findOne({ + installationId, + customerId + }); + + const plumbingWorkPictures = plumbingWorkData + ? plumbingWorkData.pictureUrl.map(pic => ({ url: pic.url, uploadedAt: new Date() })) + : []; + + // 🔹 Save all data to MasterSlaveData const newData = new MasterSlaveData({ installationId, type, + customerId, hardwareId, batchno, masterId, tankName, tankLocation, materialRecived, - electicityWork, + electricityWork, plumbingWork, - loraCheck + loraCheck, + electricityWorkPictures, + plumbingWorkPictures }); - // Save to database await newData.save(); - reply.status(201).send({ message: "Master-Slave data created successfully", data: newData }); + reply.status(201).send({ + message: "Master-Slave data created successfully", + data: newData + }); + } catch (err) { reply.status(500).send({ message: err.message }); } }; + diff --git a/src/index.js b/src/index.js index 0ef7affe..47079054 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,7 @@ const createConnectionController = require("./controllers/createConnectionContro const storeController = require("./controllers/storeController.js") const boom = require("boom"); const bcrypt = require('bcrypt'); -const { ProfilePictureStore,generateinstallationId,Store, Survey} = require("./models/store"); +const { ProfilePictureStore,generateinstallationId,Store, Survey, PlumbingWorkPictures, ElectrictyWorkPictures} = require("./models/store"); const cors = require('fastify-cors'); @@ -908,6 +908,122 @@ fastify.post('/api/uploads-user/:customerId', async (request, reply) => { } }); + +fastify.post("/api/uploads-electricty-work/:customerId/:installationId", async (request, reply) => { + try { + const { customerId, installationId } = request.params; + const files = await request.files(); // Await files properly + + if (!files || files.length === 0) { + return reply.code(400).send({ error: "No files uploaded" }); + } + + const bucketName = "arminta_profile_pictures"; + const publicUrls = []; + + for await (const file of files) { + const uniqueFileName = `${Date.now()}-${Math.random().toString(36).substring(7)}-${file.filename}`; + const filePath = `electricty_work_picture/${uniqueFileName}`; + + console.log(`Uploading file: ${file.filename} → ${filePath}`); + + const writeStream = storage.bucket(bucketName).file(filePath).createWriteStream(); + + file.file.pipe(writeStream); + + await new Promise((resolve, reject) => { + writeStream.on("finish", async () => { + try { + await storage.bucket(bucketName).file(filePath).makePublic(); + const publicUrl = `https://storage.googleapis.com/${bucketName}/${filePath}`; + publicUrls.push(publicUrl); + console.log(`File uploaded: ${publicUrl}`); + resolve(); + } catch (error) { + console.error("Failed to make file public:", error); + reject(error); + } + }); + + writeStream.on("error", (err) => { + console.error("Failed to upload file:", err); + reject(err); + }); + }); + } + + // Update MongoDB: Convert URLs to { url: "..." } objects + const updatedRecord = await ElectrictyWorkPictures.findOneAndUpdate( + { customerId, installationId }, + { $push: { pictureUrl: { $each: publicUrls.map(url => ({ url })) } } }, // Append new images + { new: true, upsert: true } + ); + + reply.send({ success: true, pictures: publicUrls, details: updatedRecord }); + } catch (err) { + console.error("Upload Error:", err); + reply.code(500).send({ error: "An error occurred", details: err.message }); + } +}); + + +fastify.post("/api/uploads-plumbing-work/:customerId/:installationId", async (request, reply) => { + try { + const { customerId, installationId } = request.params; + const files = await request.files(); // Await files properly + + if (!files || files.length === 0) { + return reply.code(400).send({ error: "No files uploaded" }); + } + + const bucketName = "arminta_profile_pictures"; + const publicUrls = []; + + for await (const file of files) { + const uniqueFileName = `${Date.now()}-${Math.random().toString(36).substring(7)}-${file.filename}`; + const filePath = `plumbing_work_picture/${uniqueFileName}`; + + console.log(`Uploading file: ${file.filename} → ${filePath}`); + + const writeStream = storage.bucket(bucketName).file(filePath).createWriteStream(); + + file.file.pipe(writeStream); + + await new Promise((resolve, reject) => { + writeStream.on("finish", async () => { + try { + await storage.bucket(bucketName).file(filePath).makePublic(); + const publicUrl = `https://storage.googleapis.com/${bucketName}/${filePath}`; + publicUrls.push(publicUrl); + console.log(`File uploaded: ${publicUrl}`); + resolve(); + } catch (error) { + console.error("Failed to make file public:", error); + reject(error); + } + }); + + writeStream.on("error", (err) => { + console.error("Failed to upload file:", err); + reject(err); + }); + }); + } + + // Update MongoDB: Convert URLs to { url: "..." } objects + const updatedRecord = await PlumbingWorkPictures.findOneAndUpdate( + { customerId, installationId }, + { $push: { pictureUrl: { $each: publicUrls.map(url => ({ url })) } } }, // Append new images + { new: true, upsert: true } + ); + + reply.send({ success: true, pictures: publicUrls, details: updatedRecord }); + } catch (err) { + console.error("Upload Error:", err); + reply.code(500).send({ error: "An error occurred", details: err.message }); + } +}); + fastify.post("/api/installLogin", { schema: { description: "This is for Login Install", diff --git a/src/models/store.js b/src/models/store.js index 7a077735..68b3e764 100644 --- a/src/models/store.js +++ b/src/models/store.js @@ -655,6 +655,7 @@ const salesSchema = new mongoose.Schema({ const masterSlaveDataSchema = new mongoose.Schema({ installationId: {type: String}, + customerId: {type: String}, type: { type: String}, hardwareId: { type: String }, batchno: { type: String, default: null }, @@ -662,17 +663,73 @@ const masterSlaveDataSchema = new mongoose.Schema({ tankName: { type: String }, tankLocation: { type: String }, materialRecived: { type: String }, - electicityWork: { type: String }, + electricityWork: { type: String }, plumbingWork: { type: String }, + electricityWorkPictures: [ + { + url: { type: String }, + uploadedAt: { type: Date, default: Date.now } + } + ], + plumbingWorkPictures: [ + { + url: { type: String }, + uploadedAt: { type: Date, default: Date.now } + } + ], loraCheck: { type: String }, }, { timestamps: true, }); +const electrictyWorkPicturesSchema = new Schema({ + installationId: { + type: String, + //required: true, + //unique: true + }, + customerId: { + type: String, + //required: true + }, + pictureUrl: [{ + url: { + type: String, + }, + }], + createdAt: { + type: Date, + default: Date.now + } +}); + +const plumbingWorkPicturesSchema = new Schema({ + installationId: { + type: String, + //required: true, + //unique: true + }, + customerId: { + type: String, + //required: true + }, + pictureUrl: [{ + url: { + type: String, + }, + }], + createdAt: { + type: Date, + default: Date.now + } +}); + const Iotprice = mongoose.model('Iotprice', iotpriceSchema); const Insensors = mongoose.model('Insensors', insensorsSchema); const MasterSlaveData = mongoose.model('MasterSlaveData', masterSlaveDataSchema); + const ElectrictyWorkPictures = mongoose.model('ElectrictyWorkPictures', electrictyWorkPicturesSchema); + const PlumbingWorkPictures = mongoose.model('PlumbingWorkPictures', plumbingWorkPicturesSchema); const Order = mongoose.model('Order', orderSchema); @@ -695,4 +752,4 @@ const Iotprice = mongoose.model('Iotprice', iotpriceSchema); - module.exports = {MasterSlaveData,SensorStock,Order,EstimationOrder,Iotprice,Sales, Install,Survey, ProfilePictureInstall, SensorQuotation,generateinstallationId,Store,ProfilePictureStore,WaterLeverSensor,MotorSwitchSensor,Insensors,generatequatationId, HardwareCart, ServiceCart}; + module.exports = {PlumbingWorkPictures,ElectrictyWorkPictures,MasterSlaveData,SensorStock,Order,EstimationOrder,Iotprice,Sales, Install,Survey, ProfilePictureInstall, SensorQuotation,generateinstallationId,Store,ProfilePictureStore,WaterLeverSensor,MotorSwitchSensor,Insensors,generatequatationId, HardwareCart, ServiceCart}; diff --git a/src/routes/installationRoute.js b/src/routes/installationRoute.js index c2ca1113..d93f64c9 100644 --- a/src/routes/installationRoute.js +++ b/src/routes/installationRoute.js @@ -288,29 +288,54 @@ module.exports = function (fastify, opts, next) { type: "object", required: ["installationId"], properties: { - installationId: { type: "string", description: "Installation ID to associate the master-slave data with" } + installationId: { type: "string", description: "Installation ID" } } }, body: { type: "object", required: ["hardwareId", "masterId"], properties: { - type: { type: "string", description: "Type of the device (master/slave)" }, - hardwareId: { type: "string", description: "Hardware ID of the device" }, - batchno: { type: "string", description: "Batch number (optional)" }, - masterId: { type: "string", description: "Master ID associated with the device" }, - tankName: { type: "string", description: "Name of the tank" }, - tankLocation: { type: "string", description: "Location of the tank" }, - materialRecived: { type: "string", description: "Material received status" }, - electicityWork: { type: "string", description: "Electricity work status" }, - plumbingWork: { type: "string", description: "Plumbing work status" }, - loraCheck: { type: "string", description: "LoRa check status" } + type: { type: "string" }, + customerId: { type: "string" }, + hardwareId: { type: "string" }, + batchno: { type: "string" }, + masterId: { type: "string" }, + tankName: { type: "string" }, + tankLocation: { type: "string" }, + materialRecived: { type: "string" }, + electricityWork: { type: "string" }, + plumbingWork: { type: "string" }, + loraCheck: { type: "string" }, + + // ✅ Removing `format: "uri"` + electricityWorkPictures: { + type: "array", + items: { + type: "object", + properties: { + url: { type: "string", description: "Image URL" }, // No format validation + uploadedAt: { type: "string", format: "date-time", description: "Upload timestamp" } + } + } + }, + plumbingWorkPictures: { + type: "array", + items: { + type: "object", + properties: { + url: { type: "string", description: "Image URL" }, // No format validation + uploadedAt: { type: "string", format: "date-time", description: "Upload timestamp" } + } + } + } } } }, handler: installationController.createMasterSlaveData }); + + next(); } \ No newline at end of file