You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2198 lines
63 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// const fastify = require("fastify")({
// logger: true,
// });
//const axios = require('axios');
const bcrypt = require("bcrypt");
const saltRounds = 10;
const libphonenumberjs = require("libphonenumber-js");
// External Dependancies
// offers http-friendly error objects.
const boom = require("boom");
const { Tankerbooking} = require("../models/tankers")
const {EstimationOrder} = require("../models/store");
// Get Data Models
const { RecurringRequestedBooking,RequestedBooking,Supplier, generateSupplierId, FriendRequest,DeliveryBoy} = require("../models/supplier")
const { User,Counter, generateBookingId,resetCounter,generateCustomerId,ProfilePicture, AddTeamMembers,Cart} = require('../models/User')
//const User = require("../models/User");
const customJwtAuth = require("../customAuthJwt");
const fastify = require("fastify")({
logger: true,
});
//function to encrypt password.
//used bcrypt module.
async function bcryptPassword(password) {
encryptedPwd = bcrypt.hash(password, saltRounds);
return encryptedPwd;
}
//function to decrypt password return user object .
//used bcrypt module.
async function bcryptComparePassword(pwd, encpassword) {
isSame = bcrypt.compare(pwd, encpassword);
return isSame;
}
// Get current users
exports.getCurrentUser = async (req, reply) => {
try {
const users = await User.findOne({ customerId: req.body.customerId });
return users;
} catch (err) {
throw boom.boomify(err);
}
};
// Get all users
exports.getUsers = async (req, reply) => {
const limit = parseInt(req.query.limit) || 100;
const page = parseInt(req.query.page) || 1;
const startindex = (page - 1) * limit;
try {
await User.find()
.limit(limit)
.skip(startindex)
.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);
}
};
// Get single user by ID
exports.getSingleUser = async (req, reply) => {
try {
const customerId = req.params.customerId;
const user = await User.findOne({ customerId: customerId });
return user;
} catch (err) {
throw boom.boomify(err);
}
};
// Edit user info by userId
exports.editUserInfo = async (req, body) => {
try {
const { userId } = req.params;
console.log(customerId)
const userInfo = await User.findById(userId);
const updateData = req.body;
console.log(updateData.firstName);
if (updateData.firstName) userInfo.profile.firstName = updateData.firstName;
if (updateData.lastName) userInfo.profile.lastName = updateData.lastName;
if (updateData.phone) userInfo.profile.contactNumber = updateData.phone;
if (updateData.address1) userInfo.profile.address1 = updateData.address1;
if (updateData.address2) userInfo.profile.address2 = updateData.address2;
if (updateData.city) userInfo.profile.city = updateData.city;
if (updateData.state) userInfo.profile.state = updateData.state;
if (updateData.country) userInfo.profile.country = updateData.country;
if (updateData.zip) userInfo.profile.zip = updateData.zip;
if (updateData.phone) userInfo.phone = updateData.phone;
if (updateData.email) userInfo.emails[0].email = updateData.email;
if (updateData.role) userInfo.profile.role = updateData.role;
const user = await userInfo.save();
return user;
} catch (err) {
throw boom.boomify(err);
}
};
exports.editCuurentUserInfo = async (req, reply) => {
try {
const { customerId } = req.params;
const userInfo = await User.findOne({ customerId: customerId.toString() });
const updateData = req.body;
if (updateData.buildingName) userInfo.buildingName = updateData.buildingName
if (updateData.firstName) userInfo.profile.firstName = updateData.firstName;
if (updateData.lastName) userInfo.profile.lastName = updateData.lastName;
if (updateData.username) userInfo.username = updateData.username;
if (updateData.phone) userInfo.profile.contactNumber = updateData.phone;
if (updateData.address1) userInfo.profile.address1 = updateData.address1;
if (updateData.address2) userInfo.profile.address2 = updateData.address2;
if (updateData.city) userInfo.profile.city = updateData.city;
if (updateData.state) userInfo.profile.state = updateData.state;
if (updateData.country) userInfo.profile.country = updateData.country;
if (updateData.zip) userInfo.profile.zip = updateData.zip;
if (updateData.phone) userInfo.phone = updateData.phone;
if (updateData.emails) userInfo.emails = updateData.emails;
console.log(userInfo.emails[0].email)
if (updateData.role) userInfo.profile.role = updateData.role;
if (updateData.phone) {
const phoneNumber = updateData.phone //libphonenumberjs.parsePhoneNumber(updateData.phone);
if (phoneNumber) {
// access returned collection
if (!phoneNumber) { //if (!phoneNumber.isValid()) {
error = {
armintatankdata: {
error: true,
code: 10002,
message:
"10002 - Phone # " +
updateData.phone +
" is not a valid phone number",
},
};
req.body.regError = error;
reply.status(406).send(error);
}
}
}
if (userInfo.phone == updateData.phone) {
console.log("IF++++++++++++++=");
userInfo.phone = updateData.phone;
userInfo.phoneVerified = true;
} else {
console.log("Ilse++++++++++++++=");
userInfo.phone = updateData.phone;
userInfo.phoneVerified = false;
}
const user = await userInfo.save();
return user;
} catch (err) {
throw boom.boomify(err);
}
};
// Add a new user
// Function accepts username, password , encrypts password and saves it in the database.
exports.addUser = async (req, reply) => {
try {
// await resetCounter();//to set customer id back to 0
var c_id = await generateCustomerId()
var building= ((req.body.buildingName).slice(0, 3)).toUpperCase();
var customer_id = `AWSU${building}${c_id}`
// console.log("This is the reply in the handler after the validations", reply);
userData = {
installationId:req.params.installationId,
customerId: customer_id,
username: req.body.username,
emails: req.body.emails,
password: req.body.password,
phone: req.body.phone,
buildingName: req.body.buildingName,
inchargeName: req.body.inchargeName,
profile: {
firstName: req.body.firstName,
lastName: req.body.lastName,
contactNumber: req.body.phone,
country: req.body.country,
state: req.body.state,
city: req.body.city,
address1: req.body.address1,
address2: req.body.address2,
zip: req.body.zip,
notes: req.body.notes,
},
longitude: req.body.longitude,
latitude:req.body.latitude,
fcmId: req.body.fcmId,
deviceId: req.body.deviceId
};
var user = new User(userData);
//password is not at the top level in the collection.
userpass = req.body.password;
// If fields are sent via form encoding , capture the fields and assign them to the user Object.
checkFormEncoding = isUserFormUrlEncoded(req);
if (checkFormEncoding.isUserFormUrlEncoded) {
usertobeInserted = checkFormEncoding.user;
console.log("thsi true url string");
user.installationId = usertobeInserted.installationId;
user.username = usertobeInserted.username;
user.firstName = usertobeInserted.firstName;
user.lastName = usertobeInserted.lastName;
user.phone = usertobeInserted.phone;
user.emails = usertobeInserted.emails;
user.passsword = usertobeInserted.password;
user.buildingName = usertobeInserted.buildingName;
user.inchargeName = usertobeInserted.inchargeName;
user.customerId = usertobeInserted.customer_id;
user.latitude = usertobeInserted.latitude;
user.longitude = usertobeInserted.longitude
user.fcmId = usertobeInserted.fcmId
user.deviceId = usertobeInserted.deviceId
}
console.log("---------checkurl ecnoded string-----------------------");
// Store hash in your password DB.
hash = await bcryptPassword(userpass);
if (hash) {
user.services.password.bcrypt = hash;
if (req.body.role) {
user.profile.role = req.body.role;
console.log("******************************************************");
console.log(user);
} else {
// override and make the user role as "user" by default
role = ["user"];
user.profile.role = role;
}
insertedUser = await user.save();
console.log(insertedUser);
if (insertedUser) {
// Prepare user object and wrap it inside the armintatankdata
var retUser = {
armintatankdata: {
username: insertedUser.username,
phone: insertedUser.phone,
customerId: insertedUser.customerId,
inchargeName: insertedUser.inchargeName,
buildingName: insertedUser.buildingName,
emails: [
{
email: insertedUser.emails[0].email,
},
],
profile: insertedUser.profile,
longitude: insertedUser.longitude,
latitude:insertedUser.latitude,
fcmId: insertedUser.fcmId,
deviceId: insertedUser.deviceId
},
status_code: 200,
};
return retUser;
}
}
} catch (err) {
throw boom.boomify(err);
}
};
// Login a user
// Accepts a user , password , and checks in the system to see if user exists , and password is valid
// returns a user object so that jwt token can be created and sent back to the client
// exports.loginUser = async (req, fcmIds, deviceId) => {
// try {
// const { phone, password } = req.body;
// let user = await User.findOne({ phone });
// let isStaff = false;
// let staffMember = null;
// // If not a main user, check staff inside all users
// if (!user) {
// const users = await User.find({ "staff.staff.phone": phone });
// for (const u of users) {
// const foundStaff = u.staff.staff.find((s) => s.phone === phone);
// if (foundStaff) {
// user = u; // Assign user as the main user under which the staff exists
// staffMember = foundStaff;
// isStaff = true;
// break;
// }
// }
// }
// // If no user or staff found, return invalid credentials
// if (!user) return { same: false };
// // Validate password
// let isSame = false;
// if (isStaff) {
// isSame = password === staffMember.password; // Plain text comparison for staff
// } else {
// isSame = await bcrypt.compare(password, user.services.password.bcrypt); // Bcrypt for main users
// }
// if (!isSame) return { same: false };
// // Update deviceId
// user.deviceId = deviceId;
// await user.save();
// return { same: true, user, isStaff, staffMember };
// } catch (err) {
// throw boom.boomify(err);
// }
// };
exports.loginUser = async (req, fcmIds, deviceId) => {
try {
const { phone, password } = req.body;
let user = await User.findOne({ phone });
let isStaff = false;
let staffMember = null;
if (!user) {
const users = await User.find({ "staff.staff.phone": phone });
for (const u of users) {
const foundStaff = u.staff.staff.find((s) => s.phone === phone);
if (foundStaff) {
user = u;
staffMember = foundStaff;
isStaff = true;
break;
}
}
}
if (!user) return { same: false };
let isSame = false;
if (isStaff) {
isSame = password === staffMember.password;
} else {
const otpMatch =
//user.oneTimePasswordSetFlag &&
user.passwordResetCode &&
password === user.passwordResetCode.toString();
if (otpMatch) {
isSame = true;
user.oneTimePasswordSetFlag = false;
user.passwordResetCode = null;
} else {
isSame = await bcrypt.compare(password, user.services.password.bcrypt);
}
}
if (!isSame) return { same: false };
user.deviceId = deviceId;
await user.save();
return { same: true, user, isStaff, staffMember };
} catch (err) {
throw boom.boomify(err);
}
};
exports.loginUserWithOTP = async (req) => {
try {
const phone = req.body.phone;
const phoneVerificationCode = req.body.phoneVerificationCode;
const userDetails = await User.findOne({ phone: phone });
const supplier = await Supplier.findOne({phone: phone})
const deliveryBoy = await DeliveryBoy.findOne( { phone : phone})
const installation = await Install.findOne( { phone : phone})
let user;
if(userDetails){
user = await User.findOne({ phone: phone, 'phoneVerificationCode': phoneVerificationCode });
}
if(supplier){
user = await Supplier.findOne({ phone: phone, 'phoneVerificationCode': phoneVerificationCode });
}
if(deliveryBoy){
user = await DeliveryBoy.findOne({ phone: phone, 'phoneVerificationCode': phoneVerificationCode });
}
if(installation){
user = await Install.findOne({ phone: phone, 'phoneVerificationCode': phoneVerificationCode });
}
if (user) {
return { same: true, user: user };
} else {
return { same: false };
}
} catch (err) {
throw boom.boomify(err);
}
};
// Update an existing user
exports.updateUser = async (req, reply) => {
try {
const id = req.params.id;
const user = req.body;
const { ...updateData } = user;
const update = await User.findByIdAndUpdate(id, updateData, { new: true });
return update;
} catch (err) {
throw boom.boomify(err);
}
};
// Delete a user
exports.deleteUser = async (req, reply) => {
try {
const id = req.params.id;
const user = await User.findByIdAndRemove(id);
return user;
} catch (err) {
throw boom.boomify(err);
}
};
//Added the getphone user and delphone user apis for testing purposes
exports.getPhoneUser = async (req, reply) => {
try {
console.log(" requesting the api getPhoneUser , and passing the phone ");
const phone = req.body.phone;
const user = await User.findOne({ phone: phone });
return user;
} catch (err) {
throw boom.boomify(err);
}
};
exports.delPhoneUser = async (req, reply) => {
try {
const phone = req.body.phone;
console.log("deleting users wiht the phone ....", phone);
const user = await User.deleteOne({ phone: phone });
return user;
} catch (err) {
throw boom.boomify(err);
}
};
// exports.uploadProfilePicture = async (req, reply) => {
// try {
// const customerId = req.params.customerId;
// const picture = req.body.picture;
// let profilePicture = await ProfilePicture.findOne({ customerId });
// if (!profilePicture) {
// profilePicture = new ProfilePicture({
// customerId,
// picture,
// });
// } else {
// profilePicture. picture = picture;
// }
// await profilePicture.save();
// reply.send({ message: 'Profile picture uploaded successfully' });
// } catch (error) {
// reply.status(500).send({ error: error.message });
// }
// };
const multer = require('multer');
const fs = require('fs');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
if (!fs.existsSync(__dirname + '/temp')) {
fs.mkdirSync(__dirname + '/temp');
}
cb(null, './temp');
},
filename: function (req, file, cb) {
cb(null, file.originalname + '-' + Date.now() + '.' + file.mimetype.split('/')[1]);
}
});
const upload = multer({ storage: storage }).single('picture'); // Specify the field name used for the file upload
exports.uploadProfilePicture = async (req, reply) => {
try {
upload(req, reply, async (err) => {
if (err) {
reply.status(400).send({ error: 'Failed to upload profile picture' });
return;
}
const customerId = req.params.customerId;
const picturePath = req.file.path;
let profilePicture = await ProfilePicture.findOne({ customerId });
if (!profilePicture) {
profilePicture = new ProfilePicture({
customerId,
picture: fs.readFileSync(picturePath),
});
} else {
profilePicture.picture = fs.readFileSync(picturePath);
}
await profilePicture.save();
// Delete the temporary uploaded file
fs.unlinkSync(picturePath);
reply.send({ message: 'Profile picture uploaded successfully' });
});
} catch (error) {
reply.status(500).send({ error: error.message });
}
};
exports.logout = async (request, reply) => {
const invalidatedTokens = {};
const accessToken = request.headers.authorization && request.body.access_token;
invalidatedTokens[accessToken] = true;
reply.send({ message: 'Logout successful' })
}
// controller.js
const http = require('https');
const { Install } = require("../models/store");
exports.sendSms = async (request, reply) => {
const code = Math.floor(100000 + Math.random() * 900000);
const username = 'Arminta';
const apiKey = '2068323bea61494d315b';
const senderId = 'ARMNTA';
const mobile = request.body.mobileNumbers//'8341426949';
const message = `Welcome to Arminta !!! your OTP is ${code} please use it for login.`//`Welcome to Arminta !!! your OTP is ${code} please use it for login.`;
const user = await User.findOne({phone: mobile})
const supplier = await Supplier.findOne({phone: mobile})
const deliveryBoy = await DeliveryBoy.findOne( { phone : mobile})
const installation = await Install.findOne( { phone : mobile})
if(user){
await User.findOneAndUpdate({phone: mobile}, { $set: {'phoneVerificationCode': code } })
}
if(supplier){
await Supplier.findOneAndUpdate({phone: mobile}, { $set: {'phoneVerificationCode': code } })
}
if(deliveryBoy){
await DeliveryBoy.findOneAndUpdate({phone: mobile}, { $set: {'phoneVerificationCode': code } })
}
if(installation){
await Install.findOneAndUpdate({phone: mobile}, { $set: {'phoneVerificationCode': code } })
}
const apiUrl = `https://smslogin.co/v3/api.php?username=${username}&apikey=${apiKey}&senderid=${senderId}&mobile=${mobile}&message=${encodeURIComponent(message)}`;
const options = {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
};
const req = http.request(apiUrl, options, (res) => {
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
reply.send(data);
});
});
req.on('error', (error) => {
console.error(error);
reply.send({ error: 'Failed to send SMS' });
});
req.end();
}
// exports.forgotPassword = async (req, reply) => {
// try {
// // Create a new User object from the request body
// var user = new User(req.body);
// // Check if the request body is URL encoded
// checkFormEncoding = isUserFormUrlEncoded(req);
// if (checkFormEncoding.isUserFormUrlEncoded) {
// // Extract user information from the request body
// usertobeInserted = checkFormEncoding.user;
// user.username = usertobeInserted.username;
// user.firstName = usertobeInserted.firstName;
// user.lastName = usertobeInserted.lastName;
// user.phone = usertobeInserted.phone;
// user.emails = usertobeInserted.emails;
// }
// // Find a user with the given phone number in the database
// userExists = await User.findOne({
// phone: user.phone,
// });
// if (userExists) {
// // Generate a random password reset code
// const code = Math.floor(100000 + Math.random() * 900000);
// // Convert the code to a string and hash it using bcrypt
// codestr = "";
// codestr = code.toString();
// hash = await bcryptPassword(codestr);
// // Update the user's password reset code and password hash in the database
// const filter = {
// phone: userExists.phone,
// };
// const update = {
// $set: {
// passwordResetCode: code,
// "services.password.bcrypt": hash,
// //oneTimePasswordSetFlag: true,
// },
// };
// const doc = await User.updateOne(filter, update);
// // Find the updated user in the database
// updatedUser = await User.findOne({ phone: userExists.phone });
// if (updatedUser.oneTimePasswordSetFlag) {
// // Send an SMS with the password reset code
// const request = {
// body: {
// mobileNumbers: userExists.phone,
// },
// };
// const response = {
// send: (data) => {
// console.log(data); // Optional: Log the response from the SMS provider
// // Send a success response with the password reset code
// req.body.passwordResetCode = code;
// reply.send('{"armintatankdata":{"error":false,"forgotPassword": true}}');
// },
// };
// await exports.sendSms(request, response);
// } else {
// // Send an error response if the password reset code was not set
// error = {
// armintatankdata: {
// error: true,
// code: 10007,
// message: "10007 - Unable to reset password",
// },
// };
// req.body.regError = error;
// reply.send(error);
// }
// } else {
// // Send an error response if no user was found with the given phone number
// error = {
// armintatankdata: {
// error: true,
// code: 10006,
// message: "10006 - Please check the phone number you entered..",
// },
// };
// req.body.regError = error;
// reply.send(error);
// }
// } catch (err) {
// // Handle any errors that occur during the API request
// throw boom.boomify(err);
// }
// };
exports.forgotPassword = async (req, reply) => {
try {
var user = new User(req.body);
checkFormEncoding = isUserFormUrlEncoded(req);
if (checkFormEncoding.isUserFormUrlEncoded) {
usertobeInserted = checkFormEncoding.user;
user.username = usertobeInserted.username;
user.firstName = usertobeInserted.firstName;
user.lastName = usertobeInserted.lastName;
user.phone = usertobeInserted.phone;
user.emails = usertobeInserted.emails;
}
const userExists = await User.findOne({ phone: user.phone });
if (!userExists) {
return reply.send({
armintatankdata: {
error: true,
code: 10006,
message: "10006 - Please check the phone number you entered.",
},
});
}
// Generate a random 6-digit code
const code = Math.floor(100000 + Math.random() * 900000);
// Store OTP only (not password hash)
const update = {
$set: {
passwordResetCode: code,
oneTimePasswordSetFlag: true,
},
};
await User.updateOne({ phone: userExists.phone }, update);
const updatedUser = await User.findOne({ phone: userExists.phone });
if (updatedUser.oneTimePasswordSetFlag) {
const request = {
body: {
mobileNumbers: userExists.phone,
},
};
const response = {
send: (data) => {
console.log(data);
req.body.passwordResetCode = code;
reply.send({
armintatankdata: {
error: false,
forgotPassword: true,
},
});
},
};
await exports.sendSms(request, response);
} else {
return reply.send({
armintatankdata: {
error: true,
code: 10007,
message: "Unable to reset password",
},
});
}
} catch (err) {
throw boom.boomify(err);
}
};
// exports.forgotPassword = async (req, reply) => {
// try {
// const user = await User.findOne({ phone: req.body.phone });
// if (!user) {
// return reply.send({
// armintatankdata: {
// error: true,
// code: 10006,
// message: "10006 - Please check the phone number you entered..",
// },
// });
// }
// const code = Math.floor(100000 + Math.random() * 900000).toString();
// const hashedOTP = await bcrypt.hash(code, 10);
// await User.updateOne(
// { phone: user.phone },
// {
// $set: {
// "services.password.bcrypt": hashedOTP,
// temporaryPasswordCode: code,
// oneTimePasswordSetFlag: true,
// },
// }
// );
// // Simulated SMS logic
// console.log("OTP sent:", code);
// reply.send({
// armintatankdata: {
// error: false,
// forgotPassword: true,
// },
// });
// } catch (err) {
// throw boom.boomify(err);
// }
// };
exports.changePassword = async (req, reply) => {
try {
const {phone, oldPassword, newPassword } = req.body;
if (!oldPassword || !newPassword) {
return reply.send({
armintatankdata: {
error: true,
code: 10008,
message: "10008 - Old password and new password are required",
},
});
}
// Find user by phone
const user = await User.findOne({ phone });
if (!user) {
return reply.send({
armintatankdata: {
error: true,
code: 10006,
message: "10006 - User not found. Please check the phone number.",
},
});
}
// Verify old password
const isMatch = await bcrypt.compare(oldPassword, user.services.password.bcrypt);
if (!isMatch) {
return reply.send({
armintatankdata: {
error: true,
code: 10009,
message: "10009 - Incorrect old password",
},
});
}
// Hash new password
const hashedPassword = await bcrypt.hash(newPassword, 10);
// Update password
await User.updateOne(
{ phone },
{
$set: {
"services.password.bcrypt": hashedPassword,
oneTimePasswordSetFlag: false, // Reset OTP flag after password change
},
}
);
reply.send({
armintatankdata: {
error: false,
message: "Password changed successfully",
},
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.addingfavoratesupplier = async (req, reply) => {
try {
const { customerId } = req.params;
const { supplierId } = req.query;
if (!supplierId) {
return reply.code(400).send({ status_code: 400, message: "supplierId is required" });
}
// Find user
const user = await User.findOne({ customerId });
if (!user) {
return reply.code(404).send({ status_code: 404, message: "User not found" });
}
// Add supplierId to favorate_suppliers if not already there
if (!user.favorate_suppliers.includes(supplierId)) {
user.favorate_suppliers.push(supplierId);
await user.save();
}
// Fetch FriendRequest status
const friendRequest = await FriendRequest.findOne({ customerId, supplierId });
const status = friendRequest ? friendRequest.status : "not_requested";
reply.send({
status_code: 200,
message: "Supplier added to favorites successfully",
data: {
customerId,
supplierId,
favorate_suppliers: user.favorate_suppliers,
status,
},
});
} catch (err) {
console.error(err);
reply.status(500).send({ status_code: 500, message: err.message });
}
};
exports.forgotPasswordSupplier = async (req, reply) => {
try {
// Create a new Supplier object from the request body
var supplier = new Supplier(req.body);
// Check if the request body is URL encoded
checkFormEncoding = isSupplierFormUrlEncoded(req);
if (checkFormEncoding.isSupplierFormUrlEncoded) {
// Extract supplier information from the request body
suppliertobeInserted = checkFormEncoding.supplier;
supplier.username = suppliertobeInserted.username;
supplier.firstName = suppliertobeInserted.firstName;
supplier.lastName = suppliertobeInserted.lastName;
supplier.phone = suppliertobeInserted.phone;
supplier.emails = suppliertobeInserted.emails;
}
// Find a supplier with the given phone number in the database
supplierExists = await Supplier.findOne({
phone: supplier.phone,
});
if (supplierExists) {
// Generate a random password reset code
const code = Math.floor(100000 + Math.random() * 900000);
// Convert the code to a string and hash it using bcrypt
codestr = "";
codestr = code.toString();
hash = await bcryptPassword(codestr);
// Update the supplier's password reset code and password hash in the database
const filter = {
phone: supplierExists.phone,
};
const update = {
$set: {
passwordResetCode: code,
"services.password.bcrypt": hash,
oneTimePasswordSetFlag: true,
},
};
const doc = await Supplier.updateOne(filter, update);
// Find the updated supplier in the database
updatedSupplier = await Supplier.findOne({ phone: supplierExists.phone });
if (updatedSupplier.oneTimePasswordSetFlag) {
// Send an SMS with the password reset code
const request = {
body: {
mobileNumbers: supplierExists.phone,
},
};
const response = {
send: (data) => {
console.log(data); // Optional: Log the response from the SMS provider
// Send a success response with the password reset code
req.body.passwordResetCode = code;
reply.send('{"armintatankdata":{"error":false,"forgotPassword": true}}');
},
};
await exports.sendSms(request, response);
} else {
// Send an error response if the password reset code was not set
error = {
armintatankdata: {
error: true,
code: 10007,
message: "10007 - Unable to reset password",
},
};
req.body.regError = error;
reply.send(error);
}
} else {
// Send an error response if no supplier was found with the given phone number
error = {
armintatankdata: {
error: true,
code: 10006,
message: "10006 - Please check the phone number you entered..",
},
};
req.body.regError = error;
reply.send(error);
}
} catch (err) {
// Handle any errors that occur during the API request
throw boom.boomify(err);
}
};
exports.addTeamMembers = async (req, reply) => {
try {
const customerId = req.params.customerId
console.log(req.params);
deliveryData = {
customerId: customerId,
teamAdminName: req.body.teamAdminName,
name: req.body.Name,
phone: req.body.phone,
};
var agent_mobile = req.body.phone
var i_agent = await AddTeamMembers.findOne({ phone: agent_mobile})
if(i_agent){
throw new Error('phone already exists');
}
else {
var agent = new AddTeamMembers(deliveryData);
checkFormEncoding = isUserFormUrlEncoded(req);
if (checkFormEncoding.isUserFormUrlEncoded) {
usertobeInserted = checkFormEncoding.agent;
console.log("thsi true url string");
agent.customerId = usertobeInserted.customerId
agent.teamAdminName = usertobeInserted.teamAdminName
agent.name = usertobeInserted.name;
agent.phone = usertobeInserted.phone;
}
}
const insertedagent = await agent.save();
console.log("inster...", insertedagent)
return insertedagent;
} catch (err) {
throw boom.boomify(err);
}
};
exports.deleteTeamMember = async (req, reply) => {
try {
var customerId = req.params.customerId;
var phone = req.query.phone;
const delivery = await AddTeamMembers.findOneAndDelete({
phone: phone,
customerId: customerId,
});
reply.send({ status_code: 200, data: delivery });
} catch (err) {
throw boom.boomify(err);
}
};
exports.editFavoriteSupplier = async (req, reply) => {
try {
const { customerId } = req.params;
const { oldSupplierId, newSupplierId } = req.query;
const user = await User.findOne({ customerId });
if (!user) return reply.code(404).send({ status_code: 404, message: "User not found" });
const index = user.favorate_suppliers.indexOf(oldSupplierId);
if (index === -1)
return reply.code(400).send({ status_code: 400, message: "Old supplier not found in favorites" });
user.favorate_suppliers[index] = newSupplierId;
await user.save();
reply.send({
status_code: 200,
message: "Favorite supplier updated",
data: user.favorate_suppliers,
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.deleteFavoriteSupplier = async (req, reply) => {
try {
const { customerId } = req.params;
const { supplierId } = req.query;
const user = await User.findOne({ customerId });
if (!user) return reply.code(404).send({ status_code: 404, message: "User not found" });
const initialLength = user.favorate_suppliers.length;
user.favorate_suppliers = user.favorate_suppliers.filter(id => id !== supplierId);
if (user.favorate_suppliers.length === initialLength)
return reply.code(400).send({ status_code: 400, message: "Supplier not found in favorites" });
await user.save();
reply.send({
status_code: 200,
message: "Favorite supplier removed",
data: user.favorate_suppliers,
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.updateTeamMember = async (req, reply) => {
try {
var customerId = req.params.customerId;
var phone = req.query.phone;
const delivery = req.body;
const { ...updateData } = delivery;
const update = await AddTeamMembers.findOneAndUpdate(
{ phone: phone, customerId: customerId },
updateData,
{ new: true }
);
console.log(update);
//return update;
reply.send({ status_code: 200, data: update });
} catch (err) {
throw boom.boomify(err);
}
};
exports.createstaff = async (request, reply) => {
try {
const { customerId } = request.params;
const { staff } = request.body;
if (!staff || !Array.isArray(staff)) {
return reply.status(400).send({ error: 'Invalid staff data provided' });
}
// Find user by customerId
const user = await User.findOne({ customerId });
if (!user) {
return reply.status(404).send({ error: 'Customer not found' });
}
// Check for duplicate phone numbers
const existingPhones = new Set(user.staff.staff.map((member) => member.phone));
const newStaff = [];
const duplicatePhones = [];
staff.forEach((member) => {
if (member.phone && existingPhones.has(member.phone)) {
duplicatePhones.push(member.phone);
} else {
if (member.phone) {
existingPhones.add(member.phone);
}
newStaff.push({
name: member.name || null,
phone: member.phone || null,
password: member.password || null,
all_motor_access:member.all_motor_access,
status: "active", // Default status
});
}
});
if (duplicatePhones.length > 0) {
return reply.status(400).send({ error: 'Duplicate phone numbers found', duplicatePhones });
}
// Update the user document with the new staff members
user.staff.staff.push(...newStaff);
// Save the updated user document
await user.save();
reply.send({ message: 'Staff members added successfully', staff: user.staff.staff });
} catch (error) {
console.error('Error creating staff:', error);
reply.status(500).send({ error: 'An error occurred while adding staff' });
}
};
exports.editStaff = async (request, reply) => {
try {
const { customerId, phone } = request.params;
const { name, password,all_motor_access } = request.body;
const user = await User.findOne({ customerId, "staff.staff.phone": phone });
if (!user) {
return reply.status(404).send({ error: 'Staff member not found' });
}
const staffMember = user.staff.staff.find(member => member.phone === phone);
staffMember.name = name || staffMember.name;
staffMember.password = password || staffMember.password;
staffMember.all_motor_access = all_motor_access || staffMember.all_motor_access;
await user.save();
reply.send({ message: 'Staff member updated successfully', staff: staffMember });
} catch (error) {
console.error('Error updating staff member:', error);
reply.status(500).send({ error: 'An error occurred while updating staff' });
}
};
exports.deleteStaff = async (request, reply) => {
try {
const { customerId, phone } = request.params;
const user = await User.findOne({ customerId });
if (!user) {
return reply.status(404).send({ error: 'Customer not found' });
}
const initialLength = user.staff.staff.length;
user.staff.staff = user.staff.staff.filter(member => member.phone !== phone);
if (initialLength === user.staff.staff.length) {
return reply.status(404).send({ error: 'Staff member not found' });
}
await user.save();
reply.send({ message: 'Staff member deleted successfully' });
} catch (error) {
console.error('Error deleting staff member:', error);
reply.status(500).send({ error: 'An error occurred while deleting staff' });
}
};
exports.blockStaff = async (request, reply) => {
try {
const { customerId, phone } = request.params;
const user = await User.findOne({ customerId, "staff.staff.phone": phone });
if (!user) {
return reply.status(404).send({ error: 'Staff member not found' });
}
const staffMember = user.staff.staff.find(member => member.phone === phone);
staffMember.status = 'blocked';
await user.save();
reply.send({ message: 'Staff member blocked successfully', staff: staffMember });
} catch (error) {
console.error('Error blocking staff member:', error);
reply.status(500).send({ error: 'An error occurred while blocking staff' });
}
};
exports.getFavoriteSuppliers = async (req, reply) => {
const { customerId } = req.params;
try {
// Find the user by customerId
const user = await User.findOne({ customerId });
if (!user) {
return reply.status(404).send({ status_code: 404, message: "User not found" });
}
const supplierIds = user.favorate_suppliers || [];
// Get full supplier details for those supplierIds
const suppliers = await Supplier.find({
supplierId: { $in: supplierIds }
}).exec();
reply.send({
status_code: 200,
data: suppliers,
count: suppliers.length
});
} catch (err) {
console.error("Error fetching favorite suppliers:", err);
reply.status(500).send({ status_code: 500, message: "Internal server error" });
}
};
exports.getCartByUserId = async (req, reply) => {
try {
const { customerId } = req.params;
const cart = await Cart.findOne({ customerId }) || { customerId, items: [] };
reply.send({
status_code: 200,
message: "Cart fetched successfully",
data: cart,
});
} catch (err) {
console.error("Error fetching cart:", err);
reply.status(500).send({ error: "Internal server error" });
}
};
exports.addItemToCart = async (req, reply) => {
try {
const { customerId } = req.params;
const { productId, name, quantity, price } = req.body;
let cart = await Cart.findOne({ customerId });
if (!cart) {
cart = new Cart({ customerId, items: [] });
}
const existingItem = cart.items.find(item => item.productId === productId);
if (existingItem) {
existingItem.quantity += quantity;
} else {
cart.items.push({ productId, name, quantity, price });
}
await cart.save();
reply.send({
status_code: 200,
message: "Item added to cart",
data: cart,
});
} catch (err) {
console.error("Error adding item:", err);
reply.status(500).send({ error: "Internal server error" });
}
};
exports.removeItemFromCart = async (req, reply) => {
try {
const { customerId } = req.params;
const { productId } = req.body;
const cart = await Cart.findOne({ customerId });
if (!cart) {
return reply.status(404).send({ error: "Cart not found" });
}
cart.items = cart.items.filter(item => item.productId !== productId);
await cart.save();
reply.send({
status_code: 200,
message: "Item removed from cart",
data: cart,
});
} catch (err) {
console.error("Error removing item:", err);
reply.status(500).send({ error: "Internal server error" });
}
};
exports.clearCart = async (req, reply) => {
try {
const { customerId } = req.params;
const cart = await Cart.findOneAndUpdate(
{ customerId },
{ items: [] },
{ new: true }
);
reply.send({
status_code: 200,
message: "Cart cleared",
data: cart,
});
} catch (err) {
console.error("Error clearing cart:", err);
reply.status(500).send({ error: "Internal server error" });
}
};
exports.getuserOrders = async (req, reply) => {
try {
const { customerId } = req.params;
const orders = await Tankerbooking.find({ customerId }).sort({ createdAt: -1 }).lean();
return reply.send({
status_code: 200,
message: `Orders for customer ${customerId} fetched successfully`,
data: orders
});
} catch (err) {
throw boom.boomify(err);
}
};
exports.getuserRequestbookings = async (req, reply) => {
try {
const { customerId } = req.params;
// 1. Get all bookings
const bookings = await RequestedBooking.find({ customerId }).sort({ createdAt: -1 }).lean();
// 2. Collect all supplierIds used
const allSupplierIds = new Set();
bookings.forEach(booking => {
booking.requested_suppliers?.forEach(s => {
if (s.supplierId) allSupplierIds.add(s.supplierId);
});
});
// 3. Query all supplier details at once
const supplierList = await Supplier.find({
supplierId: { $in: [...allSupplierIds] }
}).lean();
const supplierMap = {};
supplierList.forEach(s => {
supplierMap[s.supplierId] = {
supplierId: s.supplierId,
supplierName: s.suppliername,
phone: s.phone,
longitude: s.longitude,
latitude: s.latitude,
address: s.profile?.office_address,
status: s.status
};
});
// 4. Attach supplier_details inside each requested_suppliers[] object
const enrichedBookings = bookings.map(booking => {
booking.requested_suppliers = booking.requested_suppliers.map(supplier => ({
...supplier,
supplier_details: supplierMap[supplier.supplierId] || null
}));
return booking;
});
// 5. Send final response
return reply.send({
status_code: 200,
message: `Orders for customer ${customerId} fetched successfully`,
data: enrichedBookings
});
} catch (err) {
console.error(err);
throw boom.boomify(err);
}
};
// controllers/user.controller.js (or wherever your controllers live)
// const Supplier = require("../models/supplier.model"); // not needed here
/**
* GET /api/getuserRequestbookingsforsupplier/:supplierId
* Returns bookings where this supplier was requested, showing only this supplier's sub-entry.
*/
exports.getuserRequestbookingsForSupplier = async (req, reply) => {
try {
const { supplierId } = req.params;
if (!supplierId) {
return reply.code(400).send({
status_code: 400,
message: "supplierId is required",
});
}
// 1) Find all bookings that include this supplier
const bookings = await RequestedBooking.find({
"requested_suppliers.supplierId": supplierId,
})
.sort({ createdAt: -1 })
.lean();
if (!bookings.length) {
return reply.send({
status_code: 200,
message: `No orders found for supplier ${supplierId}`,
data: [],
});
}
// 2) Collect all unique customerIds
const customerIds = [...new Set(bookings.map((b) => b.customerId))];
// 3) Fetch user details for those customers
const users = await User.find({ customerId: { $in: customerIds } }).lean();
// 4) Build map for quick lookup
const userMap = users.reduce((acc, u) => {
acc[u.customerId] = u;
return acc;
}, {});
// 5) Format data with user info
const data = bookings.map((b) => {
const mySupplierEntry =
(b.requested_suppliers || []).find(
(s) => s.supplierId === supplierId
) || null;
return {
_id: b._id,
customerId: b.customerId,
type_of_water: b.type_of_water,
capacity: b.capacity,
quantity: b.quantity,
total_required_capacity: b.total_required_capacity,
date: b.date,
time: b.time,
booking_status: b.status,
createdAt: b.createdAt,
updatedAt: b.updatedAt,
// supplier-specific entry
my_supplier_entry: mySupplierEntry,
// attach full user details here
customer_details: userMap[b.customerId] || null,
};
});
return reply.send({
status_code: 200,
message: `Orders for supplier ${supplierId} fetched successfully`,
data,
});
} catch (err) {
console.error(err);
throw boom.boomify(err);
}
};
exports.getuserRequestbookingsforplansforsupplier = async (req, reply) => {
try {
const { supplierId } = req.params;
if (!supplierId) {
return reply.code(400).send({
status_code: 400,
message: "supplierId is required",
});
}
// 1) Find all bookings that include this supplier
const bookings = await RecurringRequestedBooking.find({
"requested_suppliers.supplierId": supplierId,
})
.sort({ createdAt: -1 })
.lean();
// 2) For each booking, expose only this supplier's subdocument
const data = bookings.map((b) => {
const mySupplierEntry = (b.requested_suppliers || []).find(
(s) => s.supplierId === supplierId
) || null;
return {
_id: b._id,
customerId: b.customerId,
type_of_water: b.type_of_water,
capacity: b.capacity,
quantity: b.quantity,
frequency:b.frequency,
weekly_count:b.weekly_count,
total_required_capacity: b.total_required_capacity,
date: b.date,
time: b.time,
// booking-wide status (e.g., pending/confirmed/cancelled)
booking_status: b.status,
createdAt: b.createdAt,
updatedAt: b.updatedAt,
// only the supplier's own requested_suppliers entry
my_supplier_entry: mySupplierEntry, // { supplierId, quoted_amount, time, status }
};
});
return reply.send({
status_code: 200,
message: `Orders for supplier ${supplierId} fetched successfully`,
data,
});
} catch (err) {
console.error(err);
throw boom.boomify(err);
}
};
// Assuming you have these models imported somewhere above:
// const RecurringRequestedBooking = require("...");
// const Supplier = require("...");
exports.getuserRequestbookingsforplansforcustomer = async (req, reply) => {
try {
const { customerId } = req.params;
if (!customerId) {
return reply.code(400).send({
status_code: 400,
message: "customerId is required",
});
}
// 1) Get bookings
const bookings = await RecurringRequestedBooking.find({ customerId })
.sort({ createdAt: -1 })
.lean();
if (!bookings.length) {
return reply.send({
status_code: 200,
message: `Orders for customer ${customerId} fetched successfully`,
data: [],
});
}
// 2) Collect unique supplierIds from requested_suppliers
const supplierIdSet = new Set();
for (const b of bookings) {
const rs = Array.isArray(b.requested_suppliers) ? b.requested_suppliers : [];
for (const s of rs) {
if (s && typeof s.supplierId === "string" && s.supplierId.trim() && s.supplierId !== "string") {
supplierIdSet.add(s.supplierId.trim());
}
}
}
const supplierIds = Array.from(supplierIdSet);
// 3) Fetch suppliers and index by supplierId
const suppliers = supplierIds.length
? await Supplier.find({ supplierId: { $in: supplierIds } })
.select("-__v") // tweak projection as you like
.lean()
: [];
const supplierById = new Map();
for (const s of suppliers) {
// Key is Supplier.supplierId (string), not _id
supplierById.set(s.supplierId, s);
}
// 4) Attach supplier details into each requested_suppliers entry
const data = bookings.map((b) => {
const rs = Array.isArray(b.requested_suppliers) ? b.requested_suppliers : [];
const enriched = rs.map((item) => ({
...item,
supplier: supplierById.get(item?.supplierId) || null, // attach or null if not found
}));
return {
...b,
requested_suppliers: enriched,
};
});
return reply.send({
status_code: 200,
message: `Orders for customer ${customerId} fetched successfully`,
data,
});
} catch (err) {
console.error(err);
throw boom.boomify(err);
}
};
const mongoose = require('mongoose');
exports.acceptRequestedBooking = async (req, reply) => {
const { supplierId } = req.params;
const { action, _id } = req.body;
if (!["accept", "reject"].includes(action)) {
return reply.code(400).send({ message: "Invalid action. Must be 'accept' or 'reject'." });
}
try {
const requestedBooking = await RequestedBooking.findOne({
_id: new mongoose.Types.ObjectId(_id),
'requested_suppliers.supplierId': supplierId
});
if (!requestedBooking) {
return reply.code(404).send({ message: "No matching request for given ID and supplier" });
}
const matchedSupplier = requestedBooking.requested_suppliers.find(s => s.supplierId === supplierId);
if (!matchedSupplier) {
return reply.code(404).send({ message: "Supplier not found in requested_suppliers array" });
}
if (action === "reject") {
matchedSupplier.status = "rejected_by_user";
await requestedBooking.save();
return reply.code(200).send({
status_code: 200,
message: "Supplier request rejected by user",
data: requestedBooking
});
}
// Accept path
requestedBooking.status = 'accepted';
await requestedBooking.save();
const customer = await User.findOne({ customerId: requestedBooking.customerId }).lean();
if (!customer) return reply.code(404).send({ message: "Customer not found" });
const supplier = await Supplier.findOne({ supplierId }).lean();
if (!supplier) return reply.code(404).send({ message: "Supplier not found" });
if (!matchedSupplier.quoted_amount) {
return reply.code(400).send({ message: "Quoted amount missing for this supplier" });
}
requestedBooking.requested_suppliers = requestedBooking.requested_suppliers.filter(
s => s.supplierId !== supplierId
);
// ✅ Optional: Mark booking as fully processed if no more suppliers remain
if (requestedBooking.requested_suppliers.length === 0) {
requestedBooking.status = 'processed';
}
await requestedBooking.save();
// Format: ARM + YYYYMMDD + random digit (09)
const today = new Date();
const datePart = today.toISOString().slice(0, 10).replace(/-/g, ''); // YYYYMMDD
const randomDigit = Math.floor(Math.random() * 10); // 09
const bookingId = `ARM${datePart}${randomDigit}`;
const amount_due = matchedSupplier.quoted_amount-matchedSupplier.advance_paid
const newBooking = new Tankerbooking({
bookingid: bookingId,
customerId: customer.customerId,
customerName: customer.profile.firstName,
customerPhone: customer.phone,
address: customer.address1,
latitude: customer.latitude,
longitude: customer.longitude,
supplierId: supplier.supplierId,
supplierName: supplier.suppliername,
supplierPhone: supplier.phone,
supplierAddress: customer.address,
amount_paid: String(matchedSupplier.advance_paid),
amount_due: String(amount_due),
advance_reference_number: matchedSupplier.advance_ref_number,
type_of_water: requestedBooking.type_of_water,
capacity: requestedBooking.capacity,
quantity: requestedBooking.quantity,
total_required_capacity: requestedBooking.total_required_capacity,
expectedDateOfDelivery: requestedBooking.date,
time: requestedBooking.time,
price: matchedSupplier.quoted_amount,
status: 'pending'
});
await newBooking.save();
reply.code(200).send({
status_code: 200,
message: "Booking accepted and moved to tanker bookings",
data: newBooking
});
} catch (err) {
console.error(err);
throw boom.internal("Failed to handle booking action", err);
}
};
exports.getordersofcustomer = async (req, reply) => {
try {
const customerId = req.params.customerId;
// Find the specific tank
const mainTank = await Tankerbooking.find({
customerId: customerId,
});
if (!mainTank) {
return reply.send({ status_code: 404, error: "Main tank not found" });
}
// Send the found tank within a list
reply.send({ status_code: 200, data: [mainTank] });
} catch (err) {
throw boom.boomify(err);
}
};
exports.getallsuppliers = async (req, reply) => {
try {
// Find the specific tank
const suppliers = await Supplier.find({
});
if (!suppliers) {
return reply.send({ status_code: 404, error: "suppliers not found" });
}
// Send the found tank within a list
reply.send({ status_code: 200, data: [suppliers] });
} catch (err) {
throw boom.boomify(err);
}
};
exports.estimationsget = async (req, reply) => {
try {
// Find the specific tank
const estimations = await EstimationOrder.find({customerId:req.params.customerId
});
if (!estimations) {
return reply.send({ status_code: 404, error: "estimations not found" });
}
// Send the found tank within a list
reply.send({ status_code: 200, data: [estimations] });
} catch (err) {
throw boom.boomify(err);
}
};
exports.updatePaymentForBooking = async (req, reply) => {
try {
const { bookingid } = req.params;
const { payment_mode, payment_reference_number } = req.body;
if (!bookingid) {
return reply.code(400).send({
status_code: 400,
message: 'bookingid (param) is required',
});
}
if (typeof payment_mode === 'undefined' && typeof payment_reference_number === 'undefined') {
return reply.code(400).send({
status_code: 400,
message: 'At least one of payment_mode or payment_reference_number must be provided in body',
});
}
const update = {};
if (typeof payment_mode !== 'undefined') update.payment_mode = payment_mode;
if (typeof payment_reference_number !== 'undefined') update.payment_reference_number = payment_reference_number;
const updated = await Tankerbooking.findOneAndUpdate(
{ bookingid },
{ $set: update },
{ new: true, runValidators: true }
).lean();
if (!updated) {
return reply.code(404).send({
status_code: 404,
message: `No booking found with bookingid ${bookingid}`,
});
}
return reply.code(200).send({
status_code: 200,
message: 'Payment info updated successfully',
data: updated,
});
} catch (err) {
console.error('updatePaymentForBooking error:', err);
// keep using boom as you used earlier
throw boom.boomify(err);
}
};
// controllers/recurringRequestedBookingController.js
exports.updateQuotedAmountForSupplier = async (req, reply) => {
try {
const { _id } = req.params;
const { supplierId, amount } = req.body;
if (!_id) {
return reply.code(400).send({ status_code: 400, message: '_id (param) is required' });
}
if (!supplierId) {
return reply.code(400).send({ status_code: 400, message: 'supplierId (body) is required' });
}
if (typeof amount === 'undefined' || amount === null || amount === '') {
return reply.code(400).send({ status_code: 400, message: 'amount (body) is required' });
}
// convert amount to number if possible
const numericAmount = Number(amount);
if (Number.isNaN(numericAmount)) {
return reply.code(400).send({ status_code: 400, message: 'amount must be a valid number' });
}
// Atomic update using positional $ operator
const filter = { _id, 'requested_suppliers.supplierId': supplierId };
const update = { $set: { 'requested_suppliers.$.quoted_amount': numericAmount } };
const updated = await RequestedBooking.findOneAndUpdate(filter, update, {
new: true,
runValidators: true,
}).lean();
if (!updated) {
// either booking _id not found OR supplierId not found inside requested_suppliers
// let's check which one
const bookingExists = await RequestedBooking.findById(_id).lean();
if (!bookingExists) {
return reply.code(404).send({ status_code: 404, message: `Booking with _id ${_id} not found` });
}
// booking exists but supplier entry missing
return reply.code(404).send({
status_code: 404,
message: `Supplier ${supplierId} not found in requested_suppliers for booking ${_id}`,
});
}
return reply.code(200).send({
status_code: 200,
message: `quoted_amount updated for supplier ${supplierId}`,
data: updated,
});
} catch (err) {
console.error('updateQuotedAmountForSupplier error:', err);
throw boom.boomify(err);
}
};
exports.updatestatusForSupplier = async (req, reply) => {
try {
const { _id } = req.params;
const { supplierId, status } = req.body;
if (!_id) {
return reply.code(400).send({ status_code: 400, message: '_id (param) is required' });
}
if (!supplierId) {
return reply.code(400).send({ status_code: 400, message: 'supplierId (body) is required' });
}
if (typeof status === 'undefined' || status === null || String(status).trim() === '') {
return reply.code(400).send({ status_code: 400, message: 'status (body) is required' });
}
// Map short keywords to the stored values
let statusToSave = String(status).trim().toLowerCase();
if (statusToSave === 'accept') statusToSave = 'accepted_by_user';
else if (statusToSave === 'reject') statusToSave = 'rejected_by_user';
// otherwise keep the original (but normalized) value
// Atomic update using positional $ operator
const filter = { _id, 'requested_suppliers.supplierId': supplierId };
const update = { $set: { 'requested_suppliers.$.status': statusToSave } };
const updated = await RequestedBooking.findOneAndUpdate(filter, update, {
new: true,
runValidators: true,
}).lean();
if (!updated) {
// either booking _id not found OR supplierId not found inside requested_suppliers
const bookingExists = await RequestedBooking.findById(_id).lean();
if (!bookingExists) {
return reply.code(404).send({ status_code: 404, message: `Booking with _id ${_id} not found` });
}
// booking exists but supplier entry missing
return reply.code(404).send({
status_code: 404,
message: `Supplier ${supplierId} not found in requested_suppliers for booking ${_id}`,
});
}
return reply.code(200).send({
status_code: 200,
message: `status updated for supplier ${supplierId}`,
data: updated,
});
} catch (err) {
console.error('updatestatusForSupplier error:', err);
throw boom.boomify(err);
}
};
exports.updateadvanceForSupplier = async (req, reply) => {
try {
const { _id } = req.params;
const { supplierId, advance_paid,advance_ref_number } = req.body;
if (!_id) {
return reply.code(400).send({ status_code: 400, message: '_id (param) is required' });
}
if (!supplierId) {
return reply.code(400).send({ status_code: 400, message: 'supplierId (body) is required' });
}
// Map short keywords to the stored values
// otherwise keep the original (but normalized) value
// Atomic update using positional $ operator
const filter = { _id, 'requested_suppliers.supplierId': supplierId };
const update = { $set: { 'requested_suppliers.$.advance_paid': advance_paid,'requested_suppliers.$.advance_ref_number': advance_ref_number } };
const updated = await RequestedBooking.findOneAndUpdate(filter, update, {
new: true,
runValidators: true,
}).lean();
if (!updated) {
// either booking _id not found OR supplierId not found inside requested_suppliers
const bookingExists = await RequestedBooking.findById(_id).lean();
if (!bookingExists) {
return reply.code(404).send({ status_code: 404, message: `Booking with _id ${_id} not found` });
}
// booking exists but supplier entry missing
return reply.code(404).send({
status_code: 404,
message: `Supplier ${supplierId} not found in requested_suppliers for booking ${_id}`,
});
}
return reply.code(200).send({
status_code: 200,
message: `status updated for supplier ${supplierId}`,
data: updated,
});
} catch (err) {
console.error('updatestatusForSupplier error:', err);
throw boom.boomify(err);
}
};
exports.splitBookingForSupplier = async (req, reply) => {
try {
const { id } = req.params;
const { capacity, quantity, date, time, quoted_amount } = req.body;
// 1) Find existing booking
const existing = await RequestedBooking.findById(id);
if (!existing) {
return reply.code(404).send({ status_code: 404, message: "Booking not found" });
}
// 2) Update the original booking
existing.capacity = `${capacity} L`;
existing.quantity = "1";
existing.total_required_capacity = capacity;
if (date) existing.date = date;
if (time) existing.time = time;
if (quoted_amount) {
existing.requested_suppliers[0].quoted_amount = quoted_amount;
}
await existing.save();
// 3) Create new bookings for the rest
const newBookings = [];
for (let i = 1; i < quantity; i++) {
const newBooking = new RequestedBooking({
status: "pending",
customerId: existing.customerId,
type_of_water: existing.type_of_water,
capacity: `${capacity} L`,
quantity: "1",
total_required_capacity: capacity,
date: date || existing.date,
time: time || existing.time,
requested_suppliers: [
{
time: new Date().toISOString().slice(0, 16).replace("T", " "),
status: "pending",
supplierId: existing.requested_suppliers[0].supplierId,
quoted_amount: quoted_amount || existing.requested_suppliers[0].quoted_amount,
},
],
});
newBookings.push(newBooking);
}
if (newBookings.length > 0) {
await RequestedBooking.insertMany(newBookings);
}
return reply.code(200).send({
status_code: 200,
message: `${quantity} booking(s) created/updated successfully`,
updated: existing,
newEntries: newBookings,
});
} catch (err) {
console.error("splitBookingForSupplier error:", err);
return reply.code(500).send({ status_code: 500, message: "Internal Server Error" });
}
};