diff --git a/app.js b/app.js index 7efff7d..46fb2b8 100644 --- a/app.js +++ b/app.js @@ -171,7 +171,7 @@ import CouponRoute from "./resources/Affiliate&Coupon/Coupon/CouponRoute.js"; //support Ticket // attandance import attendance from "./resources/Attendance/AttandanceRoute.js" -app.use("/api/v1/", user); +app.use("/api/v1", user); //Product app.use("/api", ProductRouter); diff --git a/resources/Orders/CheckoutController.js b/resources/Orders/CheckoutController.js index 0a2d656..b7eb5b4 100644 --- a/resources/Orders/CheckoutController.js +++ b/resources/Orders/CheckoutController.js @@ -3,7 +3,7 @@ const { PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET } = process.env; const base = "https://api-m.sandbox.paypal.com"; import axios from "axios"; import mongoose from "mongoose"; -import { shippingAddress } from "../ShippingAddresses/ShippingAddressModel.js"; +import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js"; //paypal client id get export const getClientId = async (req, res) => { try { @@ -108,7 +108,7 @@ export const createOrderCheckout = async (req, res) => { price_With_Tax: 0, taxId: "", })); - let addss = await shippingAddress.findById(address); + let addss = await ShippingAddress.findById(address); let shipping = { first_Name: addss.first_Name, last_Name: addss.last_Name, @@ -116,6 +116,7 @@ export const createOrderCheckout = async (req, res) => { street: addss.street, city: addss.city, state: addss.state, + panpanNumber: addss.panNumber, postalCode: addss?.postalCode, country: addss.country, addressId: address, diff --git a/resources/Orders/PosCheckoutController.js b/resources/Orders/PosCheckoutController.js index ee069ad..fd1ee6b 100644 --- a/resources/Orders/PosCheckoutController.js +++ b/resources/Orders/PosCheckoutController.js @@ -1,4 +1,4 @@ -import { shippingAddress } from "../ShippingAddresses/ShippingAddressModel.js"; +import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js"; import { Order } from "./orderModel.js"; import sendEmail from "../../Utils/sendEmail.js"; @@ -40,7 +40,7 @@ export const poscreateOrderCheckout = async (req, res) => { if (!userr) return res.status(400).json({ message: "User is not defined" }); // Retrieve shipping address from database - let addss = await shippingAddress.findById(address); + let addss = await ShippingAddress.findById(address); let shipping = { first_Name: addss.first_Name, diff --git a/resources/Orders/RazerPayCheckoutController.js b/resources/Orders/RazerPayCheckoutController.js index 6f82c1f..883dd06 100644 --- a/resources/Orders/RazerPayCheckoutController.js +++ b/resources/Orders/RazerPayCheckoutController.js @@ -3,7 +3,7 @@ import crypto from "crypto"; import Razorpay from "razorpay"; import { Order } from "./orderModel.js"; -import { shippingAddress } from "../ShippingAddresses/ShippingAddressModel.js"; +import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js"; import sendEmail from "../../Utils/sendEmail.js"; import { AffiliateModel } from "../Affiliate&Coupon/Affiliate/AffiliateModel.js"; const instance = new Razorpay({ @@ -177,7 +177,7 @@ export const checkout = async (req, res) => { // const { email } = req.user; // if (!email) // return res.status(400).send({ message: "Please enter the email" }); - let addss = await shippingAddress.findById(address); + let addss = await ShippingAddress.findById(address); let shipping = { first_Name: addss.first_Name, @@ -659,7 +659,7 @@ export const handlePayment = async (req, res) => { return res.status(404).json({ msg: "please provide product subtotal" }); } } - let addss = await shippingAddress.findById(address); + let addss = await ShippingAddress.findById(address); // console.log(addss?.postalCode); let shipping = { first_Name: addss.first_Name, diff --git a/resources/Orders/StripeCheckOutController.js b/resources/Orders/StripeCheckOutController.js index f031fe1..f08784b 100644 --- a/resources/Orders/StripeCheckOutController.js +++ b/resources/Orders/StripeCheckOutController.js @@ -7,7 +7,7 @@ const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); // const stripe = require("stripe")("Your Secret Key"); import { Order } from "./orderModel.js"; -import { shippingAddress } from "../ShippingAddresses/ShippingAddressModel.js"; +import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js"; import sendEmail from "../../Utils/sendEmail.js"; // const endpointSecret = STRIPE_SECRET_KEY; //generate unique order id @@ -48,7 +48,7 @@ export const handlePayment = async (req, res) => { return res.status(404).json({ msg: "please provide product subtotal" }); } } - let addss = await shippingAddress.findById(address); + let addss = await ShippingAddress.findById(address); let shipping = { first_Name: addss.first_Name, diff --git a/resources/SalesCoOrdinators/SalesCoOrdinatorController.js b/resources/SalesCoOrdinators/SalesCoOrdinatorController.js index a32e162..b300c2d 100644 --- a/resources/SalesCoOrdinators/SalesCoOrdinatorController.js +++ b/resources/SalesCoOrdinators/SalesCoOrdinatorController.js @@ -1,5 +1,4 @@ // import hashPassword from '../utils/hashPassword'; - import crypto from "crypto"; import SalesCoOrdinator from "./SalesCoOrdinatorModel.js"; import sendEmail, { sendOtp } from "../../Utils/sendEmail.js"; @@ -8,11 +7,9 @@ import password from "secure-random-password"; export const register = async (req, res) => { let { name, email, countryCode, mobileNumber } = req.body; - // console.log(req.body); countryCode = countryCode?.trim(); mobileNumber = mobileNumber?.trim(); const fullMobileNumber = `${countryCode}${mobileNumber}`; - // console.log(fullMobileNumber); try { let salesCoordinator = await SalesCoOrdinator.findOne({ @@ -25,10 +22,9 @@ export const register = async (req, res) => { "SalesCoordinator already registered and verified for this mobile number.", }); } - // const otp = crypto.randomInt(100000, 1000000).toString(); const otp = "123456"; - const otpExpires = Date.now() + 3 * 60 * 1000; // 3 minutes + const otpExpires = Date.now() + 1 * 60 * 1000; if (salesCoordinator) { salesCoordinator.otp = otp; @@ -42,13 +38,17 @@ export const register = async (req, res) => { otpExpires, }); } - + // Generate uniqueId if not already present + if (!salesCoordinator.uniqueId) { + const currentYear = new Date().getFullYear().toString().slice(-2); + const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); + salesCoordinator.uniqueId = `${currentYear}-${randomChars}`; + } await salesCoordinator.save(); // await sendOtp( // fullMobileNumber, - // `Your Cheminova verification OTP is: ${otp}` + // Your Cheminova verification OTP is: ${otp} // ); - return res.status(200).json({ message: `OTP sent to your mobile number ${fullMobileNumber} successfully`, }); @@ -253,7 +253,7 @@ export const forgotPassword = async (req, res) => { password.digits, ], }); -// console.log(passwords); + // 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.`; @@ -302,14 +302,16 @@ export const updateMobileNumber = async (req, res) => { "New mobile number cannot be the same as the old mobile number", }); } - // Check if the new mobile number already exists in another document - const existingSalesCoordinator = await SalesCoOrdinator.findOne({ - mobileNumber: newFullMobileNumber, - }); + // Check if the new mobile number already exists in another document + const existingSalesCoordinator = await SalesCoOrdinator.findOne({ + mobileNumber: newFullMobileNumber, + }); - if (existingSalesCoordinator) { - return res.status(400).json({ message: "Mobile number already registered and verified by someone" }); - } + if (existingSalesCoordinator) { + return res.status(400).json({ + message: "Mobile number already registered and verified by someone", + }); + } // const otp = crypto.randomInt(100000, 1000000).toString(); const otp = "123456"; const otpExpires = Date.now() + 3 * 60 * 1000; // 3 minutes diff --git a/resources/SalesCoOrdinators/SalesCoOrdinatorModel.js b/resources/SalesCoOrdinators/SalesCoOrdinatorModel.js index afafddd..babc6a7 100644 --- a/resources/SalesCoOrdinators/SalesCoOrdinatorModel.js +++ b/resources/SalesCoOrdinators/SalesCoOrdinatorModel.js @@ -5,6 +5,7 @@ import validator from "validator"; import bcrypt from "bcryptjs"; import jwt from "jsonwebtoken"; import crypto from "crypto"; + const salescoordinatorSchema = new mongoose.Schema( { name: { @@ -31,16 +32,21 @@ const salescoordinatorSchema = new mongoose.Schema( type: String, required: false, unique: true, - validate: [validator.isEmail, "Please Enter a valid Email"], + validate: [validator.isEmail, "Please enter a valid Email"], }, password: { type: String, minLength: [6, "Password should be greater than 6 characters"], - select: false, //find not got passpord + select: false, }, newMobileNumber: { type: String }, resetPasswordToken: String, resetPasswordExpire: Date, + uniqueId: { + type: String, + unique: true, + required: true, + }, }, { timestamps: true } ); @@ -53,6 +59,15 @@ salescoordinatorSchema.pre("save", async function (next) { this.password = await bcrypt.hash(this.password, 10); }); +salescoordinatorSchema.pre("save", function (next) { + if (!this.uniqueId) { + const currentYear = new Date().getFullYear().toString().slice(-2); + const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); + this.uniqueId = `${currentYear}-${randomChars}`; + } + next(); +}); + // JWT TOKEN salescoordinatorSchema.methods.getJWTToken = function () { return jwt.sign({ id: this._id }, process.env.JWT_SECRET); @@ -63,19 +78,16 @@ salescoordinatorSchema.methods.comparePassword = async function (password) { return await bcrypt.compare(password, this.password); }; -// Generating Reset Token +// Generating Reset Token salescoordinatorSchema.methods.getResetPasswordToken = function () { - // Generating Token const resetToken = crypto.randomBytes(20).toString("hex"); - // Hashing and adding reset PasswordToken to salescoordinatorSchema 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.resetPasswordExpire = Date.now() + 15 * 60 * 1000; // 15 minutes return resetToken; }; diff --git a/resources/ShippingAddresses/ShippingAddressController.js b/resources/ShippingAddresses/ShippingAddressController.js index 3a17835..5e40f5a 100644 --- a/resources/ShippingAddresses/ShippingAddressController.js +++ b/resources/ShippingAddresses/ShippingAddressController.js @@ -1,4 +1,4 @@ -import { shippingAddress } from "./ShippingAddressModel.js"; +import ShippingAddress from "./ShippingAddressModel.js"; export const AddshippingAddress = async (req, res) => { // console.log("request came here"); try { @@ -42,7 +42,7 @@ export const AddshippingAddress = async (req, res) => { } } req.body.user = req.user._id; - const address = await shippingAddress.create(req.body); + const address = await ShippingAddress.create(req.body); res.status(201).json({ success: true, @@ -59,28 +59,54 @@ export const AddshippingAddress = async (req, res) => { }; export const AddshippingAddressByAdmin = async (req, res) => { try { - const { street, city, state, postalCode, country } = req.body; + const { + street, + city, + state, + postalCode, + country, + panNumber, + tradeName, + gstNumber, + } = 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" }); - if (!country) - return res.status(404).json({ msg: "please provide country" }); - req.body.user = req.params._id; - const address = await shippingAddress.create(req.body); + // console.log(req.params._id); + // Validate required fields + if (!street || !city || !state || !postalCode || !panNumber) { + return res + .status(400) + .json({ msg: "Please provide all required fields" }); + } + // Validate PAN number format + const panNumberRegex = /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/; + if (!panNumberRegex.test(panNumber)) { + return res.status(400).json({ msg: "Invalid PAN number format" }); + } + + // Create shipping address object + const newAddress = await ShippingAddress.create({ + street, + city, + state, + postalCode, + country, + panNumber, + tradeName, + gstNumber, + user: req.params._id, // Assuming req.params._id contains the correct user ID + }); + // console.log(newAddress); res.status(201).json({ success: true, - address, - message: "shipping Address Added", + address: newAddress, + message: "Shipping address added successfully", }); } catch (error) { - console.log(error.message); + console.error("Error creating shipping address:", error.message); res.status(500).json({ success: false, - message: error.message ? error.message : "Something went Wrong", + message: error.message ? error.message : "Something went wrong", }); } }; @@ -88,10 +114,9 @@ export const AddshippingAddressByAdmin = async (req, res) => { // For website export const getSingleUserSippingAddress = async (req, res) => { try { - const UserShippingAddress = await shippingAddress - .find({ user: req.user._id }) - - .sort({ createdAt: -1 }); + const UserShippingAddress = await ShippingAddress.find({ + user: req.user._id, + }).sort({ createdAt: -1 }); if (UserShippingAddress) { res.status(201).json({ success: true, @@ -110,9 +135,9 @@ export const getSingleUserSippingAddress = async (req, res) => { export const getSingleUserSippingAddressForAdmin = async (req, res) => { try { // console.log(req.params._id); - const UserShippingAddress = await shippingAddress - .find({ user: req.params._id }) - .sort({ createdAt: -1 }); + const UserShippingAddress = await ShippingAddress.find({ + user: req.params._id, + }).sort({ createdAt: -1 }); // console.log(UserShippingAddress); if (UserShippingAddress) { res.status(201).json({ @@ -136,7 +161,7 @@ export const deleteSelfShippingAddress = async (req, res) => { return res .status(400) .json({ message: "please Provide shipping Address Id" }); - const getselfAddress = await shippingAddress.findById(req.params.id); + const getselfAddress = await ShippingAddress.findById(req.params.id); if (!getselfAddress) { return res.status(404).json({ success: false, @@ -144,7 +169,7 @@ export const deleteSelfShippingAddress = async (req, res) => { }); } if (getselfAddress?.user.toString() === req.user._id.toString()) { - const address = await shippingAddress.findByIdAndDelete(req.params.id); + const address = await ShippingAddress.findByIdAndDelete(req.params.id); await address.remove(); return res.status(200).json({ success: true, @@ -182,7 +207,7 @@ export const updateShippingAddress = async (req, res) => { return res .status(400) .json({ message: "please Provide shipping Address Id" }); - const getselfAddress = await shippingAddress.findById(req.params.id); + const getselfAddress = await ShippingAddress.findById(req.params.id); if (!getselfAddress) { return res.status(404).json({ success: false, @@ -226,7 +251,7 @@ export const updateShippingAddress = async (req, res) => { postalCode, country, }; - const updateShippingAddress = await shippingAddress.findByIdAndUpdate( + const updateShippingAddress = await ShippingAddress.findByIdAndUpdate( { _id: _id }, { $set: updateAddressData }, { new: true } @@ -248,7 +273,7 @@ export const updateShippingAddress = async (req, res) => { export const getSingleSippingAddress = async (req, res) => { try { let _id = req.params.id; - const address = await shippingAddress.findById({ _id: _id }); + const address = await ShippingAddress.findById({ _id: _id }); if (address) { res.status(201).json({ diff --git a/resources/ShippingAddresses/ShippingAddressModel.js b/resources/ShippingAddresses/ShippingAddressModel.js index 31a8a7a..5983f00 100644 --- a/resources/ShippingAddresses/ShippingAddressModel.js +++ b/resources/ShippingAddresses/ShippingAddressModel.js @@ -1,17 +1,15 @@ import mongoose from "mongoose"; + const shippingAddressSchema = new mongoose.Schema( { - first_Name: { + firstName: { type: String, - // required: true, }, - last_Name: { + lastName: { type: String, - // required: true, }, - phone_Number: { + phoneNumber: { type: Number, - // required: true, }, street: { type: String, @@ -30,28 +28,34 @@ const shippingAddressSchema = new mongoose.Schema( type: String, required: true, trim: true, - // Add a regular expression to enforce a specific postal code format - // For example, assuming a 5-digit format for the United States match: /^\d{6}$/, }, country: { type: String, required: true, }, - // company_name: { - // type: String, - // }, - // gst_number: { - // type: String, - // validate: { - // validator: function (v) { - // // Regular expression for Indian GST number validation - // return /^(\d{2}[A-Z]{5}\d{4}[A-Z]{1}\d[Z]{1}[A-Z\d]{1})$/.test(v); - // }, - // message: (props) => `${props.value} is not a valid Indian GST number!`, - // }, - // }, - default: { + panNumber: { + type: String, + required: true, + }, + tradeName: { + type: String, + }, + gstNumber: { + type: String, + validate: { + validator: function (v) { + // Check if gstNumber is provided before applying validation + if (v && v.trim().length > 0) { + return /^(\d{2}[A-Z]{5}\d{4}[A-Z]{1}\d[Z]{1}[A-Z\d]{1})$/.test(v); + } + // If gstNumber is not provided, it's considered valid + return true; + }, + message: (props) => `${props.value} is not a valid GST number!`, + }, + }, + isDefault: { type: Boolean, default: false, }, @@ -64,7 +68,6 @@ const shippingAddressSchema = new mongoose.Schema( { timestamps: true, versionKey: false } ); -export const shippingAddress = mongoose.model( - "ShippingAddress", - shippingAddressSchema -); +const ShippingAddress = mongoose.model("ShippingAddress", shippingAddressSchema); + +export default ShippingAddress; diff --git a/resources/user/userController.js b/resources/user/userController.js index 179a8bd..56a4423 100644 --- a/resources/user/userController.js +++ b/resources/user/userController.js @@ -86,7 +86,7 @@ import { Config } from "../setting/Configration/Config_model.js"; export const registerUser = async (req, res) => { try { const { name, email, password, phone, accessTo, role } = req.body; - // console.log(req.body); + let findUser = await User.findOne({ email }); if (findUser) { return res @@ -94,41 +94,39 @@ export const registerUser = async (req, res) => { .json({ success: false, message: "User already exists" }); } - // 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({ + const newUser = new User({ name, email, password, phone, role, accessTo, - // avatar, }); - // Send email with the new password + + // Generate uniqueId + const currentYear = new Date().getFullYear().toString().slice(-2); + const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); + newUser.uniqueId = `${currentYear}-${randomChars}`; + + // Save the new user to the database + await newUser.save(); + + // Send email with the new user details await sendEmail({ - to: `${email}`, // Change to your recipient - from: `${process.env.SEND_EMAIL_FROM}`, // Change to your verified sender + to: email, + from: process.env.SEND_EMAIL_FROM, subject: `Cheminova Account Created`, html: `Your Principal Distributor Account is created successfully. -
name is: ${name}
-
MobileNumber is: ${phone}
-
password is: ${password}

