principal distributor create with address and salescoordinator attendance system create

This commit is contained in:
Sibunnayak 2024-07-17 18:44:04 +05:30
parent 6c55be42d9
commit db4fd7a834
12 changed files with 425 additions and 149 deletions

9
.env
View File

@ -13,6 +13,7 @@ PORT = 5000
# mongosh "mongodb+srv://cluster0.vi4tl1l.mongodb.net/" --apiVersion 1 --username pulseayur --password rEF9gYORzKavLeiy
JWT_SECRET = jdvnvjwrniwj4562ddsjn6@1xsbf85df@!fgrjjeh@wre4Njdfeefr3;
JWT_EXPIRES_TIME=1h
# pulseayur
# // AyurPulse cloudinary credential
@ -36,9 +37,11 @@ SEND_EMAIL_FROM="cheminova2004@gmail.com"
#brevo send mail
SMPT_HOST="smtp-relay.brevo.com"
SMPT_PORT="587"
SMPT_MAIL="neonflake.enterprises@gmail.com"
SMPT_PASSWORD="ND5sgVnWtrpUFfTb"
# xsmtpsib-2bd50b1c4a48fe325b27e5e4a0466441552597b941e6f08104a7f18e0cb10988-hM6ZrJcBRSyDGjga
# SMPT_MAIL="cheminova2004@gmail.com"
SMPT_MAIL="78ab42003@smtp-brevo.com"
SMPT_PASSWORD="saTOdNcySftx2PXG"
# SMPT_PASSWORD="xsmtpsib-516d5809051c1f171a1dc17fda6b95589e8ccb81c3b45251e0c29d928a74829a-9jcngbV3AdWztGav"
# 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
PAYPAL_CLIENT_ID="AemCjVuWswklp1sWUo4peCFg9eS4bofMsMR0RCrVRB2DifYR1IUSrWqtHpVmQlrVMKTI2cWZXLJAdYwn"
PAYPAL_CLIENT_SECRET="EAo0Y9ff3jpHHg1QAbftdebfh7cb_-vnebhQrP9KALbCVer908yx2tO2eHO39r7EJSfqc4D69Qgx8R31"

5
app.js
View File

@ -169,7 +169,8 @@ import CouponRoute from "./resources/Affiliate&Coupon/Coupon/CouponRoute.js";
//short urls
// import ShortUrlRouter from "./resources/Businesses/Short_Urls/ShortUrlRoute.js";
//support Ticket
// Point of Sale
// attandance
import attandanceSalesCoordinator from "./resources/SalesCoOrdinatorAttandance/AttandanceSalesCoordinatorRoute.js"
app.use("/api/v1/", user);
//Product
@ -225,6 +226,8 @@ app.use("/api/v1/affiliate", AffiliateRoute);
app.use("/api/v1/coupon", CouponRoute);
//Blog
app.use("/api/v1/blog", BlogRoute);
//attendance
app.use("/api/v1/salescoordinator", attandanceSalesCoordinator);
//config specialty
// app.use("/api/config/specialty", SpecialtiesRouter);

View File

@ -10,14 +10,14 @@ export const isAuthenticatedSalesCoOrdinator = async (req, res, next) => {
});
}
const getToken = req.headers;
//remove Bearer from token
// Remove Bearer from token
const fronttoken = getToken.authorization.slice(7);
const frontdecoded = jwt.verify(fronttoken, process.env.JWT_SECRET);
if (!frontdecoded) {
return res.status(400).json({
success: false,
message: "incorrect token",
message: "Incorrect token",
});
}
const salescoordinator = await SalesCoOrdinator.findById(frontdecoded.id);
@ -44,9 +44,5 @@ export const isAuthenticatedSalesCoOrdinator = async (req, res, next) => {
message: "An internal error occurred while verifying the token.",
});
}
// return res.status(401).json({
// success: false,
// message: error.message,
// });
}
};

View File

