diff --git a/src/controllers/storeController.js b/src/controllers/storeController.js index 3f1c9a22..9e440f0f 100644 --- a/src/controllers/storeController.js +++ b/src/controllers/storeController.js @@ -11,7 +11,7 @@ const fastify = require("fastify")({ }, }); -const {Order,Iotprice, Install, ProfilePictureInstall, SensorQuotation,generateinstallationId,Store,WaterLeverSensor,MotorSwitchSenso,Insensors,generatequatationId, HardwareCart, ServiceCart, Sales} = require("../models/store"); +const {Order,EstimationOrder,Iotprice, Install, ProfilePictureInstall, SensorQuotation,generateinstallationId,Store,WaterLeverSensor,MotorSwitchSenso,Insensors,generatequatationId, HardwareCart, ServiceCart, Sales} = require("../models/store"); const { User,Counter, generateBookingId,resetCounter,generateCustomerId,ProfilePicture} = require('../models/User') @@ -1541,6 +1541,7 @@ exports.createquotationforSensor = async (req, reply) => { const newQuotation = new SensorQuotation({ quatationId, customerId, + surveyId, quote_status: "sentfromsurvey", masters, @@ -1559,6 +1560,7 @@ exports.createquotationforSensor = async (req, reply) => { message: 'Quotation for sensors created successfully.', data: savedQuotation, }); + } catch (error) { console.error('Error creating quotation:', error); reply.code(500).send({ @@ -1679,22 +1681,38 @@ exports.createEstimationPrice = async (req, reply) => { exports.getallquotationdata = async (req, reply) => { try { - await SensorQuotation.find({}) - .exec() - .then((docs) => { - reply.send({ status_code: 200, data: docs, count: docs.length }); - }) - .catch((err) => { - console.log(err); - reply.send({ error: err }); - }); + const quotations = await SensorQuotation.find({}).lean(); // Use lean() for better performance + + // Extract unique customerIds from quotations + const customerIds = [...new Set(quotations.map((q) => q.customerId).filter(Boolean))]; + + // Fetch customer details for all unique customerIds + const customers = await User.find({ customerId: { $in: customerIds } }).lean(); + + // Convert customer array to a dictionary for quick lookup + const customerMap = customers.reduce((acc, customer) => { + acc[customer.customerId] = customer; + return acc; + }, {}); + + + // Attach customer details to quotations + const enrichedQuotations = quotations.map((quotation) => ({ + ...quotation, + customerDetails: customerMap[quotation.customerId] || null, // Attach customer details if found + })); + + reply.send({ status_code: 200, data: enrichedQuotations, count: enrichedQuotations.length }); } catch (err) { - throw boom.boomify(err); + console.error(err); + reply.send({ error: err.message }); } }; + + exports.saveQuotationData = async (req, reply) => { try { const { quotationId } = req.params; // Retrieve the quotationId from the request parameters @@ -1902,7 +1920,7 @@ exports.handleEstimation = async (req, reply) => { } // If accepted, generate unique Order ID - const lastOrder = await Order.findOne().sort({ createdAt: -1 }); + const lastOrder = await EstimationOrder.findOne().sort({ createdAt: -1 }); let orderId = "AWS001"; if (lastOrder) { const lastNumber = parseInt(lastOrder.orderId.replace("AWS", ""), 10) + 1; @@ -1910,7 +1928,7 @@ exports.handleEstimation = async (req, reply) => { } // Create a new order in the database - const newOrder = new Order({ + const newOrder = new EstimationOrder({ orderId, customerId, items, @@ -1944,7 +1962,7 @@ exports.editOrder = async (req, reply) => { } // Find the existing order - const existingOrder = await Order.findOne({ orderId }); + const existingOrder = await EstimationOrder.findOne({ orderId }); if (!existingOrder) { return reply.code(404).send({ message: "Order not found" }); @@ -1979,7 +1997,7 @@ exports.getOrdersByCustomer = async (req, reply) => { } // Fetch orders with status 'pending' or 'accepted' for the given customer - const orders = await Order.find({ + const orders = await EstimationOrder.find({ customerId, status: { $in: ["pending", "accepted"] } }); @@ -2000,3 +2018,76 @@ exports.getOrdersByCustomer = async (req, reply) => { } }; +exports.acceptQuotation = async (req, reply) => { + try { + const { quotationId } = req.params; + let { action, storeId } = req.body; + + action = action.toLowerCase(); // Convert action to lowercase + + // Find the quotation by ID + const quotation = await SensorQuotation.findOne({ quatationId: quotationId }); + + if (!quotation) { + return reply.status(404).send({ error: "Quotation not found" }); + } + + if (action === "reject") { + // Update status to "rejected" in SensorQuotation + await SensorQuotation.updateOne({ quatationId: quotationId }, { $set: { status: "rejected" } }); + + return reply.send({ + status_code: 200, + message: "Quotation rejected successfully", + }); + } else if (action === "accept") { + // Convert quotation to an order object and include storeId + const newOrder = new Order({ + ...quotation.toObject(), // Copy all fields from quotation + storeId: storeId, // Ensure storeId is included + status: "pending", // Set status to "pending" + }); + + // Save to the Orders collection + await newOrder.save(); + + // Delete the record from SensorQuotation + await SensorQuotation.deleteOne({ quatationId: quotationId }); + + return reply.send({ + status_code: 200, + message: "Quotation accepted and moved to Orders", + data: newOrder, + }); + } else { + return reply.status(400).send({ error: "Invalid action" }); + } + } catch (err) { + console.error("Error processing quotation:", err); + return reply.status(500).send({ error: "Internal server error" }); + } +}; + + +exports.getOrdersByStoreId = async (req, reply) => { + try { + const { storeId } = req.params; + + if (!storeId) { + return reply.status(400).send({ error: "storeId is required" }); + } + + // Fetch orders with the matching storeId + const orders = await Order.find({ storeId }); + + return reply.send({ + status_code: 200, + message: "Orders fetched successfully", + data: orders, + }); + } catch (err) { + console.error("Error fetching orders:", err); + return reply.status(500).send({ error: "Internal server error" }); + } +}; + diff --git a/src/models/store.js b/src/models/store.js index cc2a7031..68f52458 100644 --- a/src/models/store.js +++ b/src/models/store.js @@ -370,7 +370,7 @@ const iotpriceSchema = new mongoose.Schema({ cost: { type: Number, default: null }, }); -const orderSchema = new mongoose.Schema({ +const estimationorderSchema = new mongoose.Schema({ orderId: { type: String, unique: true, required: true }, customerId: { type: String, required: true }, items: { type: Array, required: true }, @@ -382,6 +382,7 @@ const orderSchema = new mongoose.Schema({ const sensorquotationSchema = new mongoose.Schema({ customerId: { type: String }, surveyId: { type: String, default: null }, + storeId: { type: String, default: null }, installationId: { type: String, default: null }, quatationId: { type: String, default: null }, masters: { type: String }, @@ -405,9 +406,13 @@ const sensorquotationSchema = new mongoose.Schema({ wire: { type: String, default: null }, switch: { type: String, default: null }, text: { type: String, default: null }, + available_quantity: { type: String, default: null }, }, ], master_type_quantity_price: { type: String, default: null }, + master_available_quantity: { type: String, default: null }, + slave_available_quantity: { type: String, default: null }, + sensor_available_quantity: { type: String, default: null }, master_type_total_price: { type: String, default: null }, sensor_type_quantity_price: { type: String , default: null}, sensor_type_total_price: { type: String , default: null}, @@ -416,6 +421,56 @@ const sensorquotationSchema = new mongoose.Schema({ qutation_total_price: { type: String, default: null }, }); + + + + +const orderSchema = new mongoose.Schema({ + customerId: { type: String }, + surveyId: { type: String, default: null }, + storeId: { type: String, default: null }, + installationId: { type: String, default: null }, + quatationId: { type: String, default: null }, + masters: { type: String }, + masters_quantity_price: { type: String }, + masters_total_price: { type: String }, + slaves: { type: String }, + sensors: { type: String }, + slaves_quantity_price: { type: String }, + slaves_total_price: { type: String }, + motor_switches: { type: String }, + motor_switches_quantity_price: { type: String }, + motor_switches_total_price: { type: String }, + quote_status: { type: String, default: null }, + quoted_amount: { type: String, default: null }, + comments: { type: String, default: null }, + datetime: { type: String, default: null }, + updated_at: { type: String, default: null }, + electricals: [ + { + type: { type: String, default: null }, + wire: { type: String, default: null }, + switch: { type: String, default: null }, + text: { type: String, default: null }, + available_quantity: { type: String, default: null }, + }, + ], + master_type_quantity_price: { type: String, default: null }, + master_available_quantity: { type: String, default: null }, + slave_available_quantity: { type: String, default: null }, + sensor_available_quantity: { type: String, default: null }, + master_type_total_price: { type: String, default: null }, + sensor_type_quantity_price: { type: String, default: null }, + sensor_type_total_price: { type: String, default: null }, + switch_type_quantity_price: { type: String, default: null }, + switch_type_total_price: { type: String, default: null }, + qutation_total_price: { type: String, default: null }, + status: { type: String, default: "pending" }, // Status field added +}); + + + + const hardwareCartSchema = new mongoose.Schema({ productId: { type: String}, productName: { type: String }, @@ -510,7 +565,9 @@ const salesSchema = new mongoose.Schema({ const Iotprice = mongoose.model('Iotprice', iotpriceSchema); const Insensors = mongoose.model('Insensors', insensorsSchema); - const Order = mongoose.model('Orders', orderSchema); + const Order = mongoose.model('Order', orderSchema); + const EstimationOrder = mongoose.model('EstimationOrder', estimationorderSchema); + const Store = mongoose.model("Store", storeSchema); const WaterLeverSensor = mongoose.model('WaterLeverSensor', waterLeverSensorInSchema); const ProfilePictureStore = mongoose.model('ProfilePictureStore', profilePictureStoreSchema); @@ -527,4 +584,4 @@ const Iotprice = mongoose.model('Iotprice', iotpriceSchema); - module.exports = {Order,Iotprice,Sales, Install,Survey, ProfilePictureInstall, SensorQuotation,generateinstallationId,Store,ProfilePictureStore,WaterLeverSensor,MotorSwitchSensor,Insensors,generatequatationId, HardwareCart, ServiceCart}; + module.exports = {Order,EstimationOrder,Iotprice,Sales, Install,Survey, ProfilePictureInstall, SensorQuotation,generateinstallationId,Store,ProfilePictureStore,WaterLeverSensor,MotorSwitchSensor,Insensors,generatequatationId, HardwareCart, ServiceCart}; diff --git a/src/routes/storeRoute.js b/src/routes/storeRoute.js index e788bcd1..f034f0f6 100644 --- a/src/routes/storeRoute.js +++ b/src/routes/storeRoute.js @@ -1314,6 +1314,7 @@ fastify.post("/api/createquotationforSensor/:surveyId", { type: "object", properties: { customerId: { type: "string" }, + masters: { type: "string" }, slaves: { type: "string" }, sensors: { type: "string" }, @@ -1654,5 +1655,59 @@ fastify.post("/api/cart/installationService", { }, handler: storeController.addToCartService }); + + +fastify.post("/api/acceptquotation/:quotationId", { + schema: { + tags: ["Install"], + description: "Accepts a quotation and moves it to the Orders database", + summary: "Accepts a quotation", + params: { + type: "object", + properties: { + quotationId: { type: "string" }, + }, + }, + body: { + type: "object", + properties: { + action: { type: "string" }, + storeId: { type: "string" }, + }, + required: ["action"], + }, + security: [ + { + basicAuth: [], + }, + ], + }, + // preHandler: fastify.auth([fastify.authenticate]), // Uncomment if authentication is needed + handler: storeController.acceptQuotation, +}); + + +fastify.get("/api/ordersofstore/:storeId", { + schema: { + tags: ["Install"], + description: "Fetches orders based on storeId", + summary: "Get orders by storeId", + params: { + type: "object", + properties: { + storeId: { type: "string" }, + }, + required: ["storeId"], + }, + security: [ + { + basicAuth: [], + }, + ], + }, + handler: storeController.getOrdersByStoreId, +}); + + next(); };