|
|
|
const boom = require("boom");
|
|
|
|
const bcrypt = require('bcrypt');
|
|
|
|
const jwt = require('jsonwebtoken');
|
|
|
|
const customJwtAuth = require("../customAuthJwt");
|
|
|
|
const fastify = require("fastify")({
|
|
|
|
logger: true,
|
|
|
|
//disableRequestLogging: true,
|
|
|
|
genReqId(req) {
|
|
|
|
// you get access to the req here if you need it - must be a synchronous function
|
|
|
|
return uuidv4();
|
|
|
|
},
|
|
|
|
});
|
|
|
|
const { Tankerbooking} = require("../models/tankers")
|
|
|
|
|
|
|
|
const {Repairorder,SensorStock,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')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.installSignUp = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const i_id = await generateinstallationId();
|
|
|
|
const installationId = `AWIN${i_id}`;
|
|
|
|
|
|
|
|
const {
|
|
|
|
// name,
|
|
|
|
phone,
|
|
|
|
address,
|
|
|
|
address1,
|
|
|
|
address2,
|
|
|
|
emails,
|
|
|
|
password,
|
|
|
|
profile,
|
|
|
|
team,
|
|
|
|
manager,
|
|
|
|
longitude,
|
|
|
|
latitude,
|
|
|
|
fcmId,
|
|
|
|
alternativeNumber,
|
|
|
|
firstName,
|
|
|
|
lastName,
|
|
|
|
city,
|
|
|
|
designation,
|
|
|
|
reportingManager,
|
|
|
|
departmentName,
|
|
|
|
zone,
|
|
|
|
createdBy,
|
|
|
|
updatedBy,
|
|
|
|
} = request.body;
|
|
|
|
|
|
|
|
// Check if a user with the same phone number already exists
|
|
|
|
const existingInstall = await Install.findOne({ phone });
|
|
|
|
if (existingInstall) {
|
|
|
|
return reply.status(400).send({ message: 'Phone is already registered' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash the password using bcrypt
|
|
|
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
|
|
|
|
|
|
// Create a new install object with the hashed password and other details
|
|
|
|
const install = new Install({
|
|
|
|
// name,
|
|
|
|
installationId,
|
|
|
|
phone,
|
|
|
|
address,
|
|
|
|
address1,
|
|
|
|
address2,
|
|
|
|
emails,
|
|
|
|
services: { password: { bcrypt: hashedPassword } },
|
|
|
|
profile,
|
|
|
|
team,
|
|
|
|
manager,
|
|
|
|
longitude,
|
|
|
|
latitude,
|
|
|
|
fcmId,
|
|
|
|
alternativeNumber,
|
|
|
|
firstName,
|
|
|
|
lastName,
|
|
|
|
city,
|
|
|
|
designation,
|
|
|
|
reportingManager,
|
|
|
|
departmentName,
|
|
|
|
zone,
|
|
|
|
createdBy,
|
|
|
|
updatedBy,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Save the new install to the database
|
|
|
|
await install.save();
|
|
|
|
|
|
|
|
reply.send({ message: 'Install Account Created Successfully' });
|
|
|
|
} catch (err) {
|
|
|
|
reply.status(500).send({ message: err.message });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.installationVerifyPhone = async (req, reply) => {
|
|
|
|
console.log("-------------------------------------------------");
|
|
|
|
try {
|
|
|
|
phone = req.body.phone;
|
|
|
|
phoneVerificationCode = req.body.phoneVerificationCode;
|
|
|
|
|
|
|
|
// check if user exists in the system. If user exists , display message that
|
|
|
|
// username is not available
|
|
|
|
console.log(
|
|
|
|
"this is the phone and verification code",
|
|
|
|
phone,
|
|
|
|
phoneVerificationCode
|
|
|
|
);
|
|
|
|
deliveryBoyExists = await Install.findOne({
|
|
|
|
phone: phone,
|
|
|
|
//phoneVerified: false,
|
|
|
|
phoneVerificationCode: phoneVerificationCode,
|
|
|
|
});
|
|
|
|
console.log(deliveryBoyExists);
|
|
|
|
if (deliveryBoyExists) {
|
|
|
|
// update the phoneVerified flag to true.
|
|
|
|
const filter = {
|
|
|
|
phone: phone,
|
|
|
|
phoneVerificationCode: phoneVerificationCode,
|
|
|
|
};
|
|
|
|
const update = { phoneVerified: true };
|
|
|
|
const doc = await Install.findOneAndUpdate(filter, update);
|
|
|
|
updatedDeliveryBoy = await Install.findOne({ phone: phone });
|
|
|
|
|
|
|
|
if (updatedDeliveryBoy.phoneVerified) {
|
|
|
|
loginObject = await supplierController.loginInstallation(req);
|
|
|
|
console.log("loginObject...", loginObject);
|
|
|
|
if (loginObject.same) {
|
|
|
|
const phoneVerified = loginObject.delivery.phoneVerified;
|
|
|
|
const oneTimePasswordSetFlag =
|
|
|
|
loginObject.delivery.oneTimePasswordSetFlag;
|
|
|
|
console.log(
|
|
|
|
"oneTimePasswordSetFlag is ......",
|
|
|
|
oneTimePasswordSetFlag,
|
|
|
|
typeof oneTimePasswordSetFlag,
|
|
|
|
typeof phoneVerified
|
|
|
|
);
|
|
|
|
if (!phoneVerified) {
|
|
|
|
reply.send({
|
|
|
|
simplydata: {
|
|
|
|
error: false,
|
|
|
|
phoneVerified: false,
|
|
|
|
|
|
|
|
phone: loginObject.delivery.phone,
|
|
|
|
oneTimePasswordSetFlag: oneTimePasswordSetFlag,
|
|
|
|
message: "Please Verify your phone number",
|
|
|
|
},
|
|
|
|
});
|
|
|
|
} else if (oneTimePasswordSetFlag) {
|
|
|
|
reply.send({
|
|
|
|
simplydata: {
|
|
|
|
error: false,
|
|
|
|
phoneVerified: phoneVerified,
|
|
|
|
phone: loginObject.delivery.phone,
|
|
|
|
oneTimePasswordSetFlag: true,
|
|
|
|
message: "Password must be reset",
|
|
|
|
},
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
{
|
|
|
|
name: loginObject.delivery.name,
|
|
|
|
},
|
|
|
|
//expiresIn: expressed in seconds or a string describing a time span zeit/ms. Eg: 60, "2 days", "10h", "7d".
|
|
|
|
//A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc),
|
|
|
|
//otherwise milliseconds unit is used by default ("120" is equal to "120ms").
|
|
|
|
{ expiresIn: "30d" }
|
|
|
|
);
|
|
|
|
console.log(token, "..token");
|
|
|
|
|
|
|
|
var d_id = loginObject.delivery._id;
|
|
|
|
|
|
|
|
console.log(d_id, "deliveryId");
|
|
|
|
var profilePicture = await ProfilePictureInstall.findOne({
|
|
|
|
installationId: d_id,
|
|
|
|
});
|
|
|
|
|
|
|
|
// request.session.set('supplierId', loginObject.supplier._id)
|
|
|
|
|
|
|
|
if (!profilePicture) {
|
|
|
|
reply.send({
|
|
|
|
simplydata: {
|
|
|
|
error: false,
|
|
|
|
apiversion: fastify.config.APIVERSION,
|
|
|
|
access_token: token,
|
|
|
|
|
|
|
|
phone: loginObject.delivery.phone,
|
|
|
|
installationId: loginObject.delivery.installationId,
|
|
|
|
name: loginObject.delivery.name,
|
|
|
|
address: loginObject.delivery.address,
|
|
|
|
phoneVerified: loginObject.delivery.phoneVerified,
|
|
|
|
oneTimePasswordSetFlag:
|
|
|
|
loginObject.delivery.oneTimePasswordSetFlag,
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (profilePicture) {
|
|
|
|
reply.send({
|
|
|
|
simplydata: {
|
|
|
|
error: false,
|
|
|
|
apiversion: fastify.config.APIVERSION,
|
|
|
|
access_token: token,
|
|
|
|
picture: profilePicture.picture,
|
|
|
|
phone: loginObject.delivery.phone,
|
|
|
|
installationId: loginObject.delivery.installationId,
|
|
|
|
|
|
|
|
name: loginObject.delivery.name,
|
|
|
|
address: loginObject.delivery.address,
|
|
|
|
phoneVerified: loginObject.delivery.phoneVerified,
|
|
|
|
oneTimePasswordSetFlag:
|
|
|
|
loginObject.delivery.oneTimePasswordSetFlag,
|
|
|
|
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
error = {
|
|
|
|
simplydata: {
|
|
|
|
error: true,
|
|
|
|
code: 400,
|
|
|
|
message: "Invalid Details",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
reply.send(error);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}else {
|
|
|
|
error = {
|
|
|
|
armintatankdata: {
|
|
|
|
error: true,
|
|
|
|
code: 10005,
|
|
|
|
message: "10005 - Verification code entered cannot be validated.",
|
|
|
|
},
|
|
|
|
};
|
|
|
|
req.body.regError = error;
|
|
|
|
reply.send(error);
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const generateStoreId = async () => {
|
|
|
|
const result = await Counter.findOneAndUpdate(
|
|
|
|
{ _id: 'store_id' },
|
|
|
|
{ $inc: { seq: 1 } },
|
|
|
|
{ upsert: true, new: true }
|
|
|
|
);
|
|
|
|
return result.seq;
|
|
|
|
};
|
|
|
|
const saltRounds = 10;
|
|
|
|
const generateSalesId = async () => {
|
|
|
|
const result = await Counter.findOneAndUpdate(
|
|
|
|
{ _id: 'sales_id' },
|
|
|
|
{ $inc: { seq: 1 } },
|
|
|
|
{ upsert: true, new: true }
|
|
|
|
);
|
|
|
|
return result.seq;
|
|
|
|
};
|
|
|
|
|
|
|
|
async function bcryptPassword(password) {
|
|
|
|
encryptedPwd = bcrypt.hash(password, saltRounds);
|
|
|
|
return encryptedPwd;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function bcryptComparePassword(pwd, encpassword) {
|
|
|
|
isSame = bcrypt.compare(pwd, encpassword);
|
|
|
|
return isSame;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.addStore = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
// Generate a unique store ID
|
|
|
|
const s_id = await generateStoreId();
|
|
|
|
const storeId = `AWST${s_id}`;
|
|
|
|
|
|
|
|
const {
|
|
|
|
storename,
|
|
|
|
phone,
|
|
|
|
zone,
|
|
|
|
departmentName,
|
|
|
|
designation,
|
|
|
|
reportingManager,
|
|
|
|
contactPersonName,
|
|
|
|
contactPersonPhone,
|
|
|
|
emails,
|
|
|
|
password,
|
|
|
|
description,
|
|
|
|
startingPrice,
|
|
|
|
longitude,
|
|
|
|
latitude,
|
|
|
|
fcmId,
|
|
|
|
isActive,
|
|
|
|
createdBy,
|
|
|
|
updatedBy,
|
|
|
|
profile = {}, // Default to an empty object to prevent errors
|
|
|
|
} = request.body;
|
|
|
|
|
|
|
|
const {
|
|
|
|
firstName = null,
|
|
|
|
lastName = null,
|
|
|
|
contactNumber = null,
|
|
|
|
alternativeContactNumber = null,
|
|
|
|
store_address = null,
|
|
|
|
city = null,
|
|
|
|
state = null,
|
|
|
|
zip = null,
|
|
|
|
country = null,
|
|
|
|
address1 = null,
|
|
|
|
address2 = null
|
|
|
|
} = profile; // Extract profile fields
|
|
|
|
|
|
|
|
// Check if the phone is already registered
|
|
|
|
const existingStore = await Store.findOne({ phone });
|
|
|
|
if (existingStore) {
|
|
|
|
return reply.status(400).send({ message: 'Phone is already registered' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the contact person phone is already registered
|
|
|
|
const existingContactPhone = await Store.findOne({ contactPersonPhone });
|
|
|
|
if (existingContactPhone) {
|
|
|
|
return reply.status(400).send({ message: 'Contact Person Phone is already registered' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Hash the password
|
|
|
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
|
|
|
|
|
|
// Create a new store document
|
|
|
|
const store = new Store({
|
|
|
|
storename,
|
|
|
|
phone,
|
|
|
|
zone,
|
|
|
|
departmentName,
|
|
|
|
designation,
|
|
|
|
reportingManager,
|
|
|
|
contactPersonName,
|
|
|
|
contactPersonPhone,
|
|
|
|
storeId,
|
|
|
|
emails,
|
|
|
|
services: { password: { bcrypt: hashedPassword } },
|
|
|
|
description,
|
|
|
|
startingPrice,
|
|
|
|
profile: {
|
|
|
|
store_address,
|
|
|
|
firstName,
|
|
|
|
lastName,
|
|
|
|
contactNumber,
|
|
|
|
alternativeContactNumber,
|
|
|
|
city,
|
|
|
|
state,
|
|
|
|
zip,
|
|
|
|
country,
|
|
|
|
address1,
|
|
|
|
address2
|
|
|
|
},
|
|
|
|
longitude,
|
|
|
|
latitude,
|
|
|
|
fcmId,
|
|
|
|
isActive: isActive ?? true, // Default to true if not provided
|
|
|
|
createdBy,
|
|
|
|
updatedBy,
|
|
|
|
});
|
|
|
|
|
|
|
|
// Save the store document
|
|
|
|
await store.save();
|
|
|
|
|
|
|
|
reply.send({ message: 'Store Account Created Successfully' });
|
|
|
|
} catch (err) {
|
|
|
|
reply.status(500).send({ message: err.message });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.addSales = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const s_id = await generateSalesId();
|
|
|
|
const sales_id = `AWSL${s_id}`;
|
|
|
|
|
|
|
|
const {
|
|
|
|
phone,
|
|
|
|
username,
|
|
|
|
emails,
|
|
|
|
password,
|
|
|
|
zone,
|
|
|
|
departmentName,
|
|
|
|
designation,
|
|
|
|
reportingManager,
|
|
|
|
profile,
|
|
|
|
createdBy,
|
|
|
|
updatedBy,
|
|
|
|
} = request.body;
|
|
|
|
|
|
|
|
const { firstName, lastName ,address,city,state,country,zip,address1,address2} = profile || {};
|
|
|
|
|
|
|
|
const existingStore = await Sales.findOne({ phone });
|
|
|
|
if (existingStore) {
|
|
|
|
return reply.status(400).send({ message: 'Phone is already registered' });
|
|
|
|
}
|
|
|
|
|
|
|
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
|
|
|
|
|
|
const store = new Sales({
|
|
|
|
salesId: sales_id,
|
|
|
|
username,
|
|
|
|
phone,
|
|
|
|
address,
|
|
|
|
emails,
|
|
|
|
zone,
|
|
|
|
departmentName,
|
|
|
|
designation,
|
|
|
|
reportingManager,
|
|
|
|
services: { password: { bcrypt: hashedPassword } },
|
|
|
|
profile: {
|
|
|
|
firstName,
|
|
|
|
lastName,
|
|
|
|
address,
|
|
|
|
city,
|
|
|
|
state,
|
|
|
|
country,
|
|
|
|
zip,
|
|
|
|
address1,
|
|
|
|
address2,
|
|
|
|
...profile,
|
|
|
|
},
|
|
|
|
createdBy,
|
|
|
|
updatedBy,
|
|
|
|
});
|
|
|
|
|
|
|
|
await store.save();
|
|
|
|
|
|
|
|
reply.send({ message: 'Account Created Successfully' });
|
|
|
|
} catch (err) {
|
|
|
|
reply.status(500).send({ message: err.message });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getallsales = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
await Sales.find()
|
|
|
|
.exec()
|
|
|
|
.then((docs) => {
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log(err);
|
|
|
|
reply.send({ error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getallstore = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
await Store.find()
|
|
|
|
.exec()
|
|
|
|
.then((docs) => {
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log(err);
|
|
|
|
reply.send({ error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.deleteUserInfo = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const salesId = req.params.salesId;
|
|
|
|
|
|
|
|
const sales = await Sales.findOneAndDelete({ salesId:salesId });
|
|
|
|
|
|
|
|
reply.send({ status_code: 200, message: 'Delete Sucessfully'});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
exports.deleteStoreInfo = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const storeId = req.params.storeId;
|
|
|
|
|
|
|
|
const store = await Store.findOneAndDelete({ storeId:storeId });
|
|
|
|
|
|
|
|
reply.send({ status_code: 200, message: 'Delete Sucessfully'});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.editSalesUser = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const { salesId } = request.params;
|
|
|
|
const {
|
|
|
|
username,
|
|
|
|
phone,
|
|
|
|
emails,
|
|
|
|
address,
|
|
|
|
profile,
|
|
|
|
zone,
|
|
|
|
reportingManager,
|
|
|
|
designation,
|
|
|
|
departmentName
|
|
|
|
} = request.body;
|
|
|
|
|
|
|
|
|
|
|
|
const existingSales = await Sales.findOne({ salesId });
|
|
|
|
if (!existingSales) {
|
|
|
|
return reply.status(404).send({ message: 'Sales user not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
const phoneExists = await Sales.findOne({ phone, salesId: { $ne: salesId } });
|
|
|
|
if (phoneExists) {
|
|
|
|
return reply.status(400).send({ message: 'Phone is already registered to another user' });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
existingSales.username = username || existingSales.username;
|
|
|
|
existingSales.phone = phone || existingSales.phone;
|
|
|
|
existingSales.emails = emails || existingSales.emails;
|
|
|
|
existingSales.zone = zone || existingSales.zone;
|
|
|
|
existingSales.reportingManager = reportingManager || existingSales.reportingManager;
|
|
|
|
existingSales.designation = designation || existingSales.designation;
|
|
|
|
existingSales.departmentName = departmentName || existingSales.departmentName;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (profile) {
|
|
|
|
existingSales.profile.firstName = profile.firstName || existingSales.profile.firstName;
|
|
|
|
existingSales.profile.lastName = profile.lastName || existingSales.profile.lastName;
|
|
|
|
existingSales.profile.address = profile.address || existingSales.profile.address;
|
|
|
|
existingSales.profile.city = profile.city || existingSales.profile.city;
|
|
|
|
existingSales.profile.state = profile.state || existingSales.profile.state;
|
|
|
|
existingSales.profile.country = profile.country || existingSales.profile.country;
|
|
|
|
existingSales.profile.zip = profile.zip || existingSales.profile.zip;
|
|
|
|
existingSales.profile.address1 = profile.address1 || existingSales.profile.address1;
|
|
|
|
existingSales.profile.address2 = profile.address2 || existingSales.profile.address2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (request.body.password) {
|
|
|
|
const hashedPassword = await bcrypt.hash(request.body.password, 10);
|
|
|
|
existingSales.services.password.bcrypt = hashedPassword;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await existingSales.save();
|
|
|
|
|
|
|
|
reply.send({ message: 'Sales user updated successfully' });
|
|
|
|
} catch (err) {
|
|
|
|
reply.status(500).send({ message: err.message });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.editStore = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = request.params;
|
|
|
|
const {
|
|
|
|
storename,
|
|
|
|
phone,
|
|
|
|
address,
|
|
|
|
address1,
|
|
|
|
address2,
|
|
|
|
emails,
|
|
|
|
profile,
|
|
|
|
alternativeNumber,
|
|
|
|
longitude,
|
|
|
|
latitude,
|
|
|
|
fcmId,
|
|
|
|
description,
|
|
|
|
startingPrice,
|
|
|
|
password,
|
|
|
|
contactPersonPhone,
|
|
|
|
zone,
|
|
|
|
reportingManager,
|
|
|
|
designation,
|
|
|
|
departmentName
|
|
|
|
} = request.body;
|
|
|
|
|
|
|
|
|
|
|
|
const existingStore = await Store.findOne({ storeId: storeId });
|
|
|
|
if (!existingStore) {
|
|
|
|
return reply.status(404).send({ message: 'Store not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const phoneExists = await Store.findOne({ phone, storeId: { $ne: storeId } });
|
|
|
|
if (phoneExists) {
|
|
|
|
return reply.status(400).send({ message: 'Phone is already registered to another store' });
|
|
|
|
}
|
|
|
|
|
|
|
|
existingStore.storename = storename || existingStore.storename;
|
|
|
|
existingStore.phone = phone || existingStore.phone;
|
|
|
|
existingStore.address = address || existingStore.address;
|
|
|
|
existingStore.address1 = address1 || existingStore.address1;
|
|
|
|
existingStore.address2 = address2 || existingStore.address2;
|
|
|
|
existingStore.emails = emails || existingStore.emails;
|
|
|
|
existingStore.alternativeNumber = alternativeNumber || existingStore.alternativeNumber;
|
|
|
|
existingStore.longitude = longitude || existingStore.longitude;
|
|
|
|
existingStore.latitude = latitude || existingStore.latitude;
|
|
|
|
existingStore.fcmId = fcmId || existingStore.fcmId;
|
|
|
|
existingStore.description = description || existingStore.description;
|
|
|
|
existingStore.startingPrice = startingPrice || existingStore.startingPrice;
|
|
|
|
existingStore.contactPersonPhone = contactPersonPhone || existingStore.contactPersonPhone;
|
|
|
|
existingStore.zone = zone || existingStore.zone;
|
|
|
|
existingStore.reportingManager = reportingManager || existingStore.reportingManager;
|
|
|
|
existingStore.designation = designation || existingStore.designation;
|
|
|
|
existingStore.departmentName = departmentName || existingStore.departmentName;
|
|
|
|
|
|
|
|
|
|
|
|
if (profile) {
|
|
|
|
existingStore.profile.firstName = profile.firstName || existingStore.profile.firstName;
|
|
|
|
existingStore.profile.lastName = profile.lastName || existingStore.profile.lastName;
|
|
|
|
existingStore.profile.contactNumber = profile.contactNumber || existingStore.profile.contactNumber;
|
|
|
|
existingStore.profile.alternativeContactNumber =
|
|
|
|
profile.alternativeContactNumber || existingStore.profile.alternativeContactNumber;
|
|
|
|
existingStore.profile.store_address = profile.store_address || existingStore.profile.store_address;
|
|
|
|
existingStore.profile.city = profile.city || existingStore.profile.city;
|
|
|
|
existingStore.profile.state = profile.state || existingStore.profile.state;
|
|
|
|
existingStore.profile.country = profile.country || existingStore.profile.country;
|
|
|
|
existingStore.profile.zip = profile.zip || existingStore.profile.zip;
|
|
|
|
existingStore.profile.address1 = profile.address1 || existingStore.profile.address1;
|
|
|
|
existingStore.profile.address2 = profile.address2 || existingStore.profile.address2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (password) {
|
|
|
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
|
|
existingStore.services.password.bcrypt = hashedPassword;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
await existingStore.save();
|
|
|
|
|
|
|
|
reply.send({ message: 'Store updated successfully' });
|
|
|
|
} catch (err) {
|
|
|
|
reply.status(500).send({ message: err.message });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getAllUsers = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const users = await Install.find({});
|
|
|
|
reply.send(users);
|
|
|
|
} catch (error) {
|
|
|
|
reply.status(500).send({ message: "Error retrieving users" });
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
exports.deleteUserByInstallationId = async (request, reply) => {
|
|
|
|
const { installationId } = request.params;
|
|
|
|
try {
|
|
|
|
await Install.findOneAndDelete({ installationId });
|
|
|
|
reply.send({ message: "User deleted successfully" });
|
|
|
|
} catch (error) {
|
|
|
|
reply.status(500).send({ message: "Error deleting user" });
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
exports.updateUserByInstallationId = async (request, reply) => {
|
|
|
|
const { installationId } = request.params;
|
|
|
|
const updatedData = request.body;
|
|
|
|
try {
|
|
|
|
await Install.findOneAndUpdate({ installationId }, updatedData, { new: true });
|
|
|
|
reply.send({ message: "User updated successfully" });
|
|
|
|
} catch (error) {
|
|
|
|
reply.status(500).send({ message: "Error updating user" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const generatewaterlevelheightsensorId = async () => {
|
|
|
|
const result = await Counter.findOneAndUpdate(
|
|
|
|
{ _id: 'waterlevelheightsensor_id' },
|
|
|
|
{ $inc: { seq: 1 } },
|
|
|
|
{ upsert: true, new: true }
|
|
|
|
);
|
|
|
|
return result.seq;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const generatewaterlevelsensorId = async () => {
|
|
|
|
const result = await Counter.findOneAndUpdate(
|
|
|
|
{ _id: 'waterlevelsensor_id' },
|
|
|
|
{ $inc: { seq: 1 } },
|
|
|
|
{ upsert: true, new: true }
|
|
|
|
);
|
|
|
|
return result.seq;
|
|
|
|
};
|
|
|
|
|
|
|
|
const generatewaterlevelslavesensorId = async () => {
|
|
|
|
const result = await Counter.findOneAndUpdate(
|
|
|
|
{ _id: 'waterlevelslavesensor_id' },
|
|
|
|
{ $inc: { seq: 1 } },
|
|
|
|
{ upsert: true, new: true }
|
|
|
|
);
|
|
|
|
return result.seq;
|
|
|
|
};
|
|
|
|
|
|
|
|
const moment = require('moment');
|
|
|
|
// exports.createwaterlevelSensor = async (req, reply) => {
|
|
|
|
// try {
|
|
|
|
// const storeId = req.params.storeId
|
|
|
|
// const { hardwareId,hardwareId_company, type, indate } = req.body;
|
|
|
|
// var mater_seq_id = await generatewaterlevelsensorId();
|
|
|
|
// const date = moment().format('MM-DD');
|
|
|
|
// const prefix = 'AS' + date + 'MALOV1';
|
|
|
|
// var masterId = `${prefix}${mater_seq_id}`;
|
|
|
|
// const newSensor = new WaterLeverSensor({
|
|
|
|
// storeId,
|
|
|
|
// hardwareId,
|
|
|
|
// masterId,
|
|
|
|
// type,
|
|
|
|
// indate
|
|
|
|
// });
|
|
|
|
// const savedSensor = await newSensor.save();
|
|
|
|
// reply.code(200).send(savedSensor);
|
|
|
|
// } catch (err) {
|
|
|
|
// reply.code(500).send(err);
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// exports.editWaterLevelSensor = async (req, reply) => {
|
|
|
|
// try {
|
|
|
|
// const { storeId } = req.params;
|
|
|
|
// const updates = req.body;
|
|
|
|
|
|
|
|
// const updatedSensor = await WaterLeverSensor.findOneAndUpdate(
|
|
|
|
// { storeId:storeId,hardwareId: req.body.hardwareId },
|
|
|
|
// updates,
|
|
|
|
// { new: true }
|
|
|
|
// );
|
|
|
|
|
|
|
|
// if (!updatedSensor) {
|
|
|
|
// reply.code(404).send({ message: "Sensor not found" });
|
|
|
|
// } else {
|
|
|
|
// reply.code(200).send(updatedSensor);
|
|
|
|
// }
|
|
|
|
// } catch (err) {
|
|
|
|
// reply.code(500).send(err);
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
exports.deleteWaterLevelSensor = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = req.params;
|
|
|
|
|
|
|
|
const deletedSensor = await WaterLeverSensor.findOneAndDelete(
|
|
|
|
{ storeId,hardwareId: req.body.hardwareId }
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!deletedSensor) {
|
|
|
|
reply.code(404).send({ message: "Sensor not found" });
|
|
|
|
} else {
|
|
|
|
reply.code(200).send({ message: "Sensor deleted successfully" });
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
reply.code(500).send(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.installwaterlevelSensor = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = request.params;
|
|
|
|
const updateData = request.body;
|
|
|
|
|
|
|
|
// Find the document by hardwareId and update it with the fields received in the body
|
|
|
|
const updatedSensor = await WaterLeverSensor.findOneAndUpdate(
|
|
|
|
{ storeId:storeId,hardwareId: request.body.hardwareId, },
|
|
|
|
{ $set: updateData },
|
|
|
|
{ new: true } // Return the updated document
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedSensor) {
|
|
|
|
return reply.status(404).send({ error: 'Sensor not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.status(200).send(updatedSensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
return reply.status(500).send({ error: 'An error occurred while updating the sensor' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// exports.qccheckwaterlevelSensor = async (request, reply) => {
|
|
|
|
// try {
|
|
|
|
// const { hardwareId } = request.params;
|
|
|
|
// const updateData = request.body;
|
|
|
|
|
|
|
|
// // Find the document by hardwareId and update it with the fields received in the body
|
|
|
|
// const updatedSensor = await WaterLeverSensor.findOneAndUpdate(
|
|
|
|
// { hardwareId: hardwareId },
|
|
|
|
// { $set: updateData },
|
|
|
|
// { new: true } // Return the updated document
|
|
|
|
// );
|
|
|
|
|
|
|
|
// if (!updatedSensor) {
|
|
|
|
// return reply.status(404).send({ error: 'Sensor not found' });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return reply.status(200).send(updatedSensor);
|
|
|
|
// } catch (error) {
|
|
|
|
// console.error(error);
|
|
|
|
// return reply.status(500).send({ error: 'An error occurred while updating the sensor' });
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
exports.getHardware = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
await WaterLeverSensor.find({storeId: req.params.storeId})
|
|
|
|
.exec()
|
|
|
|
.then((docs) => {
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log(err);
|
|
|
|
reply.send({ error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getHardwaremotorswitch = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
await MotorSwitchSensor.find({storeId: req.params.storeId})
|
|
|
|
.exec()
|
|
|
|
.then((docs) => {
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log(err);
|
|
|
|
reply.send({ error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getHardwareqc = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
await WaterLeverSensor.find({storeId: req.params.storeId,hardwareId:req.body.hardwareId})
|
|
|
|
.exec()
|
|
|
|
.then((docs) => {
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log(err);
|
|
|
|
reply.send({ error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.addSlave = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const hardwareId = req.params.hardwareId;
|
|
|
|
const { tankhardwareId, type, indate, hardwareId_company } = req.body;
|
|
|
|
|
|
|
|
// Find the main hardware by hardwareId
|
|
|
|
const mainHardware = await WaterLeverSensor.findOne({ hardwareId });
|
|
|
|
|
|
|
|
if (!mainHardware) {
|
|
|
|
reply.code(404).send({ message: "Main hardware not found" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if the slave's hardwareId already exists
|
|
|
|
const existingSlave = mainHardware.slaves.tankhardware.find(slave => slave.tankhardwareId === tankhardwareId);
|
|
|
|
|
|
|
|
if (existingSlave) {
|
|
|
|
reply.code(400).send({ message: "Slave hardware ID already exists for this main hardware" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var slave_seq_id = await generatewaterlevelslavesensorId();
|
|
|
|
const date = moment().format('MM-DD');
|
|
|
|
const prefix = 'AS' + date + 'SLAOV1';
|
|
|
|
var slaveId = `${prefix}${slave_seq_id}`;
|
|
|
|
// Create new slave
|
|
|
|
const newSlave = {
|
|
|
|
tankhardwareId,
|
|
|
|
slaveId: slaveId,
|
|
|
|
type,
|
|
|
|
indate,
|
|
|
|
hardwareId_company
|
|
|
|
};
|
|
|
|
|
|
|
|
// Add the new slave to the main hardware's slaves array
|
|
|
|
mainHardware.slaves.tankhardware.push(newSlave);
|
|
|
|
|
|
|
|
// Save the updated main hardware
|
|
|
|
const updatedHardware = await mainHardware.save();
|
|
|
|
|
|
|
|
reply.code(200).send(updatedHardware);
|
|
|
|
} catch (err) {
|
|
|
|
reply.code(500).send(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// exports.editSlave = async (req, reply) => {
|
|
|
|
// try {
|
|
|
|
// const { hardwareId } = req.params;
|
|
|
|
// const updates = req.body;
|
|
|
|
|
|
|
|
// const mainHardware = await WaterLeverSensor.findOne({ hardwareId });
|
|
|
|
|
|
|
|
// if (!mainHardware) {
|
|
|
|
// reply.code(404).send({ message: "Main hardware not found" });
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// const slaveIndex = mainHardware.slaves.tankhardware.findIndex(
|
|
|
|
// (slave) => slave.tankhardwareId === req.body.tankhardwareId
|
|
|
|
// );
|
|
|
|
|
|
|
|
// if (slaveIndex === -1) {
|
|
|
|
// reply.code(404).send({ message: "Slave not found" });
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// mainHardware.slaves.tankhardware[slaveIndex] = {
|
|
|
|
// ...mainHardware.slaves.tankhardware[slaveIndex],
|
|
|
|
// ...updates,
|
|
|
|
// };
|
|
|
|
|
|
|
|
// const updatedHardware = await mainHardware.save();
|
|
|
|
|
|
|
|
// reply.code(200).send(updatedHardware);
|
|
|
|
// } catch (err) {
|
|
|
|
// reply.code(500).send(err);
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
exports.deleteSlave = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { hardwareId } = req.params;
|
|
|
|
|
|
|
|
const mainHardware = await WaterLeverSensor.findOne({ hardwareId });
|
|
|
|
|
|
|
|
if (!mainHardware) {
|
|
|
|
reply.code(404).send({ message: "Main hardware not found" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const slaveIndex = mainHardware.slaves.tankhardware.findIndex(
|
|
|
|
(slave) => slave.tankhardwareId === req.body.tankhardwareId
|
|
|
|
);
|
|
|
|
|
|
|
|
if (slaveIndex === -1) {
|
|
|
|
reply.code(404).send({ message: "Slave not found" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mainHardware.slaves.tankhardware.splice(slaveIndex, 1);
|
|
|
|
|
|
|
|
const updatedHardware = await mainHardware.save();
|
|
|
|
|
|
|
|
reply.code(200).send(updatedHardware);
|
|
|
|
} catch (err) {
|
|
|
|
reply.code(500).send(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.qccheckwaterlevelSensorSlave = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = request.params;
|
|
|
|
const updateData = request.body;
|
|
|
|
|
|
|
|
// Find the document by storeId and tankhardwareId, and update the corresponding slave
|
|
|
|
const updatedSensor = await WaterLeverSensor.findOneAndUpdate(
|
|
|
|
{
|
|
|
|
storeId: storeId,
|
|
|
|
hardwareId:request.body.hardwareId,
|
|
|
|
"slaves.tankhardware.tankhardwareId": request.body.tankhardwareId
|
|
|
|
},
|
|
|
|
{
|
|
|
|
$set: {
|
|
|
|
"slaves.tankhardware.$.qccheck": updateData.qccheck,
|
|
|
|
"slaves.tankhardware.$.qccheckdate": updateData.qccheckdate,
|
|
|
|
"slaves.tankhardware.$.qcby": updateData.qcby,
|
|
|
|
"slaves.tankhardware.$.comment": updateData.comment,
|
|
|
|
"slaves.tankhardware.$.outforrepairdate": updateData.outforrepairdate,
|
|
|
|
"slaves.tankhardware.$.sendto": updateData.sendto,
|
|
|
|
"slaves.tankhardware.$.repairfeedback": updateData.repairfeedback
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{ new: true } // Return the updated document
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedSensor) {
|
|
|
|
return reply.status(404).send({ error: 'Slave not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.status(200).send(updatedSensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
return reply.status(500).send({ error: 'An error occurred while updating the slave' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.installwaterlevelSensorSlave = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = request.params;
|
|
|
|
const { hardwareId, tankhardwareId, dateofinstallation, customerId, installedby } = request.body;
|
|
|
|
|
|
|
|
// Find the document by storeId and hardwareId, then update the specific slave with tankhardwareId
|
|
|
|
const updatedSensor = await WaterLeverSensor.findOneAndUpdate(
|
|
|
|
{
|
|
|
|
storeId: storeId,
|
|
|
|
hardwareId: hardwareId,
|
|
|
|
"slaves.tankhardware.tankhardwareId": tankhardwareId
|
|
|
|
},
|
|
|
|
{
|
|
|
|
$set: {
|
|
|
|
"slaves.tankhardware.$.dateofinstallation": dateofinstallation,
|
|
|
|
"slaves.tankhardware.$.customerId": customerId,
|
|
|
|
"slaves.tankhardware.$.installedby": installedby
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{ new: true } // Return the updated document
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedSensor) {
|
|
|
|
return reply.status(404).send({ error: 'Sensor or Slave not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.status(200).send(updatedSensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
return reply.status(500).send({ error: 'An error occurred while installing the sensor' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getHardwareqcslave = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = req.params;
|
|
|
|
const { hardwareId, tankhardwareId } = req.body;
|
|
|
|
|
|
|
|
let query;
|
|
|
|
if (tankhardwareId) {
|
|
|
|
// If tankhardwareId is provided, query for the specific slave
|
|
|
|
query = {
|
|
|
|
storeId: storeId,
|
|
|
|
hardwareId: hardwareId,
|
|
|
|
"slaves.tankhardware.tankhardwareId": tankhardwareId,
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
// Otherwise, query for the main hardware
|
|
|
|
query = {
|
|
|
|
storeId: storeId,
|
|
|
|
hardwareId: hardwareId,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
const docs = await WaterLeverSensor.find(query).exec();
|
|
|
|
|
|
|
|
if (docs.length === 0) {
|
|
|
|
return reply.status(404).send({ error: 'No hardware found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
} catch (err) {
|
|
|
|
console.error(err);
|
|
|
|
reply.status(500).send({ error: 'An error occurred while retrieving the hardware QC data' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.createmotorswitchSensor = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const storeId = req.params.storeId
|
|
|
|
const { motorId, type, indate } = req.body;
|
|
|
|
var mater_seq_id = await generatewaterlevelsensorId();
|
|
|
|
const date = moment().format('MM-DD');
|
|
|
|
const prefix = 'AS' + date + 'PSV1';
|
|
|
|
var masterId = `${prefix}${mater_seq_id}`;
|
|
|
|
const newSensor = new MotorSwitchSensor({
|
|
|
|
storeId,
|
|
|
|
motorId,
|
|
|
|
masterId,
|
|
|
|
type,
|
|
|
|
indate
|
|
|
|
});
|
|
|
|
const savedSensor = await newSensor.save();
|
|
|
|
reply.code(200).send(savedSensor);
|
|
|
|
} catch (err) {
|
|
|
|
reply.code(500).send(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.qccheckmotorswitch = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const { motorId } = request.params;
|
|
|
|
const updateData = request.body;
|
|
|
|
|
|
|
|
// Find the document by hardwareId and update it with the fields received in the body
|
|
|
|
const updatedSensor = await MotorSwitchSensor.findOneAndUpdate(
|
|
|
|
{ motorId: motorId },
|
|
|
|
{ $set: updateData },
|
|
|
|
{ new: true } // Return the updated document
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedSensor) {
|
|
|
|
return reply.status(404).send({ error: 'Sensor not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.status(200).send(updatedSensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
return reply.status(500).send({ error: 'An error occurred while updating the sensor' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.installmotorswitch = async (request, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = request.params;
|
|
|
|
const updateData = request.body;
|
|
|
|
|
|
|
|
// Find the document by hardwareId and update it with the fields received in the body
|
|
|
|
const updatedSensor = await MotorSwitchSensor.findOneAndUpdate(
|
|
|
|
{ storeId:storeId,motorId: request.body.motorId, },
|
|
|
|
{ $set: updateData },
|
|
|
|
{ new: true } // Return the updated document
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedSensor) {
|
|
|
|
return reply.status(404).send({ error: 'Sensor not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.status(200).send(updatedSensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
return reply.status(500).send({ error: 'An error occurred while updating the sensor' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.generateHardwareMasterId = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const storeId = req.params.storeId
|
|
|
|
const { from, to, type, quantity } = req.body;
|
|
|
|
const sensorType = type.toLowerCase();
|
|
|
|
const fromInt = parseInt(from, 10);
|
|
|
|
const toInt = parseInt(to, 10);
|
|
|
|
|
|
|
|
if (isNaN(fromInt) || isNaN(toInt) || fromInt > toInt) {
|
|
|
|
return reply.code(400).send({ message: 'Invalid from/to values' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch pending sensors of the given type and storeId whose hardwareId is null
|
|
|
|
const pendingSensors = await Insensors.find({ status: 'pending', type: sensorType, storeId, hardwareId: null });
|
|
|
|
|
|
|
|
if (!pendingSensors.length) {
|
|
|
|
return reply.code(404).send({ message: 'No pending sensors found for the given type and storeId' });
|
|
|
|
}
|
|
|
|
|
|
|
|
if (quantity > pendingSensors.length) {
|
|
|
|
return reply.code(400).send({ message: `Available quantity is less than requested: ${pendingSensors.length} available.` });
|
|
|
|
}
|
|
|
|
|
|
|
|
let hardwareIdSequence = fromInt;
|
|
|
|
const date = moment().format('MM-DD');
|
|
|
|
|
|
|
|
for (let i = 0; i < quantity && i < pendingSensors.length; i++) {
|
|
|
|
let sensor = pendingSensors[i];
|
|
|
|
if (hardwareIdSequence > toInt) break;
|
|
|
|
|
|
|
|
sensor.hardwareId = hardwareIdSequence.toString().padStart(8, '0');
|
|
|
|
|
|
|
|
let mater_seq_id;
|
|
|
|
if (sensorType === 'master') {
|
|
|
|
mater_seq_id = await generatewaterlevelsensorId();
|
|
|
|
sensor.masterId = `AS${date}MALOV1${mater_seq_id}`;
|
|
|
|
} else if (sensorType === 'slave') {
|
|
|
|
mater_seq_id = await generatewaterlevelslavesensorId();
|
|
|
|
sensor.masterId = `AS${date}SLLOV1${mater_seq_id}`;
|
|
|
|
} else if (sensorType === 'sensor') {
|
|
|
|
mater_seq_id = await generatewaterlevelheightsensorId();
|
|
|
|
sensor.masterId = `AS${date}SELOV1${mater_seq_id}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
await sensor.save(); // Save updated sensor in the database
|
|
|
|
hardwareIdSequence++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.code(200).send({ message: 'HardwareId and MasterId assigned successfully' });
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error generating IDs:', error);
|
|
|
|
return reply.code(500).send({ message: 'Internal Server Error' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getSensorByHardwareId = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
|
|
|
|
const { storeId } = req.params;
|
|
|
|
const { hardwareId } = req.body;
|
|
|
|
|
|
|
|
if (!hardwareId) {
|
|
|
|
return reply.code(400).send({ message: 'hardwareId is required' });
|
|
|
|
}
|
|
|
|
|
|
|
|
const sensor = await Insensors.findOne({ storeId, hardwareId });
|
|
|
|
|
|
|
|
if (!sensor) {
|
|
|
|
return reply.code(404).send({ message: 'Sensor not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.code(200).send(sensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error fetching sensor by hardwareId:', error);
|
|
|
|
return reply.code(500).send({ message: 'Internal Server Error' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.updateSensorById = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { _id } = req.params;
|
|
|
|
let updateData = req.body;
|
|
|
|
|
|
|
|
const allowedFields = ["model", "type", "hardwareId_company", "hardwareId","masterId"];
|
|
|
|
|
|
|
|
// Filter out unwanted fields and convert type to lowercase if present
|
|
|
|
const filteredUpdateData = Object.keys(updateData)
|
|
|
|
.filter((key) => allowedFields.includes(key))
|
|
|
|
.reduce((obj, key) => {
|
|
|
|
obj[key] = key === "type" ? updateData[key].toLowerCase() : updateData[key];
|
|
|
|
return obj;
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
const updatedSensor = await Insensors.findByIdAndUpdate(_id, filteredUpdateData, { new: true });
|
|
|
|
|
|
|
|
if (!updatedSensor) {
|
|
|
|
return reply.code(404).send({ message: "Sensor not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.code(200).send(updatedSensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error updating sensor:", error);
|
|
|
|
return reply.code(500).send({ message: "Internal Server Error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.deleteSensorById = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { _id } = req.params;
|
|
|
|
|
|
|
|
const deletedSensor = await Insensors.findByIdAndDelete(_id);
|
|
|
|
|
|
|
|
if (!deletedSensor) {
|
|
|
|
return reply.code(404).send({ message: "Sensor not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.code(200).send({ message: "Sensor deleted successfully" });
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error deleting sensor:", error);
|
|
|
|
return reply.code(500).send({ message: "Internal Server Error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.updateSensorQC = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { hardwareId } = req.params;
|
|
|
|
let updateData = req.body;
|
|
|
|
|
|
|
|
const allowedFields = ['qccheck', 'qcby', 'comment', 'status', 'quality_check_details'];
|
|
|
|
|
|
|
|
// Filter only allowed fields
|
|
|
|
const filteredUpdateData = Object.keys(updateData)
|
|
|
|
.filter((key) => allowedFields.includes(key))
|
|
|
|
.reduce((obj, key) => {
|
|
|
|
obj[key] = updateData[key];
|
|
|
|
return obj;
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
// Ensure qccheck is handled properly
|
|
|
|
if (filteredUpdateData.qccheck) {
|
|
|
|
const qccheckLower = filteredUpdateData.qccheck.toLowerCase();
|
|
|
|
filteredUpdateData.status = qccheckLower === 'pass' ? 'available' : 'qcfailed';
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update qccheckdate with the current date in "DD-MMM-YYYY - HH:MM" format
|
|
|
|
filteredUpdateData.qccheckdate = moment().format('DD-MMM-YYYY - HH:mm');
|
|
|
|
|
|
|
|
// Find the sensor by ID
|
|
|
|
const updatedSensor = await Insensors.findOneAndUpdate(
|
|
|
|
{ hardwareId }, // correct query filter
|
|
|
|
filteredUpdateData,
|
|
|
|
{ new: true }
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedSensor) {
|
|
|
|
return reply.code(409).send({ message: 'Sensor not found' });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update stock based on QC result
|
|
|
|
const stockRecord = await SensorStock.findOne({ storeId: updatedSensor.storeId, type: updatedSensor.type });
|
|
|
|
|
|
|
|
if (stockRecord) {
|
|
|
|
if (filteredUpdateData.qccheck && filteredUpdateData.qccheck.toLowerCase() === 'ok') {
|
|
|
|
// If QC is "ok", move 1 from total_count_before_qc to total_available
|
|
|
|
await SensorStock.updateOne(
|
|
|
|
{ storeId: updatedSensor.storeId, type: updatedSensor.type },
|
|
|
|
{ $inc: { total_count_before_qc: -1, total_available: 1 } }
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// If QC is failed, move 1 from total_count_before_qc to total_repair
|
|
|
|
await SensorStock.updateOne(
|
|
|
|
{ storeId: updatedSensor.storeId, type: updatedSensor.type },
|
|
|
|
{ $inc: { total_count_before_qc: -1, total_repair: 1 } }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.code(200).send(updatedSensor);
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error updating QC fields:', error);
|
|
|
|
return reply.code(500).send({ message: 'Internal Server Error' });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getSensorsByStatus = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId } = req.params;
|
|
|
|
|
|
|
|
const statuses = ["pending", "available", "rejected","blocked"];
|
|
|
|
let result = {};
|
|
|
|
|
|
|
|
for (const status of statuses) {
|
|
|
|
result[status] = await Insensors.find({ storeId, status });
|
|
|
|
}
|
|
|
|
const sensorStock = await SensorStock.find({ storeId }).lean();
|
|
|
|
return reply.code(200).send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Sensors and stock fetched successfully",
|
|
|
|
data: {
|
|
|
|
sensors: result,
|
|
|
|
stock: sensorStock
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error fetching sensors:", error);
|
|
|
|
return reply.code(500).send({ message: "Internal Server Error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getpumpswitchqc = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
await MotorSwitchSensor.find({storeId: req.params.storeId,motorId:req.body.motorId})
|
|
|
|
.exec()
|
|
|
|
.then((docs) => {
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log(err);
|
|
|
|
reply.send({ error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const generateBatchNo = (type, hardwareIdCompany) => {
|
|
|
|
const date = new Date();
|
|
|
|
const ddmmyy = `${date.getDate().toString().padStart(2, '0')}${(date.getMonth() + 1).toString().padStart(2, '0')}${date.getFullYear().toString().slice(-2)}`;
|
|
|
|
const companyPrefix = hardwareIdCompany.slice(0, 2).toUpperCase();
|
|
|
|
const randomNumbers = Math.floor(100 + Math.random() * 900).toString(); // 3 random digits
|
|
|
|
if (type === 'SENSOR') {
|
|
|
|
return `SN${ddmmyy}${companyPrefix}${randomNumbers}`;
|
|
|
|
}
|
|
|
|
if (type === 'SLAVE') {
|
|
|
|
return `SL${ddmmyy}${companyPrefix}${randomNumbers}`;
|
|
|
|
}
|
|
|
|
if (type === 'MASTER') {
|
|
|
|
return `MA${ddmmyy}${companyPrefix}${randomNumbers}`;
|
|
|
|
}
|
|
|
|
if (type === 'MOTOR_SWITCH') {
|
|
|
|
return `MS${ddmmyy}${companyPrefix}${randomNumbers}`;
|
|
|
|
}
|
|
|
|
// Add other type conditions if needed
|
|
|
|
return null;
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.createSensor = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const storeId = req.params.storeId;
|
|
|
|
const { indate, batchno, hardwareId_company, quantity, model, type } = req.body;
|
|
|
|
const sensorType = type.toLowerCase();
|
|
|
|
let finalBatchNo = batchno;
|
|
|
|
|
|
|
|
// Generate unique batch number if 'New' is received
|
|
|
|
if (batchno === "New") {
|
|
|
|
let isUnique = false;
|
|
|
|
while (!isUnique) {
|
|
|
|
finalBatchNo = generateBatchNo(type, hardwareId_company);
|
|
|
|
const existingBatchNo = await Insensors.findOne({ batchno: finalBatchNo });
|
|
|
|
if (!existingBatchNo) {
|
|
|
|
isUnique = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let entries = [];
|
|
|
|
for (let i = 0; i < quantity; i++) {
|
|
|
|
entries.push({
|
|
|
|
storeId,
|
|
|
|
model,
|
|
|
|
batchno: finalBatchNo,
|
|
|
|
type: sensorType,
|
|
|
|
indate,
|
|
|
|
hardwareId_company,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert new sensors into Insensors collection
|
|
|
|
const savedSensors = await Insensors.insertMany(entries);
|
|
|
|
|
|
|
|
// Update stock information in SensorStock
|
|
|
|
const stockRecord = await SensorStock.findOne({ storeId, type: sensorType });
|
|
|
|
|
|
|
|
if (stockRecord) {
|
|
|
|
// If stock record exists, update total_count
|
|
|
|
await SensorStock.updateOne(
|
|
|
|
{ storeId, type: sensorType },
|
|
|
|
{ $inc: { total_count: quantity, total_count_before_qc: quantity } }
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
// If no stock record exists, create a new one
|
|
|
|
await SensorStock.create({
|
|
|
|
storeId,
|
|
|
|
type: sensorType,
|
|
|
|
total_count: quantity,
|
|
|
|
total_available: 0,
|
|
|
|
total_blocked: 0,
|
|
|
|
total_repair: 0,
|
|
|
|
total_installed: 0,
|
|
|
|
total_count_before_qc:quantity
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
reply.code(200).send(savedSensors);
|
|
|
|
} catch (err) {
|
|
|
|
reply.code(500).send(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getbatchnumbers = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { storeId, type } = req.params;
|
|
|
|
|
|
|
|
let prefix = "";
|
|
|
|
switch (type.toUpperCase()) {
|
|
|
|
case "SLAVE":
|
|
|
|
prefix = "SL";
|
|
|
|
break;
|
|
|
|
case "MASTER":
|
|
|
|
prefix = "MA";
|
|
|
|
break;
|
|
|
|
case "SENSOR":
|
|
|
|
prefix = "SN";
|
|
|
|
break;
|
|
|
|
case "MOTOR_SWITCH":
|
|
|
|
prefix = "MS";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
reply.send({ status_code: 400, message: "Invalid type" });
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
await Insensors.distinct('batchno', {
|
|
|
|
storeId: storeId,
|
|
|
|
batchno: { $regex: `^${prefix}` },
|
|
|
|
})
|
|
|
|
.then((batchNumbers) => {
|
|
|
|
reply.send({ status_code: 200, data: batchNumbers, count: batchNumbers.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.error(err);
|
|
|
|
reply.send({ status_code: 500, error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
console.error(err);
|
|
|
|
reply.send({ status_code: 500, error: err });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getbatquotationsforparticularstore = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const storeId = req.params.storeId;
|
|
|
|
|
|
|
|
|
|
|
|
let query = { storeId: storeId };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch data based on the query
|
|
|
|
const result = await SensorQuotation.find(query);
|
|
|
|
|
|
|
|
if (!result ) {
|
|
|
|
return reply.send({ status_code: 404, error: "not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
reply.send({ status_code: 200, data: result });
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getiots = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const storeId = req.params.storeId;
|
|
|
|
let type = req.params.type ? req.params.type.toLowerCase() : null; // Convert type to uppercase
|
|
|
|
|
|
|
|
let query = { storeId: storeId };
|
|
|
|
|
|
|
|
if (type !== "ALL") {
|
|
|
|
query.type = type;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch data based on the query
|
|
|
|
const result = await Insensors.find(query);
|
|
|
|
|
|
|
|
if (!result ) {
|
|
|
|
return reply.send({ status_code: 404, error: "not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
reply.send({ status_code: 200, data: result });
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getusersofParticularInstaller = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
await User.find({installationId: req.query.InstallerId})
|
|
|
|
.exec()
|
|
|
|
.then((docs) => {
|
|
|
|
reply.send({ status_code: 200, data: docs, count: docs.length });
|
|
|
|
})
|
|
|
|
.catch((err) => {
|
|
|
|
console.log(err);
|
|
|
|
reply.send({ error: err });
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const dayjs = require('dayjs');
|
|
|
|
const utc = require('dayjs/plugin/utc');
|
|
|
|
const timezone = require('dayjs/plugin/timezone');
|
|
|
|
|
|
|
|
// Extend dayjs with UTC and timezone plugins
|
|
|
|
dayjs.extend(utc);
|
|
|
|
dayjs.extend(timezone);
|
|
|
|
|
|
|
|
exports.createquotationforSensor = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const i_id = await generatequatationId();
|
|
|
|
const quatationId = `AWQU${i_id}`;
|
|
|
|
const { surveyId } = req.params;
|
|
|
|
const { customerId, masters, slaves, sensors, motor_switches, electricals,master_connections } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
// Format electricals field
|
|
|
|
const formattedElectricals = electricals.map((item) => ({
|
|
|
|
type: item.type || "",
|
|
|
|
wire: item.wire || "",
|
|
|
|
switch: item.switch || "",
|
|
|
|
text: item.text || "",
|
|
|
|
}));
|
|
|
|
const formattedMasterDetails = master_connections.map((item) => ({
|
|
|
|
master_name: item.master_name || "",
|
|
|
|
slaves: item.slaves || "",
|
|
|
|
location: item.location || "",
|
|
|
|
googleLocation: item.googleLocation || "",
|
|
|
|
latitude: item.latitude || "",
|
|
|
|
longitude: item.longitude || "",
|
|
|
|
tanks: Array.isArray(item.tanks)
|
|
|
|
? item.tanks.map(tank => ({
|
|
|
|
tankName: tank.tankName || "",
|
|
|
|
tankLocation: tank.tankLocation || ""
|
|
|
|
}))
|
|
|
|
: [],
|
|
|
|
motor_switches: Array.isArray(item.motor_switches)
|
|
|
|
? item.motor_switches.map(motor_switch => ({
|
|
|
|
|
|
|
|
from_tank: motor_switch.from_tank || "",
|
|
|
|
from_location: motor_switch.from_location || "",
|
|
|
|
to_tank: motor_switch.to_tank || "",
|
|
|
|
to_location: motor_switch.to_location || "",
|
|
|
|
|
|
|
|
}))
|
|
|
|
: [],
|
|
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
// Fetch pricing data from Iotprice database
|
|
|
|
const getPrice = async (name, type) => {
|
|
|
|
const priceData = await Iotprice.findOne({ name, type });
|
|
|
|
return priceData ? priceData.cost : 0; // Default to 0 if not found
|
|
|
|
};
|
|
|
|
|
|
|
|
// Calculate price for masters, slaves, sensors, motor switches
|
|
|
|
const masterPrice = await getPrice("master", "master");
|
|
|
|
const slavePrice = await getPrice("slave", "slave");
|
|
|
|
const sensorPrice = await getPrice("sensor", "sensor");
|
|
|
|
const motorSwitchPrice = await getPrice("motor_switch", "motor_switches");
|
|
|
|
|
|
|
|
// Calculate price for electricals
|
|
|
|
let electricalPrice = 0;
|
|
|
|
for (const item of formattedElectricals) {
|
|
|
|
if (item.type === "cable") {
|
|
|
|
electricalPrice += await getPrice("cable", item.wire); // wire field is type
|
|
|
|
} else if (item.type === "switch") {
|
|
|
|
electricalPrice += await getPrice("switch", item.switch); // switch field is type
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate total estimation price
|
|
|
|
const totalEstimatedPrice = masterPrice + slavePrice + sensorPrice + motorSwitchPrice + electricalPrice;
|
|
|
|
|
|
|
|
// Format current date and time in IST
|
|
|
|
const formattedDateTime = dayjs().tz("Asia/Kolkata").format('DD-MMM-YYYY - HH:mm');
|
|
|
|
|
|
|
|
// Create a new SensorQuotation document
|
|
|
|
const newQuotation = new SensorQuotation({
|
|
|
|
quatationId,
|
|
|
|
customerId,
|
|
|
|
master_connections: formattedMasterDetails,
|
|
|
|
surveyId,
|
|
|
|
quote_status: "sentfromsurvey",
|
|
|
|
masters,
|
|
|
|
slaves,
|
|
|
|
sensors,
|
|
|
|
motor_switches,
|
|
|
|
electricals: formattedElectricals,
|
|
|
|
datetime: formattedDateTime,
|
|
|
|
estimated_price: totalEstimatedPrice, // Store estimated price
|
|
|
|
});
|
|
|
|
|
|
|
|
const savedQuotation = await newQuotation.save();
|
|
|
|
|
|
|
|
reply.code(200).send({
|
|
|
|
success: true,
|
|
|
|
message: 'Quotation for sensors created successfully.',
|
|
|
|
data: savedQuotation,
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error creating quotation:', error);
|
|
|
|
reply.code(500).send({
|
|
|
|
success: false,
|
|
|
|
message: 'Failed to create quotation for sensors.',
|
|
|
|
error: error.message,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.editQuotationForSensor = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { quatationId } = req.params; // Get the ID of the quotation to edit
|
|
|
|
const { masters, slaves, sensors, motor_switches, electricals, master_connections } = req.body;
|
|
|
|
|
|
|
|
// Format electricals field
|
|
|
|
const formattedElectricals = electricals.map((item) => ({
|
|
|
|
type: item.type || "",
|
|
|
|
wire: item.wire || "",
|
|
|
|
switch: item.switch || "",
|
|
|
|
text: item.text || "",
|
|
|
|
}));
|
|
|
|
|
|
|
|
// Format master_connections field
|
|
|
|
const formattedMasterDetails = master_connections.map((item) => ({
|
|
|
|
master_name: item.master_name || "",
|
|
|
|
slaves: item.slaves || "",
|
|
|
|
location: item.location || "",
|
|
|
|
tanks: Array.isArray(item.tanks)
|
|
|
|
? item.tanks.map(tank => ({
|
|
|
|
tankName: tank.tankName || "",
|
|
|
|
tankLocation: tank.tankLocation || ""
|
|
|
|
}))
|
|
|
|
: []
|
|
|
|
}));
|
|
|
|
|
|
|
|
console.log("Formatted Master Connections:", formattedMasterDetails); // Debugging
|
|
|
|
|
|
|
|
// Find and update the quotation
|
|
|
|
const updatedQuotation = await SensorQuotation.findOneAndUpdate(
|
|
|
|
{ quatationId },
|
|
|
|
{
|
|
|
|
masters,
|
|
|
|
slaves,
|
|
|
|
sensors,
|
|
|
|
motor_switches,
|
|
|
|
electricals: formattedElectricals,
|
|
|
|
master_connections: formattedMasterDetails, // <- Ensure it's included
|
|
|
|
updated_at: dayjs().tz("Asia/Kolkata").format('DD-MMM-YYYY - HH:mm'),
|
|
|
|
},
|
|
|
|
{ new: true } // Return the updated document
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedQuotation) {
|
|
|
|
return reply.code(404).send({
|
|
|
|
success: false,
|
|
|
|
message: 'Quotation not found.',
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
reply.code(200).send({
|
|
|
|
success: true,
|
|
|
|
message: 'Quotation updated successfully.',
|
|
|
|
data: updatedQuotation,
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error updating quotation:', error);
|
|
|
|
reply.code(500).send({
|
|
|
|
success: false,
|
|
|
|
message: 'Failed to update quotation.',
|
|
|
|
error: error.message,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.createEstimationPrice = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { customerId,items } = req.body;
|
|
|
|
const user = await User.findOne({ customerId });
|
|
|
|
|
|
|
|
if (!Array.isArray(items) || items.length === 0) {
|
|
|
|
return reply.code(400).send({ message: "Items array is required and cannot be empty" });
|
|
|
|
}
|
|
|
|
|
|
|
|
let totalEstimation = 0;
|
|
|
|
const itemDetails = [];
|
|
|
|
|
|
|
|
for (const item of items) {
|
|
|
|
const { name, type, quantity } = item;
|
|
|
|
|
|
|
|
// Fetch the unit price from IotPrice collection
|
|
|
|
const priceEntry = await Iotprice.findOne({ name, type });
|
|
|
|
|
|
|
|
if (!priceEntry) {
|
|
|
|
itemDetails.push({
|
|
|
|
name,
|
|
|
|
type,
|
|
|
|
quantity,
|
|
|
|
unitPrice: null,
|
|
|
|
totalCost: null,
|
|
|
|
message: "Price not found"
|
|
|
|
});
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
const unitPrice = priceEntry.cost;
|
|
|
|
const totalCost = unitPrice * quantity;
|
|
|
|
totalEstimation += totalCost;
|
|
|
|
|
|
|
|
itemDetails.push({
|
|
|
|
name,
|
|
|
|
type,
|
|
|
|
quantity,
|
|
|
|
unitPrice,
|
|
|
|
totalCost
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.code(200).send({
|
|
|
|
items: itemDetails,
|
|
|
|
estimatedTotal: totalEstimation,
|
|
|
|
userDetails: user || null // Include user details in the response
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error calculating estimation:", error);
|
|
|
|
return reply.code(500).send({ message: "Failed to calculate estimation" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getallquotationdata = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
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) {
|
|
|
|
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
|
|
|
|
|
|
|
|
// Fetch the quotation data from the database
|
|
|
|
const quotation = await SensorQuotation.findOne({ quatationId: quotationId });
|
|
|
|
console.log(quotation)
|
|
|
|
if (!quotation) {
|
|
|
|
return reply.code(404).send({
|
|
|
|
success: false,
|
|
|
|
message: 'Quotation not found.'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract the price-per-unit and total price values from the request body
|
|
|
|
const {
|
|
|
|
masters_quantity_price,
|
|
|
|
masters_total_price,
|
|
|
|
slaves_quantity_price,
|
|
|
|
slaves_total_price,
|
|
|
|
motor_switches_quantity_price,
|
|
|
|
motor_switches_total_price,
|
|
|
|
electricals_quantity_price,
|
|
|
|
electricals_total_price,
|
|
|
|
master_type_quantity_price,
|
|
|
|
master_type_total_price,
|
|
|
|
sensor_type_quantity_price,
|
|
|
|
sensor_type_total_price,
|
|
|
|
switch_type_quantity_price,
|
|
|
|
switch_type_total_price,
|
|
|
|
quotation_total_price
|
|
|
|
} = req.body;
|
|
|
|
|
|
|
|
// Update the quotation document with the data from the request body
|
|
|
|
quotation.masters_quantity_price = masters_quantity_price;
|
|
|
|
quotation.masters_total_price = masters_total_price;
|
|
|
|
quotation.slaves_quantity_price = slaves_quantity_price;
|
|
|
|
quotation.slaves_total_price = slaves_total_price;
|
|
|
|
quotation.motor_switches_quantity_price = motor_switches_quantity_price;
|
|
|
|
quotation.motor_switches_total_price = motor_switches_total_price;
|
|
|
|
quotation.electricals_quantity_price = electricals_quantity_price;
|
|
|
|
quotation.electricals_total_price = electricals_total_price;
|
|
|
|
quotation.master_type_quantity_price = master_type_quantity_price;
|
|
|
|
quotation.master_type_total_price = master_type_total_price;
|
|
|
|
quotation.sensor_type_quantity_price = sensor_type_quantity_price;
|
|
|
|
quotation.sensor_type_total_price = sensor_type_total_price;
|
|
|
|
quotation.switch_type_quantity_price = switch_type_quantity_price;
|
|
|
|
quotation.switch_type_total_price = switch_type_total_price;
|
|
|
|
quotation.qutation_total_price = quotation_total_price;
|
|
|
|
|
|
|
|
// Save the updated document back to the database
|
|
|
|
await quotation.save();
|
|
|
|
|
|
|
|
// Send back the updated data
|
|
|
|
reply.code(200).send({
|
|
|
|
success: true,
|
|
|
|
message: 'Quotation data saved successfully.',
|
|
|
|
data: quotation
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error saving quotation data to the database:', error);
|
|
|
|
reply.code(500).send({
|
|
|
|
success: false,
|
|
|
|
message: 'Failed to save quotation data.',
|
|
|
|
error: error.message,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getSinleQuotationData = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { quotationId } = req.params; // Correct the parameter name
|
|
|
|
|
|
|
|
// Fetch the quotation data from the database
|
|
|
|
const quotation = await SensorQuotation.findOne({ quatationId: quotationId }); // Correctly referencing quotationId
|
|
|
|
|
|
|
|
if (!quotation) {
|
|
|
|
return reply.code(404).send({
|
|
|
|
success: false,
|
|
|
|
message: 'Quotation not found.'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
reply.code(200).send({
|
|
|
|
success: true,
|
|
|
|
message: 'Quotation data retrieved successfully.',
|
|
|
|
data: quotation
|
|
|
|
});
|
|
|
|
} catch (error) {
|
|
|
|
console.error('Error fetching quotation data:', error);
|
|
|
|
reply.code(500).send({
|
|
|
|
success: false,
|
|
|
|
message: 'Failed to retrieve quotation data.',
|
|
|
|
error: error.message,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.addToCartHardwareItems = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { productId, productName, description, GST, unitPrice, quantity, totalAmount, serialId } = req.body;
|
|
|
|
|
|
|
|
const gstAmount = (GST / 100) * totalAmount;
|
|
|
|
const grandTotal = totalAmount + gstAmount;
|
|
|
|
|
|
|
|
const newCartItem = new HardwareCart({
|
|
|
|
productId,
|
|
|
|
productName,
|
|
|
|
description,
|
|
|
|
GST,
|
|
|
|
unitPrice,
|
|
|
|
quantity,
|
|
|
|
totalAmount,
|
|
|
|
grandTotal,
|
|
|
|
serialId
|
|
|
|
});
|
|
|
|
|
|
|
|
const savedItem = await newCartItem.save();
|
|
|
|
|
|
|
|
reply.code(201).send({ message: 'Item added to cart', data: savedItem });
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
reply.code(500).send({ message: 'Error adding item to cart', error });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.addToCartService = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { productId, productName, description, GST, unitPrice, quantity, totalAmount, serialId,installationId } = req.body;
|
|
|
|
|
|
|
|
const gstAmount = (GST / 100) * totalAmount;
|
|
|
|
const grandTotal = totalAmount + gstAmount;
|
|
|
|
|
|
|
|
const newCartItem = new ServiceCart({
|
|
|
|
installationId,
|
|
|
|
productId,
|
|
|
|
productName,
|
|
|
|
description,
|
|
|
|
GST,
|
|
|
|
unitPrice,
|
|
|
|
quantity,
|
|
|
|
totalAmount,
|
|
|
|
grandTotal,
|
|
|
|
serialId
|
|
|
|
});
|
|
|
|
|
|
|
|
const savedItem = await newCartItem.save();
|
|
|
|
|
|
|
|
reply.code(201).send({ message: 'Item added to cart', data: savedItem });
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error);
|
|
|
|
reply.code(500).send({ message: 'Error adding item to cart', error });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getquotationofinstalleranduser = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const surveyId = req.params.surveyId;
|
|
|
|
const customerId = req.body.customerId;
|
|
|
|
|
|
|
|
// Find the specific tank
|
|
|
|
const result = await SensorQuotation.find({
|
|
|
|
surveyId: surveyId,
|
|
|
|
customerId: customerId,
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!result) {
|
|
|
|
return reply.send({ status_code: 404, error: "not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
reply.send({ status_code: 200, data: result });
|
|
|
|
} catch (err) {
|
|
|
|
throw boom.boomify(err);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.updateInstallationId = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { _id } = req.params;
|
|
|
|
const { installationId } = req.body;
|
|
|
|
|
|
|
|
if (!_id || !installationId) {
|
|
|
|
return reply.status(400).send({ error: "orderId and installationId are required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the order with the new installationId
|
|
|
|
const updatedOrder = await Order.findByIdAndUpdate(
|
|
|
|
_id,
|
|
|
|
{
|
|
|
|
installationId,
|
|
|
|
status: "installer_assigned", // Updating the status
|
|
|
|
updated_at: new Date().toISOString(), // Updating timestamp
|
|
|
|
},
|
|
|
|
{ new: true }
|
|
|
|
);
|
|
|
|
|
|
|
|
if (!updatedOrder) {
|
|
|
|
return reply.status(404).send({ error: "Order not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Installation ID updated successfully",
|
|
|
|
data: updatedOrder,
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error updating installationId:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getPendingOrders = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const pendingOrders = await Order.find({ status: "pending" });
|
|
|
|
|
|
|
|
if (!pendingOrders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No pending orders found",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Pending orders fetched successfully",
|
|
|
|
data: pendingOrders,
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error fetching pending orders:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.handleEstimation = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { customerId, items, estimatedTotal, action } = req.body;
|
|
|
|
|
|
|
|
if (!customerId) {
|
|
|
|
return reply.code(400).send({ message: "customerId is required" });
|
|
|
|
}
|
|
|
|
if (!Array.isArray(items) || items.length === 0) {
|
|
|
|
return reply.code(400).send({ message: "Items array is required and cannot be empty" });
|
|
|
|
}
|
|
|
|
if (!estimatedTotal) {
|
|
|
|
return reply.code(400).send({ message: "Estimated total is required" });
|
|
|
|
}
|
|
|
|
if (!["accept", "reject"].includes(action)) {
|
|
|
|
return reply.code(400).send({ message: "Invalid action, must be 'accept' or 'reject'" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// If rejected, return a response without creating an order
|
|
|
|
if (action === "reject") {
|
|
|
|
return reply.code(200).send({ message: "Estimation rejected" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// If accepted, generate unique Order ID
|
|
|
|
const lastOrder = await EstimationOrder.findOne().sort({ createdAt: -1 });
|
|
|
|
let orderId = "AWS001";
|
|
|
|
if (lastOrder) {
|
|
|
|
const lastNumber = parseInt(lastOrder.orderId.replace("AWS", ""), 10) + 1;
|
|
|
|
orderId = `AWS${String(lastNumber).padStart(3, "0")}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new order in the database
|
|
|
|
const newOrder = new EstimationOrder({
|
|
|
|
orderId,
|
|
|
|
customerId,
|
|
|
|
items,
|
|
|
|
estimatedTotal,
|
|
|
|
status: "pending"
|
|
|
|
});
|
|
|
|
|
|
|
|
await newOrder.save();
|
|
|
|
|
|
|
|
return reply.code(200).send({
|
|
|
|
message: "Order created successfully",
|
|
|
|
orderId,
|
|
|
|
customerId,
|
|
|
|
estimatedTotal,
|
|
|
|
items,
|
|
|
|
status: "pending"
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error handling estimation:", error);
|
|
|
|
return reply.code(500).send({ message: "Failed to process estimation" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.editOrder = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { orderId, customerId, items, estimatedTotal } = req.body;
|
|
|
|
|
|
|
|
if (!orderId) {
|
|
|
|
return reply.code(400).send({ message: "orderId is required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the existing order
|
|
|
|
const existingOrder = await EstimationOrder.findOne({ orderId });
|
|
|
|
|
|
|
|
if (!existingOrder) {
|
|
|
|
return reply.code(404).send({ message: "Order not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the order in the database
|
|
|
|
existingOrder.customerId = customerId;
|
|
|
|
existingOrder.items = items;
|
|
|
|
existingOrder.estimatedTotal = estimatedTotal;
|
|
|
|
|
|
|
|
await existingOrder.save();
|
|
|
|
|
|
|
|
return reply.code(200).send({
|
|
|
|
message: "Order updated successfully",
|
|
|
|
orderId,
|
|
|
|
updatedItems: items,
|
|
|
|
estimatedTotal
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error updating order:", error);
|
|
|
|
return reply.code(500).send({ message: "Failed to update order" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getOrdersByCustomer = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { customerId } = req.params;
|
|
|
|
|
|
|
|
if (!customerId) {
|
|
|
|
return reply.code(400).send({ message: "customerId is required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch orders with status 'pending' or 'accepted' for the given customer
|
|
|
|
const orders = await EstimationOrder.find({
|
|
|
|
customerId,
|
|
|
|
status: { $in: ["pending", "accepted"] }
|
|
|
|
});
|
|
|
|
|
|
|
|
if (orders.length === 0) {
|
|
|
|
return reply.code(404).send({ message: "No orders found for this customer" });
|
|
|
|
}
|
|
|
|
|
|
|
|
return reply.code(200).send({
|
|
|
|
message: "Orders retrieved successfully",
|
|
|
|
customerId,
|
|
|
|
orders
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error fetching orders:", error);
|
|
|
|
return reply.code(500).send({ message: "Failed to fetch orders" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.acceptQuotation = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { quotationId } = req.params;
|
|
|
|
let { action, storeId } = req.body;
|
|
|
|
|
|
|
|
action = action.toLowerCase();
|
|
|
|
|
|
|
|
const quotation = await SensorQuotation.findOne({ quatationId: quotationId });
|
|
|
|
if (!quotation) {
|
|
|
|
return reply.status(404).send({ error: "Quotation not found" });
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action === "reject") {
|
|
|
|
await SensorQuotation.updateOne({ quatationId: quotationId }, { $set: { status: "rejected" } });
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Quotation rejected successfully",
|
|
|
|
});
|
|
|
|
} else if (action === "accept") {
|
|
|
|
const { customerId, masters, slaves, sensors, master_connections } = quotation;
|
|
|
|
|
|
|
|
// Step 1: Block Masters
|
|
|
|
let blockedMasters = [];
|
|
|
|
if (parseInt(masters) > 0) {
|
|
|
|
const availableMasters = await Insensors.find({ storeId, type: "master", status: "available" })
|
|
|
|
.limit(parseInt(masters))
|
|
|
|
.lean();
|
|
|
|
|
|
|
|
const masterIds = availableMasters.map(master => master._id);
|
|
|
|
blockedMasters = availableMasters.map(master => ({ _id: master._id, hardwareId: master.hardwareId }));
|
|
|
|
|
|
|
|
if (masterIds.length > 0) {
|
|
|
|
await Insensors.updateMany(
|
|
|
|
{ _id: { $in: masterIds } },
|
|
|
|
{ $set: { status: "blocked", customerId } }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step 2: Assign Slaves to Masters
|
|
|
|
let blockedSlaveIds = [];
|
|
|
|
let blockedSlaves = [];
|
|
|
|
|
|
|
|
for (let i = 0; i < master_connections.length; i++) {
|
|
|
|
const masterData = master_connections[i];
|
|
|
|
if (i >= blockedMasters.length) break;
|
|
|
|
|
|
|
|
const masterHardwareId = blockedMasters[i].hardwareId;
|
|
|
|
const masterId = blockedMasters[i]._id;
|
|
|
|
const slaveCount = parseInt(masterData.slaves) || 0;
|
|
|
|
|
|
|
|
// Assign Slaves
|
|
|
|
if (slaveCount > 0) {
|
|
|
|
const availableSlaves = await Insensors.find({ storeId, type: "slave", status: "available" })
|
|
|
|
.limit(slaveCount)
|
|
|
|
.lean();
|
|
|
|
|
|
|
|
const slaveIds = availableSlaves.map(slave => slave._id);
|
|
|
|
blockedSlaveIds.push(...slaveIds);
|
|
|
|
blockedSlaves.push(...availableSlaves.map(slave => ({ _id: slave._id, hardwareId: slave.hardwareId })));
|
|
|
|
|
|
|
|
for (let j = 0; j < availableSlaves.length; j++) {
|
|
|
|
const slave = availableSlaves[j];
|
|
|
|
const tank = masterData.tanks?.[j] || {};
|
|
|
|
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: slave._id },
|
|
|
|
{
|
|
|
|
$set: {
|
|
|
|
status: "blocked",
|
|
|
|
customerId,
|
|
|
|
connected_to: masterHardwareId,
|
|
|
|
tankhardwareId: `tank-${j + 1}`,
|
|
|
|
hardwareId: slave.hardwareId,
|
|
|
|
tankName: tank.tankName || "",
|
|
|
|
tankLocation: tank.tankLocation || "",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update tanks and motor switches for master
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: masterId },
|
|
|
|
{
|
|
|
|
$set: {
|
|
|
|
hardwareId: masterHardwareId,
|
|
|
|
tanks: (masterData.tanks || []).map(tank => ({
|
|
|
|
tankName: tank.tankName || "",
|
|
|
|
tankLocation: tank.tankLocation || "",
|
|
|
|
})),
|
|
|
|
motor_switches: masterData.motor_switches || [],
|
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step 2.5: Update master_connections.hardwareId
|
|
|
|
const updatedMasterConnections = quotation.master_connections.map((conn, index) => {
|
|
|
|
const plain = conn.toObject ? conn.toObject() : conn;
|
|
|
|
return {
|
|
|
|
...plain,
|
|
|
|
hardwareId: blockedMasters[index]?.hardwareId || null,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
// Step 3: Assign Sensors to Slaves
|
|
|
|
if (parseInt(sensors) > 0 && blockedSlaves.length > 0) {
|
|
|
|
const availableSensors = await Insensors.find({ storeId, type: "sensor", status: "available" })
|
|
|
|
.limit(parseInt(sensors))
|
|
|
|
.lean();
|
|
|
|
|
|
|
|
const sensorIds = availableSensors.map(sensor => sensor._id);
|
|
|
|
|
|
|
|
for (let i = 0; i < sensorIds.length; i++) {
|
|
|
|
const assignedSlave = blockedSlaves[i % blockedSlaves.length];
|
|
|
|
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: sensorIds[i] },
|
|
|
|
{
|
|
|
|
$set: {
|
|
|
|
status: "blocked",
|
|
|
|
customerId,
|
|
|
|
connected_to: assignedSlave.hardwareId,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step 4: Update Sensor Stock
|
|
|
|
const sensorTypes = [
|
|
|
|
{ type: "master", count: parseInt(masters || 0) },
|
|
|
|
{ type: "slave", count: parseInt(slaves || 0) },
|
|
|
|
{ type: "sensor", count: parseInt(sensors || 0) },
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const sensor of sensorTypes) {
|
|
|
|
if (sensor.count > 0) {
|
|
|
|
const stock = await SensorStock.findOne({ storeId, type: sensor.type });
|
|
|
|
|
|
|
|
if (stock) {
|
|
|
|
let available = stock.total_available || 0;
|
|
|
|
let needed = sensor.count;
|
|
|
|
let toBlock = Math.min(available, needed);
|
|
|
|
let excessNeeded = needed - toBlock;
|
|
|
|
|
|
|
|
if (toBlock > 0) {
|
|
|
|
const availableSensors = await Insensors.find({ storeId, type: sensor.type, status: "available" })
|
|
|
|
.limit(toBlock)
|
|
|
|
.lean();
|
|
|
|
|
|
|
|
const sensorIds = availableSensors.map(sensor => sensor._id);
|
|
|
|
|
|
|
|
if (sensorIds.length > 0) {
|
|
|
|
await Insensors.updateMany(
|
|
|
|
{ _id: { $in: sensorIds } },
|
|
|
|
{ $set: { status: "blocked", customerId } }
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
await SensorStock.updateOne(
|
|
|
|
{ storeId, type: sensor.type },
|
|
|
|
{
|
|
|
|
$inc: {
|
|
|
|
total_available: -toBlock,
|
|
|
|
total_blocked: toBlock,
|
|
|
|
excess_needed: excessNeeded > 0 ? excessNeeded : 0,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Step 5: Create Order
|
|
|
|
const plainQuotation = quotation.toObject();
|
|
|
|
plainQuotation.master_connections = updatedMasterConnections;
|
|
|
|
|
|
|
|
const newOrder = new Order({
|
|
|
|
...plainQuotation,
|
|
|
|
storeId,
|
|
|
|
status: "pending",
|
|
|
|
});
|
|
|
|
|
|
|
|
await newOrder.save();
|
|
|
|
|
|
|
|
// Step 6: Delete Quotation
|
|
|
|
await SensorQuotation.deleteOne({ quatationId: quotationId });
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Quotation accepted, sensors blocked, 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 });
|
|
|
|
|
|
|
|
if (!orders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No orders found for this store",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch customer details & allocated sensors for each order
|
|
|
|
const ordersWithDetails = await Promise.all(
|
|
|
|
orders.map(async (order) => {
|
|
|
|
// Fetch customer details
|
|
|
|
const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
|
|
|
|
// Fetch allocated sensors for this customer
|
|
|
|
const allocatedSensors = await Insensors.find({
|
|
|
|
storeId,
|
|
|
|
customerId: order.customerId, // Match only sensors allocated to this customer
|
|
|
|
status: "blocked", // Only fetch sensors that are allocated (blocked)
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
return {
|
|
|
|
...order.toObject(),
|
|
|
|
customer: customer || null, // Include customer details or null if not found
|
|
|
|
allocated_sensors: allocatedSensors, // List of allocated sensors
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Orders fetched successfully",
|
|
|
|
data: ordersWithDetails,
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error fetching orders:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// exports.getOrdersByInstallationId = async (req, reply) => {
|
|
|
|
// try {
|
|
|
|
// const { installationId } = req.params;
|
|
|
|
|
|
|
|
// if (!installationId) {
|
|
|
|
// return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Fetch all orders by installationId
|
|
|
|
// const orders = await Order.find({ installationId });
|
|
|
|
|
|
|
|
// if (!orders.length) {
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: "No orders found for this installation",
|
|
|
|
// data: {
|
|
|
|
// customers: [],
|
|
|
|
// orders: []
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Get unique customerIds from orders
|
|
|
|
// const uniqueCustomerIds = [...new Set(orders.map(order => order.customerId))];
|
|
|
|
|
|
|
|
// // Fetch all customers in a single query
|
|
|
|
// const customers = await User.find({ customerId: { $in: uniqueCustomerIds } }).lean();
|
|
|
|
|
|
|
|
// // Map customerId -> customer object
|
|
|
|
// const customerMap = {};
|
|
|
|
// customers.forEach(c => {
|
|
|
|
// customerMap[c.customerId] = c;
|
|
|
|
// });
|
|
|
|
|
|
|
|
// // For each order, attach allocated sensors only
|
|
|
|
// const ordersWithSensors = await Promise.all(
|
|
|
|
// orders.map(async (order) => {
|
|
|
|
// const allocatedSensors = await Insensors.find({
|
|
|
|
// storeId: order.storeId,
|
|
|
|
// customerId: order.customerId,
|
|
|
|
// status: "blocked"
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
// return {
|
|
|
|
// ...order.toObject(),
|
|
|
|
// allocated_sensors: allocatedSensors
|
|
|
|
// };
|
|
|
|
// })
|
|
|
|
// );
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: "Orders fetched successfully",
|
|
|
|
// data: customers
|
|
|
|
// // data: {
|
|
|
|
// // customers,
|
|
|
|
// // // orders: ordersWithSensors
|
|
|
|
// // }
|
|
|
|
// });
|
|
|
|
|
|
|
|
// } catch (err) {
|
|
|
|
// console.error("Error fetching orders:", err);
|
|
|
|
// return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
// exports.getOrdersByInstallationId = async (req, reply) => {
|
|
|
|
// try {
|
|
|
|
// const { installationId } = req.params;
|
|
|
|
|
|
|
|
// if (!installationId) {
|
|
|
|
// return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Fetch orders with the matching installationId
|
|
|
|
// const orders = await Order.find({ installationId });
|
|
|
|
|
|
|
|
// if (!orders.length) {
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: "No orders found for this installation",
|
|
|
|
// data: [],
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// const uniqueCustomersMap = new Map();
|
|
|
|
|
|
|
|
// // Build unique customerId-based map
|
|
|
|
// for (const order of orders) {
|
|
|
|
// if (!uniqueCustomersMap.has(order.customerId)) {
|
|
|
|
// uniqueCustomersMap.set(order.customerId, order);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Only keep one order per customerId
|
|
|
|
// const uniqueOrders = Array.from(uniqueCustomersMap.values());
|
|
|
|
|
|
|
|
// // Enrich with customer and sensor info
|
|
|
|
// const ordersWithDetails = await Promise.all(
|
|
|
|
// uniqueOrders.map(async (order) => {
|
|
|
|
// const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
|
|
|
|
// const allocatedSensors = await Insensors.find({
|
|
|
|
// storeId: order.storeId,
|
|
|
|
// customerId: order.customerId,
|
|
|
|
// status: "blocked",
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
// return {
|
|
|
|
// ...order.toObject(),
|
|
|
|
// customer: customer || null,
|
|
|
|
// allocated_sensors: allocatedSensors,
|
|
|
|
// };
|
|
|
|
// })
|
|
|
|
// );
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: "Orders fetched successfully",
|
|
|
|
// data: ordersWithDetails,
|
|
|
|
// });
|
|
|
|
|
|
|
|
// } catch (err) {
|
|
|
|
// console.error("Error fetching orders:", err);
|
|
|
|
// return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
exports.getOrdersByInstallationId = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { installationId } = req.params;
|
|
|
|
|
|
|
|
if (!installationId) {
|
|
|
|
return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch orders with the matching installationId
|
|
|
|
const orders = await Order.find({ installationId });
|
|
|
|
|
|
|
|
if (!orders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No orders found for this installation",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const uniqueCustomersMap = new Map();
|
|
|
|
|
|
|
|
// Build unique customerId-based map
|
|
|
|
for (const order of orders) {
|
|
|
|
if (!uniqueCustomersMap.has(order.customerId)) {
|
|
|
|
uniqueCustomersMap.set(order.customerId, order);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only keep one order per customerId
|
|
|
|
let uniqueOrders = Array.from(uniqueCustomersMap.values());
|
|
|
|
|
|
|
|
// ✅ Filter: keep only orders where work_status is 'active'
|
|
|
|
uniqueOrders = uniqueOrders.filter(order => order.work_status === 'active');
|
|
|
|
|
|
|
|
// If no orders left after filtering, return empty list
|
|
|
|
if (!uniqueOrders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No active orders found for this installation",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enrich with customer and sensor info
|
|
|
|
const ordersWithDetails = await Promise.all(
|
|
|
|
uniqueOrders.map(async (order) => {
|
|
|
|
const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
|
|
|
|
const allocatedSensors = await Insensors.find({
|
|
|
|
storeId: order.storeId,
|
|
|
|
customerId: order.customerId,
|
|
|
|
status: "blocked",
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
return {
|
|
|
|
...order.toObject(),
|
|
|
|
customer: customer || null,
|
|
|
|
allocated_sensors: allocatedSensors,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Active orders fetched successfully",
|
|
|
|
data: ordersWithDetails,
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error fetching orders:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
exports.getPendingOrdersByInstallationId = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { installationId } = req.params;
|
|
|
|
|
|
|
|
if (!installationId) {
|
|
|
|
return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch orders with the matching installationId
|
|
|
|
const orders = await Order.find({ installationId });
|
|
|
|
|
|
|
|
if (!orders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No orders found for this installation",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const uniqueCustomersMap = new Map();
|
|
|
|
|
|
|
|
// Build unique customerId-based map
|
|
|
|
for (const order of orders) {
|
|
|
|
if (!uniqueCustomersMap.has(order.customerId)) {
|
|
|
|
uniqueCustomersMap.set(order.customerId, order);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only keep one order per customerId
|
|
|
|
let uniqueOrders = Array.from(uniqueCustomersMap.values());
|
|
|
|
|
|
|
|
// ✅ Filter: keep only those where work_status is "pending"
|
|
|
|
uniqueOrders = uniqueOrders.filter(order => order.work_status === 'pending');
|
|
|
|
|
|
|
|
// If nothing left after filtering, return empty
|
|
|
|
if (!uniqueOrders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No pending orders found for this installation",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enrich with customer and sensor info
|
|
|
|
const ordersWithDetails = await Promise.all(
|
|
|
|
uniqueOrders.map(async (order) => {
|
|
|
|
const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
|
|
|
|
const allocatedSensors = await Insensors.find({
|
|
|
|
storeId: order.storeId,
|
|
|
|
customerId: order.customerId,
|
|
|
|
status: "blocked",
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
return {
|
|
|
|
...order.toObject(),
|
|
|
|
customer: customer || null,
|
|
|
|
allocated_sensors: allocatedSensors,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Pending orders fetched successfully",
|
|
|
|
data: ordersWithDetails,
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error fetching orders:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
exports.getPendingOrdersByInstallationId = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { installationId } = req.params;
|
|
|
|
|
|
|
|
if (!installationId) {
|
|
|
|
return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch orders with the matching installationId
|
|
|
|
const orders = await Order.find({ installationId });
|
|
|
|
|
|
|
|
if (!orders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No orders found for this installation",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
const uniqueCustomersMap = new Map();
|
|
|
|
|
|
|
|
// Build unique customerId-based map
|
|
|
|
for (const order of orders) {
|
|
|
|
if (!uniqueCustomersMap.has(order.customerId)) {
|
|
|
|
uniqueCustomersMap.set(order.customerId, order);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only keep one order per customerId
|
|
|
|
let uniqueOrders = Array.from(uniqueCustomersMap.values());
|
|
|
|
|
|
|
|
// ✅ Filter: keep only those where work_status is "pending"
|
|
|
|
uniqueOrders = uniqueOrders.filter(order => order.work_status === 'complete');
|
|
|
|
|
|
|
|
// If nothing left after filtering, return empty
|
|
|
|
if (!uniqueOrders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No pending orders found for this installation",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enrich with customer and sensor info
|
|
|
|
const ordersWithDetails = await Promise.all(
|
|
|
|
uniqueOrders.map(async (order) => {
|
|
|
|
const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
|
|
|
|
const allocatedSensors = await Insensors.find({
|
|
|
|
storeId: order.storeId,
|
|
|
|
customerId: order.customerId,
|
|
|
|
status: "blocked",
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
return {
|
|
|
|
...order.toObject(),
|
|
|
|
customer: customer || null,
|
|
|
|
allocated_sensors: allocatedSensors,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Complete orders fetched successfully",
|
|
|
|
data: ordersWithDetails,
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error fetching orders:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// exports.getOrdersByInstallationId = async (req, reply) => {
|
|
|
|
// try {
|
|
|
|
// const { installationId } = req.params;
|
|
|
|
|
|
|
|
// if (!installationId) {
|
|
|
|
// return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Build query — do NOT filter by work_status yet
|
|
|
|
// const query = { installationId };
|
|
|
|
|
|
|
|
// const orders = await Order.find(query);
|
|
|
|
|
|
|
|
// if (!orders.length) {
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: "No orders found for this installation and customer",
|
|
|
|
// data: [],
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// const ordersWithDetails = [];
|
|
|
|
|
|
|
|
// for (const order of orders) {
|
|
|
|
// // Ensure work_status is set
|
|
|
|
// if (!order.work_status || order.work_status.trim() === "") {
|
|
|
|
// order.work_status = "active";
|
|
|
|
// await order.save();
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // ✅ Only push if work_status is "active"
|
|
|
|
// if (order.work_status === "active") {
|
|
|
|
// const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
// const allocatedSensors = await Insensors.find({
|
|
|
|
// storeId: order.storeId,
|
|
|
|
// customerId: order.customerId,
|
|
|
|
// status: "blocked",
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
// ordersWithDetails.push({
|
|
|
|
// ...order.toObject(),
|
|
|
|
// customer: customer || null,
|
|
|
|
// allocated_sensors: allocatedSensors,
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: "Orders fetched successfully",
|
|
|
|
// data: ordersWithDetails,
|
|
|
|
// });
|
|
|
|
|
|
|
|
// } catch (err) {
|
|
|
|
// console.error("Error fetching orders:", err);
|
|
|
|
// return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// exports.updateWorkStatusByInstallationId = async (req, reply) => {
|
|
|
|
// try {
|
|
|
|
// const { installationId, customerId } = req.params;
|
|
|
|
// const { work_status } = req.body; // 🟢 pass in body
|
|
|
|
|
|
|
|
// if (!installationId) {
|
|
|
|
// return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if (!customerId) {
|
|
|
|
// return reply.status(400).send({ error: "customerId is required" });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// if (!work_status || !['active', 'pending', 'complete'].includes(work_status)) {
|
|
|
|
// return reply.status(400).send({ error: "Valid work_status is required: active, pending or complete" });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Find all orders for this installation + customer
|
|
|
|
// const orders = await Order.find({ installationId, customerId });
|
|
|
|
|
|
|
|
// if (!orders.length) {
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: "No orders found for this installation and customer",
|
|
|
|
// data: [],
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Update all found orders to new work_status
|
|
|
|
// for (const order of orders) {
|
|
|
|
// order.work_status = work_status;
|
|
|
|
// await order.save();
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // After update, fetch all with updated work_status only
|
|
|
|
// const updatedOrders = await Order.find({ installationId, customerId, work_status });
|
|
|
|
|
|
|
|
// const ordersWithDetails = await Promise.all(
|
|
|
|
// updatedOrders.map(async (order) => {
|
|
|
|
// const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
// const allocatedSensors = await Insensors.find({
|
|
|
|
// storeId: order.storeId,
|
|
|
|
// customerId: order.customerId,
|
|
|
|
// status: "blocked",
|
|
|
|
// }).lean();
|
|
|
|
|
|
|
|
// return {
|
|
|
|
// ...order.toObject(),
|
|
|
|
// customer: customer || null,
|
|
|
|
// allocated_sensors: allocatedSensors,
|
|
|
|
// };
|
|
|
|
// })
|
|
|
|
// );
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
// status_code: 200,
|
|
|
|
// message: `Orders updated to work_status '${work_status}' successfully`,
|
|
|
|
// data: ordersWithDetails,
|
|
|
|
// });
|
|
|
|
|
|
|
|
// } catch (err) {
|
|
|
|
// console.error("Error updating work_status:", err);
|
|
|
|
// return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
// }
|
|
|
|
// };
|
|
|
|
|
|
|
|
exports.updateWorkStatusByInstallationId = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { installationId, customerId } = req.params;
|
|
|
|
const { work_status, hardwareId } = req.body;
|
|
|
|
|
|
|
|
if (!installationId) {
|
|
|
|
return reply.status(400).send({ error: "installationId is required" });
|
|
|
|
}
|
|
|
|
if (!customerId) {
|
|
|
|
return reply.status(400).send({ error: "customerId is required" });
|
|
|
|
}
|
|
|
|
if (!hardwareId) {
|
|
|
|
return reply.status(400).send({ error: "hardwareId is required" });
|
|
|
|
}
|
|
|
|
if (!work_status || !['active', 'pending', 'complete'].includes(work_status)) {
|
|
|
|
return reply.status(400).send({ error: "Valid work_status is required: active, pending or complete" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// ✅ Correct query
|
|
|
|
const orders = await Order.find({
|
|
|
|
installationId,
|
|
|
|
customerId,
|
|
|
|
'master_connections.hardwareId': hardwareId
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!orders.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No orders found for this installation, customer and hardwareId",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update work_status
|
|
|
|
for (const order of orders) {
|
|
|
|
order.work_status = work_status;
|
|
|
|
await order.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch updated orders
|
|
|
|
const updatedOrders = await Order.find({
|
|
|
|
installationId,
|
|
|
|
customerId,
|
|
|
|
'master_connections.hardwareId': hardwareId,
|
|
|
|
work_status
|
|
|
|
});
|
|
|
|
|
|
|
|
// Enrich data
|
|
|
|
const ordersWithDetails = await Promise.all(
|
|
|
|
updatedOrders.map(async (order) => {
|
|
|
|
const customer = await User.findOne({ customerId: order.customerId }).lean();
|
|
|
|
const allocatedSensors = await Insensors.find({
|
|
|
|
storeId: order.storeId,
|
|
|
|
customerId: order.customerId,
|
|
|
|
status: "blocked",
|
|
|
|
}).lean();
|
|
|
|
|
|
|
|
return {
|
|
|
|
...order.toObject(),
|
|
|
|
customer: customer || null,
|
|
|
|
allocated_sensors: allocatedSensors,
|
|
|
|
};
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: `Orders updated to work_status '${work_status}' successfully`,
|
|
|
|
data: ordersWithDetails,
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error updating work_status:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.getallocatedsensorstouser= async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { customerId } = req.params;
|
|
|
|
|
|
|
|
if (!customerId) {
|
|
|
|
return reply.status(400).send({ error: "customerId is required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fetch orders with the matching storeId
|
|
|
|
const allocated_iots = await Insensors.find({ customerId });
|
|
|
|
|
|
|
|
if (!allocated_iots.length) {
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "No sensors found for this store",
|
|
|
|
data: [],
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "iots fetched successfully",
|
|
|
|
data: allocated_iots,
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error fetching iots:", err);
|
|
|
|
return reply.status(500).send({ error: "Internal server error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const crypto = require("crypto");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
exports.replaceAndRepair = async (req, reply) => {
|
|
|
|
try {
|
|
|
|
const { customerId } = req.params;
|
|
|
|
const { items } = req.body;
|
|
|
|
|
|
|
|
if (!customerId || !Array.isArray(items) || items.length === 0) {
|
|
|
|
return reply.code(400).send({ error: "customerId and items[] are required" });
|
|
|
|
}
|
|
|
|
|
|
|
|
const replacements = [];
|
|
|
|
|
|
|
|
for (const item of items) {
|
|
|
|
const { type, hardwareId } = item;
|
|
|
|
console.log(`🔍 Processing ${type} with hardwareId: ${hardwareId}`);
|
|
|
|
|
|
|
|
const existing = await Insensors.findOne({ hardwareId, type, customerId });
|
|
|
|
|
|
|
|
if (!existing) {
|
|
|
|
console.warn(`⚠️ No existing ${type} found for hardwareId: ${hardwareId}`);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark existing as repair
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: existing._id },
|
|
|
|
{ $set: { status: "repair", outforrepairdate: new Date().toISOString() } }
|
|
|
|
);
|
|
|
|
console.log(`🛠 Marked old ${type} ${hardwareId} as repair`);
|
|
|
|
|
|
|
|
// Find replacement
|
|
|
|
const replacement = await Insensors.findOne({
|
|
|
|
type,
|
|
|
|
status: "available",
|
|
|
|
storeId: existing.storeId
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!replacement) {
|
|
|
|
console.warn(`⚠️ No available replacement found for ${type} at store ${existing.storeId}`);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log(`✅ Found replacement ${replacement.hardwareId} for ${type}`);
|
|
|
|
|
|
|
|
const updateData = {
|
|
|
|
status: "blocked",
|
|
|
|
customerId: existing.customerId,
|
|
|
|
tankName: existing.tankName,
|
|
|
|
tankLocation: existing.tankLocation,
|
|
|
|
storeId: existing.storeId,
|
|
|
|
model: existing.model,
|
|
|
|
tankhardwareId: existing.tankhardwareId,
|
|
|
|
masterId: existing.masterId,
|
|
|
|
masterName: existing.masterName,
|
|
|
|
location: existing.location
|
|
|
|
};
|
|
|
|
|
|
|
|
await Insensors.updateOne({ _id: replacement._id }, { $set: updateData });
|
|
|
|
console.log(`✅ Updated replacement ${type} ${replacement.hardwareId} with previous config`);
|
|
|
|
|
|
|
|
// === Cascade updates ===
|
|
|
|
if (type === "master") {
|
|
|
|
const connectedSlaves = await Insensors.find({
|
|
|
|
type: "slave",
|
|
|
|
connected_to: hardwareId,
|
|
|
|
customerId
|
|
|
|
});
|
|
|
|
|
|
|
|
for (const slave of connectedSlaves) {
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: slave._id },
|
|
|
|
{ $set: { connected_to: replacement.hardwareId } }
|
|
|
|
);
|
|
|
|
console.log(`🔁 Updated slave ${slave.hardwareId} → connected_to: ${replacement.hardwareId}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type === "slave") {
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: replacement._id },
|
|
|
|
{ $set: { connected_to: existing.connected_to } }
|
|
|
|
);
|
|
|
|
console.log(`🔁 New slave ${replacement.hardwareId} → connected_to: ${existing.connected_to}`);
|
|
|
|
|
|
|
|
const connectedSensors = await Insensors.find({
|
|
|
|
type: "sensor",
|
|
|
|
connected_to: hardwareId,
|
|
|
|
customerId
|
|
|
|
});
|
|
|
|
|
|
|
|
for (const sensor of connectedSensors) {
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: sensor._id },
|
|
|
|
{ $set: { connected_to: replacement.hardwareId } }
|
|
|
|
);
|
|
|
|
console.log(`🔁 Updated sensor ${sensor.hardwareId} → connected_to: ${replacement.hardwareId}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type === "sensor") {
|
|
|
|
await Insensors.updateOne(
|
|
|
|
{ _id: replacement._id },
|
|
|
|
{ $set: { connected_to: existing.connected_to } }
|
|
|
|
);
|
|
|
|
console.log(`🔁 Sensor ${replacement.hardwareId} connected to same slave: ${existing.connected_to}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Log replacement
|
|
|
|
replacements.push({
|
|
|
|
type,
|
|
|
|
oldHardwareId: hardwareId,
|
|
|
|
newHardwareId: replacement.hardwareId
|
|
|
|
});
|
|
|
|
|
|
|
|
console.log(`📦 Logged replacement: ${type} ${hardwareId} ➜ ${replacement.hardwareId}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log("🧾 Final replacements:", replacements);
|
|
|
|
|
|
|
|
// Create repair log
|
|
|
|
const packageId = "PKG-" + crypto.randomBytes(4).toString("hex").toUpperCase();
|
|
|
|
const otp = Math.floor(100000 + Math.random() * 900000).toString();
|
|
|
|
|
|
|
|
const repairLog = new Repairorder({
|
|
|
|
customerId,
|
|
|
|
packageId,
|
|
|
|
otp,
|
|
|
|
replacements,
|
|
|
|
createdAt: new Date()
|
|
|
|
});
|
|
|
|
|
|
|
|
await repairLog.save();
|
|
|
|
console.log("✅ RepairLog saved");
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
status_code: 200,
|
|
|
|
message: "Repaired and replaced successfully",
|
|
|
|
data: {
|
|
|
|
packageId,
|
|
|
|
otp,
|
|
|
|
replacements,
|
|
|
|
createdAt: repairLog.createdAt
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (err) {
|
|
|
|
console.error("❌ Error during replacement:", err);
|
|
|
|
return reply.code(500).send({ error: "Internal Server Error" });
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|