|
|
@ -1138,18 +1138,131 @@ fastify.post("/api/uploads-material-recieved/:customerId/:installationId", async
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fastify.post("/api/installLogin", {
|
|
|
|
|
|
|
|
// schema: {
|
|
|
|
|
|
|
|
// description: "This is for Login Install",
|
|
|
|
|
|
|
|
// tags: ["Installation"],
|
|
|
|
|
|
|
|
// summary: "This is for Login Install",
|
|
|
|
|
|
|
|
// body: {
|
|
|
|
|
|
|
|
// type: "object",
|
|
|
|
|
|
|
|
// required: ["type", "phone", "password"],
|
|
|
|
|
|
|
|
// properties: {
|
|
|
|
|
|
|
|
// type: { type: "string", description: "User role type (e.g., 'admin', 'manager')" },
|
|
|
|
|
|
|
|
// phone: { type: "string", description: "Registered phone number" },
|
|
|
|
|
|
|
|
// password: { type: "string", description: "Password for authentication" },
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// async handler(req, reply) {
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
|
|
|
// const { type, phone, password } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Check if user exists in the Department Schema
|
|
|
|
|
|
|
|
// const user = await Deparments.findOne({ phone });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!user) {
|
|
|
|
|
|
|
|
// return reply.code(400).send({ message: "User not found" });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Verify Password
|
|
|
|
|
|
|
|
// const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!isMatch) {
|
|
|
|
|
|
|
|
// return reply.code(400).send({ message: "Invalid credentials" });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Check if department details already exist in installation schema
|
|
|
|
|
|
|
|
// let installation = await Install.findOne({ phone });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!installation) {
|
|
|
|
|
|
|
|
// // Create a new entry in installation schema with departmentId as installationId
|
|
|
|
|
|
|
|
// installation = new Install({
|
|
|
|
|
|
|
|
// phone: user.phone,
|
|
|
|
|
|
|
|
// installationId: user.departmentId, // Store departmentId in installationId
|
|
|
|
|
|
|
|
// firstName: user.firstName,
|
|
|
|
|
|
|
|
// lastName: user.lastName,
|
|
|
|
|
|
|
|
// email: user.email,
|
|
|
|
|
|
|
|
// alternativeNumber: user.alternativeContactNumber,
|
|
|
|
|
|
|
|
// departmentName: user.departmentName,
|
|
|
|
|
|
|
|
// designation: user.desginationName,
|
|
|
|
|
|
|
|
// reportingManager: user.reportingManager,
|
|
|
|
|
|
|
|
// city: user.city,
|
|
|
|
|
|
|
|
// zone: user.zone,
|
|
|
|
|
|
|
|
// address1: user.address1,
|
|
|
|
|
|
|
|
// address2: user.address2,
|
|
|
|
|
|
|
|
// profile: {
|
|
|
|
|
|
|
|
// state: user.state,
|
|
|
|
|
|
|
|
// country: user.country,
|
|
|
|
|
|
|
|
// role: type, // Store type in profile.role
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// await installation.save();
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Ensure `type` is stored in `profile.role`
|
|
|
|
|
|
|
|
// if (!installation.profile?.role) {
|
|
|
|
|
|
|
|
// installation.profile.role = type;
|
|
|
|
|
|
|
|
// await installation.save(); // Save the updated type
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Fetch profile picture if available
|
|
|
|
|
|
|
|
// const profilePicture = await ProfilePictureInstall.findOne({ customerId: installation._id });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Generate JWT Token
|
|
|
|
|
|
|
|
// const token = fastify.jwt.sign(
|
|
|
|
|
|
|
|
// { userId: user._id, phone: user.phone, role: installation.profile?.role },
|
|
|
|
|
|
|
|
// "your_secret_key",
|
|
|
|
|
|
|
|
// { expiresIn: "7d" }
|
|
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Construct response payload
|
|
|
|
|
|
|
|
// const responsePayload = {
|
|
|
|
|
|
|
|
// simplydata: {
|
|
|
|
|
|
|
|
// error: false,
|
|
|
|
|
|
|
|
// apiversion: fastify.config.APIVERSION,
|
|
|
|
|
|
|
|
// access_token: token,
|
|
|
|
|
|
|
|
// email: installation.emails || [],
|
|
|
|
|
|
|
|
// installationId: installation.installationId,
|
|
|
|
|
|
|
|
// phone: installation.phone,
|
|
|
|
|
|
|
|
// address1: installation.address1,
|
|
|
|
|
|
|
|
// address2: installation.address2,
|
|
|
|
|
|
|
|
// phoneVerified: installation.phoneVerified,
|
|
|
|
|
|
|
|
// oneTimePasswordSetFlag: installation.oneTimePasswordSetFlag,
|
|
|
|
|
|
|
|
// type: installation.profile?.role || "user", // Default to "user" if not available
|
|
|
|
|
|
|
|
// fcmIds: installation.fcmId || null,
|
|
|
|
|
|
|
|
// team: installation.team,
|
|
|
|
|
|
|
|
// city: installation.city,
|
|
|
|
|
|
|
|
// manager: installation.manager,
|
|
|
|
|
|
|
|
// firstName: installation.firstName,
|
|
|
|
|
|
|
|
// lastName: installation.lastName,
|
|
|
|
|
|
|
|
// address: installation.address || "",
|
|
|
|
|
|
|
|
// alternativeNumber: installation.alternativeNumber || null,
|
|
|
|
|
|
|
|
// profilePicture: profilePicture ? profilePicture.pictureUrl : null, // Include profile picture URL if available
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// return reply.send(responsePayload);
|
|
|
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
|
|
|
// console.error("Login Error:", error);
|
|
|
|
|
|
|
|
// return reply.code(500).send({ message: "Internal server error" });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fastify.post("/api/installLogin", {
|
|
|
|
fastify.post("/api/installLogin", {
|
|
|
|
schema: {
|
|
|
|
schema: {
|
|
|
|
description: "This is for Login Install",
|
|
|
|
description: "Login as Installation Manager",
|
|
|
|
tags: ["Installation"],
|
|
|
|
tags: ["Installation"],
|
|
|
|
summary: "This is for Login Install",
|
|
|
|
summary: "Installation Manager login",
|
|
|
|
body: {
|
|
|
|
body: {
|
|
|
|
type: "object",
|
|
|
|
type: "object",
|
|
|
|
required: ["type", "phone", "password"],
|
|
|
|
required: ["type", "phone", "password"],
|
|
|
|
properties: {
|
|
|
|
properties: {
|
|
|
|
type: { type: "string", description: "User role type (e.g., 'admin', 'manager')" },
|
|
|
|
type: { type: "string", enum: ["Installation_Manager"], description: "Login type" },
|
|
|
|
phone: { type: "string", description: "Registered phone number" },
|
|
|
|
phone: { type: "string", description: "Registered phone number" },
|
|
|
|
password: { type: "string", description: "Password for authentication" },
|
|
|
|
password: { type: "string", description: "Password" },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
@ -1157,28 +1270,24 @@ fastify.post("/api/installLogin", {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const { type, phone, password } = req.body;
|
|
|
|
const { type, phone, password } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
// Check if user exists in the Department Schema
|
|
|
|
// Find department record
|
|
|
|
const user = await Deparments.findOne({ phone });
|
|
|
|
const user = await Deparments.findOne({ phone }).lean();
|
|
|
|
|
|
|
|
|
|
|
|
if (!user) {
|
|
|
|
if (!user) {
|
|
|
|
return reply.code(400).send({ message: "User not found" });
|
|
|
|
return reply.code(400).send({ message: "User not found" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Verify Password
|
|
|
|
// Validate password
|
|
|
|
const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);
|
|
|
|
const isMatch = await bcrypt.compare(password, user.services.password.bcrypt);
|
|
|
|
|
|
|
|
|
|
|
|
if (!isMatch) {
|
|
|
|
if (!isMatch) {
|
|
|
|
return reply.code(400).send({ message: "Invalid credentials" });
|
|
|
|
return reply.code(401).send({ message: "Invalid credentials" });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if department details already exist in installation schema
|
|
|
|
// Find or create installation document
|
|
|
|
let installation = await Install.findOne({ phone });
|
|
|
|
let installation = await Install.findOne({ phone });
|
|
|
|
|
|
|
|
|
|
|
|
if (!installation) {
|
|
|
|
if (!installation) {
|
|
|
|
// Create a new entry in installation schema with departmentId as installationId
|
|
|
|
|
|
|
|
installation = new Install({
|
|
|
|
installation = new Install({
|
|
|
|
phone: user.phone,
|
|
|
|
phone,
|
|
|
|
installationId: user.departmentId, // Store departmentId in installationId
|
|
|
|
installationId: user.departmentId,
|
|
|
|
firstName: user.firstName,
|
|
|
|
firstName: user.firstName,
|
|
|
|
lastName: user.lastName,
|
|
|
|
lastName: user.lastName,
|
|
|
|
email: user.email,
|
|
|
|
email: user.email,
|
|
|
@ -1193,194 +1302,269 @@ fastify.post("/api/installLogin", {
|
|
|
|
profile: {
|
|
|
|
profile: {
|
|
|
|
state: user.state,
|
|
|
|
state: user.state,
|
|
|
|
country: user.country,
|
|
|
|
country: user.country,
|
|
|
|
role: type, // Store type in profile.role
|
|
|
|
role: type, // store login type
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await installation.save();
|
|
|
|
await installation.save();
|
|
|
|
}
|
|
|
|
} else if (!installation.profile?.role) {
|
|
|
|
|
|
|
|
|
|
|
|
// Ensure `type` is stored in `profile.role`
|
|
|
|
|
|
|
|
if (!installation.profile?.role) {
|
|
|
|
|
|
|
|
installation.profile.role = type;
|
|
|
|
installation.profile.role = type;
|
|
|
|
await installation.save(); // Save the updated type
|
|
|
|
await installation.save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Fetch profile picture if available
|
|
|
|
// Generate JWT
|
|
|
|
const profilePicture = await ProfilePictureInstall.findOne({ customerId: installation._id });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate JWT Token
|
|
|
|
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
{ userId: user._id, phone: user.phone, role: installation.profile?.role },
|
|
|
|
{ userId: user._id, phone, role: type },
|
|
|
|
"your_secret_key",
|
|
|
|
"your_secret_key", // replace with config
|
|
|
|
{ expiresIn: "7d" }
|
|
|
|
{ expiresIn: "7d" }
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// Construct response payload
|
|
|
|
return reply.send({
|
|
|
|
const responsePayload = {
|
|
|
|
success: true,
|
|
|
|
simplydata: {
|
|
|
|
message: "Login successful",
|
|
|
|
error: false,
|
|
|
|
data: {
|
|
|
|
apiversion: fastify.config.APIVERSION,
|
|
|
|
|
|
|
|
access_token: token,
|
|
|
|
access_token: token,
|
|
|
|
email: installation.emails || [],
|
|
|
|
|
|
|
|
installationId: installation.installationId,
|
|
|
|
installationId: installation.installationId,
|
|
|
|
phone: installation.phone,
|
|
|
|
phone: installation.phone,
|
|
|
|
address1: installation.address1,
|
|
|
|
|
|
|
|
address2: installation.address2,
|
|
|
|
|
|
|
|
phoneVerified: installation.phoneVerified,
|
|
|
|
|
|
|
|
oneTimePasswordSetFlag: installation.oneTimePasswordSetFlag,
|
|
|
|
|
|
|
|
type: installation.profile?.role || "user", // Default to "user" if not available
|
|
|
|
|
|
|
|
fcmIds: installation.fcmId || null,
|
|
|
|
|
|
|
|
team: installation.team,
|
|
|
|
|
|
|
|
city: installation.city,
|
|
|
|
|
|
|
|
manager: installation.manager,
|
|
|
|
|
|
|
|
firstName: installation.firstName,
|
|
|
|
firstName: installation.firstName,
|
|
|
|
lastName: installation.lastName,
|
|
|
|
lastName: installation.lastName,
|
|
|
|
address: installation.address || "",
|
|
|
|
city: installation.city,
|
|
|
|
alternativeNumber: installation.alternativeNumber || null,
|
|
|
|
email: installation.emails?.map(e => e.email) || [],
|
|
|
|
profilePicture: profilePicture ? profilePicture.pictureUrl : null, // Include profile picture URL if available
|
|
|
|
type: installation.profile?.role || type,
|
|
|
|
|
|
|
|
team: installation.team,
|
|
|
|
|
|
|
|
manager: installation.manager,
|
|
|
|
|
|
|
|
fcmId: installation.fcmId,
|
|
|
|
|
|
|
|
alternativeNumber: installation.alternativeNumber,
|
|
|
|
|
|
|
|
phoneVerified: installation.phoneVerified,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
return reply.send(responsePayload);
|
|
|
|
console.error("installLogin error:", err);
|
|
|
|
} catch (error) {
|
|
|
|
reply.code(500).send({ message: "Internal server error" });
|
|
|
|
console.error("Login Error:", error);
|
|
|
|
}
|
|
|
|
return reply.code(500).send({ message: "Internal server error" });
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fastify.post("/api/teamMemberLogin", {
|
|
|
|
|
|
|
|
// schema: {
|
|
|
|
|
|
|
|
// description: "Login API for team members",
|
|
|
|
|
|
|
|
// tags: ["Installation"],
|
|
|
|
|
|
|
|
// summary: "Login as a Team Member",
|
|
|
|
|
|
|
|
// body: {
|
|
|
|
|
|
|
|
// type: "object",
|
|
|
|
|
|
|
|
// required: ["type", "phone", "password"],
|
|
|
|
|
|
|
|
// properties: {
|
|
|
|
|
|
|
|
// type: { type: "string", description: "Role type of the user (e.g., 'team_member')" },
|
|
|
|
|
|
|
|
// phone: { type: "string", description: "Registered phone number of the team member" },
|
|
|
|
|
|
|
|
// password: { type: "string", description: "Password for authentication" },
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// async handler(request, reply) {
|
|
|
|
|
|
|
|
// try {
|
|
|
|
|
|
|
|
// const { type, phone, password } = request.body;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // ✅ Step 1: Find the team member in `Deparments`
|
|
|
|
|
|
|
|
// const department = await Deparments.findOne({
|
|
|
|
|
|
|
|
// "team_member.team_member.phone": phone
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!department) {
|
|
|
|
|
|
|
|
// return reply.status(401).send({
|
|
|
|
|
|
|
|
// simplydata: {
|
|
|
|
|
|
|
|
// error: true,
|
|
|
|
|
|
|
|
// message: "Invalid phone number",
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // ✅ Step 2: Find the specific team member
|
|
|
|
|
|
|
|
// const teamMember = department.team_member.team_member.find(
|
|
|
|
|
|
|
|
// (member) => member.phone === phone
|
|
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!teamMember) {
|
|
|
|
|
|
|
|
// return reply.status(401).send({
|
|
|
|
|
|
|
|
// simplydata: {
|
|
|
|
|
|
|
|
// error: true,
|
|
|
|
|
|
|
|
// message: "Invalid phone number",
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // ✅ Step 3: Verify password
|
|
|
|
|
|
|
|
// const isPasswordValid = await bcrypt.compare(password, teamMember.password);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!isPasswordValid) {
|
|
|
|
|
|
|
|
// return reply.status(401).send({
|
|
|
|
|
|
|
|
// simplydata: {
|
|
|
|
|
|
|
|
// error: true,
|
|
|
|
|
|
|
|
// message: "Invalid phone number or password",
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// console.log("Team Member First Name:", teamMember.firstName); // ✅ Debugging
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // ✅ Step 4: Check if this team member already exists in `Install`
|
|
|
|
|
|
|
|
// let installation = await Install.findOne({
|
|
|
|
|
|
|
|
// installationId: department.departmentId
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!installation) {
|
|
|
|
|
|
|
|
// return reply.status(404).send({
|
|
|
|
|
|
|
|
// simplydata: {
|
|
|
|
|
|
|
|
// error: true,
|
|
|
|
|
|
|
|
// message: "Installation not found",
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // Check if team member already exists in Install schema
|
|
|
|
|
|
|
|
// const existingTeamMember = installation.team_member.team_member.find(
|
|
|
|
|
|
|
|
// (member) => member.phone === phone
|
|
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (!existingTeamMember) {
|
|
|
|
|
|
|
|
// // ✅ Step 5: Add team member details to `Install` schema
|
|
|
|
|
|
|
|
// installation.team_member.team_member.push({
|
|
|
|
|
|
|
|
// teamMemberId: teamMember.teamMemberId,
|
|
|
|
|
|
|
|
// firstName: teamMember.firstName,
|
|
|
|
|
|
|
|
// phone: teamMember.phone,
|
|
|
|
|
|
|
|
// email: teamMember.email,
|
|
|
|
|
|
|
|
// alternativePhone: teamMember.alternativePhone,
|
|
|
|
|
|
|
|
// installationTeamMemId: installation.installationId,
|
|
|
|
|
|
|
|
// password: teamMember.password, // Store hashed password
|
|
|
|
|
|
|
|
// status: teamMember.status || "active",
|
|
|
|
|
|
|
|
// type: type, // Store login type
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// await installation.save();
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // ✅ Step 6: Generate JWT token
|
|
|
|
|
|
|
|
// const token = fastify.jwt.sign(
|
|
|
|
|
|
|
|
// { phone: teamMember.phone, role: type, installationId: installation.installationId },
|
|
|
|
|
|
|
|
// "JWT_SECRET",
|
|
|
|
|
|
|
|
// { expiresIn: "1h" }
|
|
|
|
|
|
|
|
// );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// return reply.send({
|
|
|
|
|
|
|
|
// simplydata: {
|
|
|
|
|
|
|
|
// error: false,
|
|
|
|
|
|
|
|
// message: "Login successful",
|
|
|
|
|
|
|
|
// access_token: token,
|
|
|
|
|
|
|
|
// phone: teamMember.phone,
|
|
|
|
|
|
|
|
// firstName: teamMember.firstName || null, // ✅ Now included
|
|
|
|
|
|
|
|
// teamMemberId: teamMember.teamMemberId,
|
|
|
|
|
|
|
|
// alternativePhone: teamMember.alternativePhone || null,
|
|
|
|
|
|
|
|
// email: teamMember.email || null,
|
|
|
|
|
|
|
|
// status: teamMember.status || "active",
|
|
|
|
|
|
|
|
// type: teamMember.type,
|
|
|
|
|
|
|
|
// installationId: installation.installationId
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// } catch (err) {
|
|
|
|
|
|
|
|
// console.error("Error logging in:", err);
|
|
|
|
|
|
|
|
// reply.status(500).send({
|
|
|
|
|
|
|
|
// simplydata: {
|
|
|
|
|
|
|
|
// error: true,
|
|
|
|
|
|
|
|
// message: "Internal server error",
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// },
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fastify.post("/api/teamMemberLogin", {
|
|
|
|
fastify.post("/api/teamMemberLogin", {
|
|
|
|
schema: {
|
|
|
|
schema: {
|
|
|
|
description: "Login API for team members",
|
|
|
|
description: "Login as Installation Team Member",
|
|
|
|
tags: ["Installation"],
|
|
|
|
tags: ["Installation"],
|
|
|
|
summary: "Login as a Team Member",
|
|
|
|
summary: "Team member login",
|
|
|
|
body: {
|
|
|
|
body: {
|
|
|
|
type: "object",
|
|
|
|
type: "object",
|
|
|
|
required: ["type", "phone", "password"],
|
|
|
|
required: ["type", "phone", "password"],
|
|
|
|
properties: {
|
|
|
|
properties: {
|
|
|
|
type: { type: "string", description: "Role type of the user (e.g., 'team_member')" },
|
|
|
|
type: { type: "string", enum: ["Installation_TeamMember"], description: "Login type" },
|
|
|
|
phone: { type: "string", description: "Registered phone number of the team member" },
|
|
|
|
phone: { type: "string", description: "Team member phone" },
|
|
|
|
password: { type: "string", description: "Password for authentication" },
|
|
|
|
password: { type: "string", description: "Password" },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
async handler(request, reply) {
|
|
|
|
async handler(req, reply) {
|
|
|
|
try {
|
|
|
|
try {
|
|
|
|
const { type, phone, password } = request.body;
|
|
|
|
const { type, phone, password } = req.body;
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Step 1: Find the team member in `Deparments`
|
|
|
|
|
|
|
|
const department = await Deparments.findOne({
|
|
|
|
|
|
|
|
"team_member.team_member.phone": phone
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Find department with this team member phone
|
|
|
|
|
|
|
|
const department = await Deparments.findOne({ "team_member.team_member.phone": phone }).lean();
|
|
|
|
if (!department) {
|
|
|
|
if (!department) {
|
|
|
|
return reply.status(401).send({
|
|
|
|
return reply.code(401).send({ message: "Invalid phone number" });
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Step 2: Find the specific team member
|
|
|
|
// Find the actual team member
|
|
|
|
const teamMember = department.team_member.team_member.find(
|
|
|
|
const teamMember = department.team_member.team_member.find(m => m.phone === phone);
|
|
|
|
(member) => member.phone === phone
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!teamMember) {
|
|
|
|
if (!teamMember) {
|
|
|
|
return reply.status(401).send({
|
|
|
|
return reply.code(401).send({ message: "Invalid phone number" });
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Step 3: Verify password
|
|
|
|
// Validate password
|
|
|
|
const isPasswordValid = await bcrypt.compare(password, teamMember.password);
|
|
|
|
const isMatch = await bcrypt.compare(password, teamMember.password);
|
|
|
|
|
|
|
|
if (!isMatch) {
|
|
|
|
if (!isPasswordValid) {
|
|
|
|
return reply.code(401).send({ message: "Invalid credentials" });
|
|
|
|
return reply.status(401).send({
|
|
|
|
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Invalid phone number or password",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
console.log("Team Member First Name:", teamMember.firstName); // ✅ Debugging
|
|
|
|
// Find install document
|
|
|
|
|
|
|
|
const installation = await Install.findOne({ installationId: department.departmentId });
|
|
|
|
// ✅ Step 4: Check if this team member already exists in `Install`
|
|
|
|
|
|
|
|
let installation = await Install.findOne({
|
|
|
|
|
|
|
|
installationId: department.departmentId
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!installation) {
|
|
|
|
if (!installation) {
|
|
|
|
return reply.status(404).send({
|
|
|
|
return reply.code(404).send({ message: "Installation not found" });
|
|
|
|
simplydata: {
|
|
|
|
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Installation not found",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Check if team member already exists in Install schema
|
|
|
|
// Add team member to install if missing
|
|
|
|
const existingTeamMember = installation.team_member.team_member.find(
|
|
|
|
const alreadyExists = installation.team_member?.team_member?.some(m => m.phone === phone);
|
|
|
|
(member) => member.phone === phone
|
|
|
|
if (!alreadyExists) {
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!existingTeamMember) {
|
|
|
|
|
|
|
|
// ✅ Step 5: Add team member details to `Install` schema
|
|
|
|
|
|
|
|
installation.team_member.team_member.push({
|
|
|
|
installation.team_member.team_member.push({
|
|
|
|
teamMemberId: teamMember.teamMemberId,
|
|
|
|
teamMemberId: teamMember.teamMemberId,
|
|
|
|
firstName: teamMember.firstName,
|
|
|
|
firstName: teamMember.firstName,
|
|
|
|
phone: teamMember.phone,
|
|
|
|
phone: teamMember.phone,
|
|
|
|
email: teamMember.email,
|
|
|
|
|
|
|
|
alternativePhone: teamMember.alternativePhone,
|
|
|
|
|
|
|
|
installationTeamMemId: installation.installationId,
|
|
|
|
installationTeamMemId: installation.installationId,
|
|
|
|
password: teamMember.password, // Store hashed password
|
|
|
|
password: teamMember.password,
|
|
|
|
status: teamMember.status || "active",
|
|
|
|
status: teamMember.status || "active",
|
|
|
|
type: type, // Store login type
|
|
|
|
email: teamMember.email,
|
|
|
|
|
|
|
|
alternativePhone: teamMember.alternativePhone,
|
|
|
|
|
|
|
|
type
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
await installation.save();
|
|
|
|
await installation.save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ✅ Step 6: Generate JWT token
|
|
|
|
// Generate JWT
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
const token = fastify.jwt.sign(
|
|
|
|
{ phone: teamMember.phone, role: type, installationId: installation.installationId },
|
|
|
|
{ phone, role: type, installationId: installation.installationId },
|
|
|
|
"JWT_SECRET",
|
|
|
|
"your_secret_key", // replace with config
|
|
|
|
{ expiresIn: "1h" }
|
|
|
|
{ expiresIn: "1h" }
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
return reply.send({
|
|
|
|
return reply.send({
|
|
|
|
simplydata: {
|
|
|
|
success: true,
|
|
|
|
error: false,
|
|
|
|
|
|
|
|
message: "Login successful",
|
|
|
|
message: "Login successful",
|
|
|
|
|
|
|
|
data: {
|
|
|
|
access_token: token,
|
|
|
|
access_token: token,
|
|
|
|
phone: teamMember.phone,
|
|
|
|
phone: teamMember.phone,
|
|
|
|
firstName: teamMember.firstName || null, // ✅ Now included
|
|
|
|
firstName: teamMember.firstName,
|
|
|
|
teamMemberId: teamMember.teamMemberId,
|
|
|
|
teamMemberId: teamMember.teamMemberId,
|
|
|
|
alternativePhone: teamMember.alternativePhone || null,
|
|
|
|
alternativePhone: teamMember.alternativePhone,
|
|
|
|
email: teamMember.email || null,
|
|
|
|
email: teamMember.email,
|
|
|
|
status: teamMember.status || "active",
|
|
|
|
status: teamMember.status || "active",
|
|
|
|
type: teamMember.type,
|
|
|
|
type,
|
|
|
|
installationId: installation.installationId
|
|
|
|
installationId: installation.installationId
|
|
|
|
},
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
} catch (err) {
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error logging in:", err);
|
|
|
|
console.error("teamMemberLogin error:", err);
|
|
|
|
reply.status(500).send({
|
|
|
|
reply.code(500).send({ message: "Internal server error" });
|
|
|
|
simplydata: {
|
|
|
|
}
|
|
|
|
error: true,
|
|
|
|
|
|
|
|
message: "Internal server error",
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|