@ -13,7 +13,7 @@ export const isAuthenticatedUser = async (req, res, next) => {
});
}
const getToken = req.headers;
// console.log(getToken);
//remove Bearer from token
const fronttoken = getToken.authorization.slice(7);
@ -24,8 +24,9 @@ export const isAuthenticatedUser = async (req, res, next) => {
message: "incorrect token",
});
}
// console.log(frontdecoded);
const fuser = await User.findById(frontdecoded.id);
// console.log(fuser);
req.user = fuser;
next();
@ -112,6 +113,7 @@ export const isFranchiAuthenticated = async (req, res, next) => {
export const authorizeRoles = (...roles) => {
//pass admin
return (req, res, next) => {
// console.log(req.user.role);
if (!roles.includes(req.user.role)) {
return next(
new ErrorHander(

View File

@ -0,0 +1,189 @@
import { AttendanceSalesCoOrdinator } from "./AttandanceSalesCoordinatorModel.js";
export const markAttendance = async (req, res) => {
try {
const { date, time, location, notes } = req.body;
const salesCoordinatorId = req.salescoordinator._id;
// Get the start and end of the day to check if the attendance is already marked
const startOfDay = new Date(date);
startOfDay.setHours(0, 0, 0, 0);
const endOfDay = new Date(date);
endOfDay.setHours(23, 59, 59, 999);
// Check if the attendance record exists for today
const existingAttendance = await AttendanceSalesCoOrdinator.findOne({
salesCoordinator: salesCoordinatorId,
"records.date": { $gte: startOfDay, $lte: endOfDay },
});
if (existingAttendance) {
return res.status(400).json({
success: false,
message: "Attendance for today is already marked.",
});
}
// Check if attendance record exists for the sales coordinator
let attendance = await AttendanceSalesCoOrdinator.findOne({
salesCoordinator: salesCoordinatorId,
});
if (!attendance) {
// Create a new attendance record if it doesn't exist
attendance = new AttendanceSalesCoOrdinator({
salesCoordinator: salesCoordinatorId,
records: [],
});
}
// Add the new attendance record to the array
attendance.records.push({ date, time, location, notes });
await attendance.save();
res.status(201).json({
success: true,
message: "Attendance marked successfully",
record: { date, time, location, notes },
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message || "Something went wrong",
});
}
};
export const getAttendanceBySalesCoordinator = async (req, res) => {
try {
const salesCoordinatorId = req.salescoordinator._id;
const attendance = await AttendanceSalesCoOrdinator.findOne({
salesCoordinator: salesCoordinatorId,
}).populate("salesCoordinator", "name email");
if (!attendance) {
return res.status(404).json({
success: false,
message: "No attendance records found for this sales coordinator.",
});
}
res.status(200).json({
success: true,
attendance,
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message || "Something went wrong",
});
}
};
// admin
export const AdmingetAttendanceBySalesCoordinator = async (req, res) => {
try {
const { id } = req.params;
const { page = 1, show = 10 } = req.query;
const limit = parseInt(show);
const skip = (page - 1) * limit;
// Find attendance records for the given sales coordinator
const attendanceDoc = await AttendanceSalesCoOrdinator.findOne({
salesCoordinator: id,
}).populate("salesCoordinator", "name email");
if (!attendanceDoc) {
return res.status(404).json({
success: false,
message: "No attendance records found for this sales coordinator.",
});
}
// Pagination and slicing records
const totalData = attendanceDoc.records.length;
const paginatedRecords = attendanceDoc.records.slice(skip, skip + limit);
res.status(200).json({
success: true,
salesCoordinator: attendanceDoc.salesCoordinator,
attendance: paginatedRecords,
total_data: totalData,
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message || "Something went wrong",
});
}
};
export const getTodayAttendance = async (req, res) => {
try {
const today = new Date();
today.setHours(0, 0, 0, 0);
const startOfDay = new Date(today);
const endOfDay = new Date(today);
endOfDay.setHours(23, 59, 59, 999);
const { page = 1, show = 10 } = req.query;
const limit = parseInt(show);
const skip = (page - 1) * limit;
const attendances = await AttendanceSalesCoOrdinator.aggregate([
{ $unwind: '$records' },
{
$match: {
'records.date': { $gte: startOfDay, $lte: endOfDay }
}
},
{
$lookup: {
from: 'salescoordinators',
localField: 'salesCoordinator',
foreignField: '_id',
as: 'salesCoordinator'
}
},
{ $unwind: '$salesCoordinator' },
{
$facet: {
totalData: [{ $count: 'count' }],
attendance: [
{ $skip: skip },
{ $limit: limit },
{
$project: {
salesCoordinator: {
id: '$salesCoordinator._id',
name: '$salesCoordinator.name',
email: '$salesCoordinator.email'
},
date: '$records.date',
time: '$records.time',
location: '$records.location',
note: '$records.notes'
}
}
]
}
}
]);
const totalData = attendances[0].totalData[0] ? attendances[0].totalData[0].count : 0;
res.status(200).json({
success: true,
attendance: attendances[0].attendance,
total_data: totalData
});
} catch (error) {
res.status(500).json({
success: false,
message: error.message || 'Something went wrong'
});
}
};

View File

@ -0,0 +1,31 @@
import mongoose from 'mongoose';
const attendanceRecordSchema = new mongoose.Schema({
date: {
type: Date,
required: true,
},
time: {
type: String,
required: true,
},
location: {
type: String,
required: true,
},
notes: {
type: String,
},
});
const attendanceSchema = new mongoose.Schema({
salesCoordinator: {
type: mongoose.Schema.Types.ObjectId,
ref: 'SalesCoOrdinator',
required: true,
unique: true,
},
records: [attendanceRecordSchema],
}, { timestamps: true, versionKey: false });
export const AttendanceSalesCoOrdinator = mongoose.model('Attendance', attendanceSchema);

View File

@ -0,0 +1,41 @@
import express from "express";
import {
markAttendance,
getAttendanceBySalesCoordinator,
getTodayAttendance,
AdmingetAttendanceBySalesCoordinator,
} from "./AttandanceSalesCoordinatorController.js";
import { isAuthenticatedSalesCoOrdinator } from "../../middlewares/SalesCoOrdinatorAuth.js";
import { authorizeRoles, isAuthenticatedUser } from "../../middlewares/auth.js";
const router = express.Router();
// Place more specific routes first
// Route to get today's attendance for admin
router.get(
"/attendance/today",
isAuthenticatedUser,
authorizeRoles("admin"),
getTodayAttendance
);
// Route to mark attendance
router.post("/attendance", isAuthenticatedSalesCoOrdinator, markAttendance);
// Route to get attendance for the logged-in sales coordinator
router.get(
"/attendance",
isAuthenticatedSalesCoOrdinator,
getAttendanceBySalesCoordinator
);
// Admin route to get attendance by sales coordinator ID
router.get(
"/attendance/:id",
isAuthenticatedUser,
authorizeRoles("admin"),
AdmingetAttendanceBySalesCoordinator
);
export default router;

View File

@ -78,8 +78,8 @@ export const verifyOtp = async (req, res) => {
) {
return res.status(400).json({ message: "Invalid or expired OTP" });
}
// const name = salesCoordinator.name;
// const mobile = salesCoordinator.mobileNumber;
const name = salesCoordinator.name;
const mobile = salesCoordinator.mobileNumber;
salesCoordinator.isVerified = true;
salesCoordinator.otp = undefined;
salesCoordinator.otpExpires = undefined;
@ -100,15 +100,15 @@ export const verifyOtp = async (req, res) => {
await salesCoordinator.save();
// Send email with the new password
// await sendEmail({
// to: `${salesCoordinator?.email}`, // Change to your recipient
// from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
// subject: `Cheminova Account Created`,
// html: `Your Account is created successfully.
// <br/>name is: <strong>${name}</strong><br/>
// <br/>MobileNumber is: <strong>${mobile}</strong><br/>
// <br/>password is: <strong>${newPassword}</strong><br/><br/>If you have not requested this email, please ignore it.`,
// });
await sendEmail({
to: `${salesCoordinator?.email}`, // Change to your recipient
from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
subject: `Cheminova Account Created`,
html: `Your Sales Coordinator Account is created successfully.
<br/>name is: <strong>${name}</strong><br/>
<br/>MobileNumber is: <strong>${mobile}</strong><br/>
<br/>password is: <strong>${newPassword}</strong><br/><br/>If you have not requested this email, please ignore it.`,
});
const token = salesCoordinator.getJWTToken();
res.status(200).json({
@ -253,7 +253,7 @@ export const forgotPassword = async (req, res) => {
password.digits,
],
});
// console.log(passwords);
salescoordinator.password = passwords;
await salescoordinator.save();
// const message = `Your password reset token are :- \n\n ${resetPasswordUrl} \n\nyour new password is:${password}\n\nIf you have not requested this email then, please ignore it.`;

View File

@ -58,45 +58,16 @@ export const AddshippingAddress = async (req, res) => {
}
};
export const AddshippingAddressByAdmin = async (req, res) => {
// console.log("request came here ", req.params._id);
try {
const {
first_Name,
last_Name,
phone_Number,
street,
city,
state,
postalCode,
country,
} = req.body;
switch (true) {
//validation
case !first_Name: {
return res.status(404).json({ msg: "please provide first_Name" });
}
case !last_Name: {
return res.status(404).json({ msg: "please provide last_Name" });
}
case !phone_Number: {
return res.status(404).json({ msg: "please provide phone_Number" });
}
case !street: {
return res.status(404).json({ msg: "please provide street" });
}
case !city: {
return res.status(404).json({ msg: "please provide city" });
}
case !state: {
return res.status(404).json({ msg: "please provide state" });
}
case !postalCode: {
const { street, city, state, postalCode, country } = req.body;
// console.log(req.body);
if (!street) return res.status(404).json({ msg: "please provide street" });
if (!city) return res.status(404).json({ msg: "please provide city" });
if (!state) return res.status(404).json({ msg: "please provide state" });
if (!postalCode)
return res.status(404).json({ msg: "please provide postalCode" });
}
case !country: {
if (!country)
return res.status(404).json({ msg: "please provide country" });
}
}
req.body.user = req.params._id;
const address = await shippingAddress.create(req.body);
@ -106,12 +77,14 @@ export const AddshippingAddressByAdmin = async (req, res) => {
message: "shipping Address Added",
});
} catch (error) {
console.log(error.message);
res.status(500).json({
success: false,
message: error.message ? error.message : "Something went Wrong",
});
}
};
// For website
export const getSingleUserSippingAddress = async (req, res) => {
try {
@ -136,10 +109,11 @@ export const getSingleUserSippingAddress = async (req, res) => {
// For Admin
export const getSingleUserSippingAddressForAdmin = async (req, res) => {
try {
// console.log(req.params._id);
const UserShippingAddress = await shippingAddress
.find({ user: req.params._id })
.sort({ createdAt: -1 });
// console.log(UserShippingAddress);
if (UserShippingAddress) {
res.status(201).json({
success: true,

View File

@ -3,15 +3,15 @@ const shippingAddressSchema = new mongoose.Schema(
{
first_Name: {
type: String,
required: true,
// required: true,
},
last_Name: {
type: String,
required: true,
// required: true,
},
phone_Number: {
type: Number,
required: true,
// required: true,
},
street: {
type: String,

View File

@ -10,29 +10,102 @@ import { Order } from "../Orders/orderModel.js";
import { RegisterEmail } from "../EmailCMS/RegisterEmail/registerEmailModal.js";
import { Config } from "../setting/Configration/Config_model.js";
// 1.Register a User
// export const registerUser = async (req, res) => {
// try {
// const { name, email, password, phone, accessTo, role } = req.body;
// // console.log("this is the password ", password, name, req.body);
// let findUser = await User.findOne({ email });
// if (findUser) {
// return res
// .status(400)
// .json({ success: false, message: "User already exists" });
// }
// if (req.files) {
// const files = req.files.avatar;
// const myCloud = await cloudinary.uploader.upload(
// files.tempFilePath,
// {
// folder: "Cheminova/user-image",
// },
// function (error, result) {
// result, error;
// }
// );
// }
// const user = await User.create({
// name,
// email,
// password,
// phone,
// role,
// accessTo,
// // avatar: {
// // public_id: myCloud.public_id,
// // url: myCloud.secure_url,
// // },
// });
// // const emailData = await RegisterEmail.find();
// // let emailSubject = emailData[0]?.subject;
// // let emailDescription = emailData[0]?.description;
// const config = await Config.find();
// let appName = config[0]?.appName;
// // await sendEmail({
// // to: `${email}`, // Change to your recipient
// // from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
// // subject: `Welcome to Cheminova - Let the Shopping Begin!`,
// // html: ` <h1 style="color: #333; text-align: left; font-family: Arial, sans-serif;">Welcome to ${appName} - Let the Shopping Begin!</h1>
// // <strong style="color: #1b03a3; font-size: 16px"> Hey ${name},</strong>
// // <p style="color: #555; font-size: 15px;">
// // Welcome to Cheminova - Let the Shopping Begin!
// // </p>
// // <br/>
// // <p style="color: #555; font-size: 15px;">You can login into :${role === "Employee" || role === "admin"
// // ? `https://admin.smellika.com/`
// // : `https://smellika.com`
// // } </p>
// // <br/>
// // <p style="color: #555; font-size: 15px;">Below are your login credentials:</p>
// // <p style="color: #555; font-size: 15px;">Email: ${email}</p>
// // <p style="color: #555; font-size: 15px;">Password: ${password}</p>
// // <span style="color: #555; font-size: 13px;">Happy shopping,</span><br/>
// // <span style="color: #555; font-size: 13px;">Team ${appName}</span>`,
// // });
// sendToken(user, 201, res);
// } catch (e) {
// return res.status(400).json({ success: false, message: e.message });
// }
// };
export const registerUser = async (req, res) => {
try {
const { name, email, password, phone, accessTo, role } = req.body;
// console.log("this is the password ", password, name, req.body);
// console.log(req.body);
let findUser = await User.findOne({ email });
if (findUser) {
return res
.status(400)
.json({ success: false, message: "User already exists" });
}
if (req.files) {
const files = req.files.avatar;
const myCloud = await cloudinary.uploader.upload(
files.tempFilePath,
{
folder: "Cheminova/user-image",
},
function (error, result) {
result, error;
}
);
}
// let avatar = { public_id: "", url: "" };
// if (req.files) {
// const files = req.files.avatar;
// const myCloud = await cloudinary.uploader.upload(files.tempFilePath, {
// folder: "Cheminova/user-image",
// });
// avatar = {
// public_id: myCloud.public_id,
// url: myCloud.secure_url,
// };
// }
const user = await User.create({
name,
@ -41,49 +114,23 @@ export const registerUser = async (req, res) => {
phone,
role,
accessTo,
// avatar: {
// public_id: myCloud.public_id,
// url: myCloud.secure_url,
// },
// avatar,
});
// Send email with the new password
await sendEmail({
to: `${email}`, // Change to your recipient
from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
subject: `Cheminova Account Created`,
html: `Your Principal Distributor Account is created successfully.
<br/>name is: <strong>${name}</strong><br/>
<br/>MobileNumber is: <strong>${phone}</strong><br/>
<br/>password is: <strong>${password}</strong><br/><br/>If you have not requested this email, please ignore it.`,
});
// const emailData = await RegisterEmail.find();
// let emailSubject = emailData[0]?.subject;
// let emailDescription = emailData[0]?.description;
const config = await Config.find();
let appName = config[0]?.appName;
// await sendEmail({
// to: `${email}`, // Change to your recipient
// from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender
// subject: `Welcome to Cheminova - Let the Shopping Begin!`,
// html: ` <h1 style="color: #333; text-align: left; font-family: Arial, sans-serif;">Welcome to ${appName} - Let the Shopping Begin!</h1>
// <strong style="color: #1b03a3; font-size: 16px"> Hey ${name},</strong>
// <p style="color: #555; font-size: 15px;">
// Welcome to Cheminova - Let the Shopping Begin!
// </p>
// <br/>
// <p style="color: #555; font-size: 15px;">You can login into :${role === "Employee" || role === "admin"
// ? `https://admin.smellika.com/`
// : `https://smellika.com`
// } </p>
// <br/>
// <p style="color: #555; font-size: 15px;">Below are your login credentials:</p>
// <p style="color: #555; font-size: 15px;">Email: ${email}</p>
// <p style="color: #555; font-size: 15px;">Password: ${password}</p>
// <span style="color: #555; font-size: 13px;">Happy shopping,</span><br/>
// <span style="color: #555; font-size: 13px;">Team ${appName}</span>`,
// });
sendToken(user, 201, res);
} catch (e) {
return res.status(400).json({ success: false, message: e.message });
}
};
// 2.Login User
export const loginUser = async (req, res, next) => {
const { email, password } = req.body;
@ -362,7 +409,7 @@ export const updateProfile = catchAsyncErrors(async (req, res, next) => {
// 9.Get all users(admin)
export const getAllUser = catchAsyncErrors(async (req, res, next) => {
// Assuming your User model is imported as 'User'
const users = await User.find({ role: "user" });
const users = await User.find({ role: "principal-Distributor" });
res.status(200).json({
success: true,

View File

@ -20,38 +20,37 @@ const userSchema = new mongoose.Schema(
unique: true,
validate: [validator.isEmail, "Please Enter a valid Email"],
},
phone: {
type: Number,
// required: [true, "Please Enter Your phone no."],
maxLength: [12, "phone cannot exceed 12 characters"],
minLength: [6, "phone should have more than 6 characters"],
phone: { // Change to 'mobileno' to match frontend field
type: String,
required: [true, "Please Enter Your phone no."],
validate: {
validator: function (v) {
return /^\d{10}$/.test(v);
},
message: "Please enter a valid 10-digit phone number",
},
},
password: {
type: String,
required: [true, "Please Enter Your Password"],
minLength: [6, "Password should be greater than 6 characters"],
select: false, //find not got passpord
select: false,
},
avatar: {
public_id: {
type: String,
// required: true,
default: "",
},
url: {
type: String,
// required: true,
default: "",
},
},
role: {
type: String,
default: "user",
default: "principal-Distributor",
},
accessTo: {},
// createdAt: {
// type: Date,
// default: Date.now,
// },
resetPasswordToken: String,
resetPasswordExpire: Date,
},
@ -62,37 +61,28 @@ userSchema.pre("save", async function (next) {
if (!this.isModified("password")) {
next();
}
this.password = await bcrypt.hash(this.password, 10);
});
// JWT TOKEN
userSchema.methods.getJWTToken = function () {
return jwt.sign({ id: this._id }, process.env.JWT_SECRET);
return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {
expiresIn: process.env.JWT_EXPIRES_TIME,
});
};
// Compare Password
userSchema.methods.comparePassword = async function (password) {
return await bcrypt.compare(password, this.password);
};
// Generating Reset Token
userSchema.methods.getResetPasswordToken = function () {
// Generating Token
const resetToken = crypto.randomBytes(20).toString("hex");
// Hashing and adding reset PasswordToken to userSchema
this.resetPasswordToken = crypto
.createHash("sha256")
.update(resetToken)
.digest("hex");
//expire password time
// console.log(this.resetPasswordToken)
this.resetPasswordExpire = Date.now() + 15 * 60 * 1000; //15 minut
this.resetPasswordToken = crypto.createHash("sha256").update(resetToken).digest("hex");
this.resetPasswordExpire = Date.now() + 15 * 60 * 1000; // 15 minutes
return resetToken;
};
const UserModel = mongoose.model("User", userSchema);
export default UserModel;
const User = mongoose.model("User", userSchema);
export default User;