If you have not requested this email, please ignore it.`, +
Name: ${name}
+
Mobile Number: ${phone}
+
Password: ${password}

If you have not requested this email, please ignore it.`, }); - sendToken(user, 201, res); - } catch (e) { - return res.status(400).json({ success: false, message: e.message }); + + // Respond with success and token + res.status(201).json({ success: true, message: "User created successfully", userId: newUser._id }); + } catch (error) { + console.error(error); + res.status(400).json({ success: false, message: error.message }); } }; // 2.Login User @@ -368,7 +366,7 @@ export const updatePassword = catchAsyncErrors(async (req, res, next) => { export const updateProfile = catchAsyncErrors(async (req, res, next) => { const newUserData = { name: req.body.name, - + phone:req.body.phone, email: req.body.email, }; diff --git a/resources/user/userModel.js b/resources/user/userModel.js index 5d0a02d..b25c7ec 100644 --- a/resources/user/userModel.js +++ b/resources/user/userModel.js @@ -8,6 +8,11 @@ import crypto from "crypto"; const userSchema = new mongoose.Schema( { + uniqueId: { + type: String, + unique: true, + required: true, + }, name: { type: String, required: [true, "Please Enter Your Name"], @@ -20,7 +25,7 @@ const userSchema = new mongoose.Schema( unique: true, validate: [validator.isEmail, "Please Enter a valid Email"], }, - phone: { // Change to 'mobileno' to match frontend field + phone: { type: String, required: [true, "Please Enter Your phone no."], validate: { @@ -64,6 +69,16 @@ userSchema.pre("save", async function (next) { this.password = await bcrypt.hash(this.password, 10); }); +// Generate uniqueId before saving +userSchema.pre("save", function (next) { + if (!this.uniqueId) { + const currentYear = new Date().getFullYear().toString().slice(-2); + const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase(); + this.uniqueId = `${currentYear}-${randomChars}`; + } + next(); +}); + // JWT TOKEN userSchema.methods.getJWTToken = function () { return jwt.sign({ id: this._id }, process.env.JWT_SECRET, {