principal distributor multipal added successfully
This commit is contained in:
parent
5d4058f170
commit
8d88e4ec0a
@ -69,19 +69,10 @@ export const AddshippingAddressByAdmin = async (req, res) => {
|
||||
tradeName,
|
||||
gstNumber,
|
||||
} = req.body;
|
||||
// console.log(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({ message: "Invalid PAN number format" });
|
||||
return res.status(400).json({ msg: "Please provide all required fields" });
|
||||
}
|
||||
|
||||
// Create shipping address object
|
||||
@ -96,17 +87,28 @@ export const AddshippingAddressByAdmin = async (req, res) => {
|
||||
gstNumber,
|
||||
user: req.params._id, // Assuming req.params._id contains the correct user ID
|
||||
});
|
||||
// console.log(newAddress);
|
||||
|
||||
res.status(201).json({
|
||||
success: true,
|
||||
address: newAddress,
|
||||
message: "Shipping address added successfully",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error creating shipping address:", error.message);
|
||||
// console.error("Error creating shipping address:", error.message);
|
||||
|
||||
// Check for validation errors
|
||||
if (error.name === 'ValidationError') {
|
||||
const errorMessages = Object.values(error.errors).map(err => err.message);
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: errorMessages.join(", "),
|
||||
});
|
||||
}
|
||||
|
||||
// General error
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message ? error.message : "Something went wrong",
|
||||
message: error.message || "Something went wrong",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -28,7 +28,12 @@ const shippingAddressSchema = new mongoose.Schema(
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
match: /^\d{6}$/,
|
||||
validate: {
|
||||
validator: function (v) {
|
||||
return /^\d{6}$/.test(v);
|
||||
},
|
||||
message: "Postal code must be a 6-digit number",
|
||||
},
|
||||
},
|
||||
country: {
|
||||
type: String,
|
||||
@ -37,22 +42,27 @@ const shippingAddressSchema = new mongoose.Schema(
|
||||
panNumber: {
|
||||
type: String,
|
||||
required: true,
|
||||
set: v => v.toUpperCase(), // Convert to uppercase before saving
|
||||
validate: {
|
||||
validator: function (v) {
|
||||
return /^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(v);
|
||||
},
|
||||
message: props => `${props.value} is not a valid PAN number!`,
|
||||
},
|
||||
},
|
||||
tradeName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
gstNumber: {
|
||||
type: String,
|
||||
required: true,
|
||||
set: v => v.toUpperCase(),
|
||||
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!`,
|
||||
message: props => `${props.value} is not a valid GST number!`,
|
||||
},
|
||||
},
|
||||
isDefault: {
|
||||
|
@ -16,7 +16,7 @@ router
|
||||
.route("/admin/new/:_id")
|
||||
.post(
|
||||
isAuthenticatedUser,
|
||||
authorizeRoles("admin", "Employee"),
|
||||
authorizeRoles("admin"),
|
||||
AddshippingAddressByAdmin
|
||||
);
|
||||
|
||||
|
@ -9,6 +9,273 @@ import password from "secure-random-password";
|
||||
import { Order } from "../Orders/orderModel.js";
|
||||
import { RegisterEmail } from "../EmailCMS/RegisterEmail/registerEmailModal.js";
|
||||
import { Config } from "../setting/Configration/Config_model.js";
|
||||
import XLSX from "xlsx";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import validator from 'validator';
|
||||
import ShippingAddress from "../ShippingAddresses/ShippingAddressModel.js";
|
||||
|
||||
const generatePassword = (name, email) => {
|
||||
// Combine name and email, and convert to lowercase
|
||||
const combinedStr = (name + email).toLowerCase();
|
||||
|
||||
// Define character pools
|
||||
const specialChars = "@#*";
|
||||
const numbers = "0123456789";
|
||||
const alphaLower = combinedStr.match(/[a-z]/g) || [];
|
||||
const alphaUpper = combinedStr.match(/[A-Z]/g) || [];
|
||||
|
||||
// Ensure at least one character from each category
|
||||
const specialChar = specialChars.charAt(
|
||||
Math.floor(Math.random() * specialChars.length)
|
||||
);
|
||||
const numberChar = numbers.charAt(Math.floor(Math.random() * numbers.length));
|
||||
const lowerChar =
|
||||
alphaLower.length > 0
|
||||
? alphaLower[Math.floor(Math.random() * alphaLower.length)]
|
||||
: String.fromCharCode(Math.floor(Math.random() * 26) + 97);
|
||||
const upperChar =
|
||||
alphaUpper.length > 0
|
||||
? alphaUpper[Math.floor(Math.random() * alphaUpper.length)]
|
||||
: String.fromCharCode(Math.floor(Math.random() * 26) + 65);
|
||||
|
||||
// Combine required characters
|
||||
let passwordChars = [specialChar, numberChar, lowerChar, upperChar];
|
||||
|
||||
// Fill remaining positions with random characters from the combined string
|
||||
const allChars = combinedStr + specialChars + numbers;
|
||||
while (passwordChars.length < 8) {
|
||||
passwordChars.push(
|
||||
allChars.charAt(Math.floor(Math.random() * allChars.length))
|
||||
);
|
||||
}
|
||||
|
||||
// Shuffle characters to ensure randomness
|
||||
passwordChars = passwordChars.sort(() => Math.random() - 0.5);
|
||||
|
||||
// Generate password of length 8
|
||||
const password = passwordChars.slice(0, 8).join("");
|
||||
|
||||
return password;
|
||||
};
|
||||
|
||||
export const uploadPrincipaldistributors = async (req, res) => {
|
||||
try {
|
||||
if (!req.files || !req.files.file) {
|
||||
return res.status(400).json({ message: "No file uploaded" });
|
||||
}
|
||||
|
||||
const file = req.files.file;
|
||||
const filePath = path.join("public", "uploads", file.name);
|
||||
|
||||
// Ensure 'uploads' directory exists
|
||||
if (!fs.existsSync(path.dirname(filePath))) {
|
||||
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
||||
}
|
||||
|
||||
// Move the file from temp to the uploads directory
|
||||
await file.mv(filePath);
|
||||
|
||||
// Process the file
|
||||
const fileBuffer = fs.readFileSync(filePath);
|
||||
const workbook = XLSX.read(fileBuffer, { type: "buffer" });
|
||||
const sheetName = workbook.SheetNames[0];
|
||||
const worksheet = workbook.Sheets[sheetName];
|
||||
const data = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
|
||||
|
||||
if (data.length <= 1) {
|
||||
return res.status(400).json({ message: "Empty spreadsheet or no data found" });
|
||||
}
|
||||
|
||||
const headers = data[0];
|
||||
|
||||
// Map headers from the Excel file to your schema
|
||||
const headerMapping = {
|
||||
"Principal Distributor Name": "name",
|
||||
"Email": "email",
|
||||
"Phone Number": "phone",
|
||||
"PAN Number": "panNumber",
|
||||
"Trade Name": "tradeName",
|
||||
"GST Number": "gstNumber",
|
||||
"State": "state",
|
||||
"City": "city",
|
||||
"Street": "street",
|
||||
"Pincode": "postalCode",
|
||||
};
|
||||
|
||||
const requiredHeaders = Object.keys(headerMapping);
|
||||
|
||||
if (!requiredHeaders.every((header) => headers.includes(header))) {
|
||||
return res.status(400).json({ message: "Missing required columns in spreadsheet" });
|
||||
}
|
||||
|
||||
const errors = [];
|
||||
const processedUsers = [];
|
||||
|
||||
for (let i = 1; i < data.length; i++) {
|
||||
const row = data[i];
|
||||
const item = {};
|
||||
|
||||
headers.forEach((header, index) => {
|
||||
if (headerMapping[header]) {
|
||||
item[headerMapping[header]] = row[index] !== undefined ? row[index] : "";
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize error tracking for each item
|
||||
const missingFields = new Set();
|
||||
const validationErrors = new Set();
|
||||
|
||||
// Validate required fields
|
||||
if (!item.name) missingFields.add("name");
|
||||
if (!item.email) missingFields.add("email");
|
||||
if (!item.phone) missingFields.add("phone");
|
||||
if (!item.panNumber) missingFields.add("panNumber");
|
||||
if (!item.tradeName) missingFields.add("tradeName");
|
||||
if (!item.gstNumber) missingFields.add("gstNumber");
|
||||
if (!item.state) missingFields.add("state");
|
||||
if (!item.city) missingFields.add("city");
|
||||
if (!item.street) missingFields.add("street");
|
||||
if (!item.postalCode) missingFields.add("postalCode");
|
||||
|
||||
// Check email validity
|
||||
if (item.email && !validator.isEmail(item.email)) {
|
||||
validationErrors.add("incorrect mail");
|
||||
}
|
||||
|
||||
// Validate mobile number
|
||||
if (item.phone && !/^\d{10}$/.test(item.phone)) {
|
||||
validationErrors.add("Invalid Mobile Number (should be 10 digits)");
|
||||
}
|
||||
|
||||
// Check GST, PAN, and postal code validation
|
||||
item.panNumber = item.panNumber ? item.panNumber.toUpperCase() : "";
|
||||
item.gstNumber = item.gstNumber ? item.gstNumber.toUpperCase() : "";
|
||||
|
||||
// Validate PAN Number
|
||||
if (item.panNumber && !/^[A-Z]{5}[0-9]{4}[A-Z]{1}$/.test(item.panNumber)) {
|
||||
validationErrors.add("Invalid PAN Number");
|
||||
}
|
||||
|
||||
// Validate GST Number
|
||||
if (item.gstNumber && !/^(\d{2}[A-Z]{5}\d{4}[A-Z]{1}\d[Z]{1}[A-Z\d]{1})$/.test(item.gstNumber)) {
|
||||
validationErrors.add("Invalid GST Number");
|
||||
}
|
||||
|
||||
// Validate Postal Code
|
||||
if (item.postalCode && !/^\d{6}$/.test(item.postalCode)) {
|
||||
validationErrors.add("Invalid Postal Code");
|
||||
}
|
||||
|
||||
// Combine all errors into a single message
|
||||
let errorMessage = "";
|
||||
if (missingFields.size > 0) {
|
||||
errorMessage += `Missing fields: ${Array.from(missingFields).join(", ")}. `;
|
||||
}
|
||||
if (validationErrors.size > 0) {
|
||||
errorMessage += `Validation errors: ${Array.from(validationErrors).join(", ")}.`;
|
||||
}
|
||||
|
||||
// If there are errors, push them to the errors array
|
||||
if (errorMessage.trim()) {
|
||||
errors.push({
|
||||
name: item.name || "N/A",
|
||||
email: item.email || "N/A",
|
||||
phone: item.phone || "N/A",
|
||||
panNumber: item.panNumber || "N/A",
|
||||
gstNumber: item.gstNumber || "N/A",
|
||||
message: errorMessage.trim(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
// Generate a password
|
||||
const password = generatePassword(item.name, item.email);
|
||||
item.role = "principal-Distributor";
|
||||
const currentYear = new Date().getFullYear().toString().slice(-2);
|
||||
const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase();
|
||||
item.uniqueId = `${currentYear}-${randomChars}`;
|
||||
// Check for existing user
|
||||
let user = await User.findOne({ email: item.email });
|
||||
|
||||
if (user) {
|
||||
// Update existing user details
|
||||
user.name = item.name;
|
||||
user.phone = item.phone;
|
||||
await user.save();
|
||||
} else {
|
||||
// Create a new user
|
||||
user = new User({
|
||||
name: item.name,
|
||||
email: item.email,
|
||||
phone: item.phone,
|
||||
password,
|
||||
role: item.role,
|
||||
uniqueId: item.uniqueId,
|
||||
});
|
||||
await user.save();
|
||||
|
||||
// Send email with the new user details
|
||||
await sendEmail({
|
||||
to: item.email,
|
||||
from: process.env.SEND_EMAIL_FROM,
|
||||
subject: `Cheminova Account Created`,
|
||||
html: `
|
||||
Your Principal Distributor Account is created successfully.
|
||||
<br/>Name: <strong>${item.name}</strong><br/>
|
||||
<br/>Mobile Number: <strong>${item.phone}</strong><br/>
|
||||
<br/>Password: <strong>${password}</strong><br/><br/>
|
||||
<a href="${process.env.PD_APP_URL}/login">Click here to login</a><br/><br/>
|
||||
If you have not requested this email, please ignore it.
|
||||
`,
|
||||
});
|
||||
}
|
||||
|
||||
// Create or update shipping address
|
||||
const addressData = {
|
||||
street: item.street,
|
||||
city: item.city,
|
||||
state: item.state,
|
||||
postalCode: item.postalCode,
|
||||
country: "India", // Default country
|
||||
panNumber: item.panNumber,
|
||||
tradeName: item.tradeName,
|
||||
gstNumber: item.gstNumber,
|
||||
user: user._id,
|
||||
};
|
||||
|
||||
let existingAddress = await ShippingAddress.findOne({ user: user._id });
|
||||
|
||||
if (existingAddress) {
|
||||
// Update existing address
|
||||
await ShippingAddress.updateOne({ user: user._id }, addressData);
|
||||
} else {
|
||||
// Create new address
|
||||
await ShippingAddress.create(addressData);
|
||||
}
|
||||
|
||||
processedUsers.push({
|
||||
...user._doc,
|
||||
...addressData,
|
||||
});
|
||||
}
|
||||
|
||||
fs.unlinkSync(filePath); // Clean up uploaded file
|
||||
|
||||
res.status(201).json({
|
||||
message:
|
||||
errors.length > 0
|
||||
? "File processed with errors!"
|
||||
: "File processed successfully!",
|
||||
processedUsers: processedUsers.length, // Total processed users
|
||||
errors,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
res.status(500).json({ message: error.message || "Something went wrong!" });
|
||||
}
|
||||
};
|
||||
|
||||
// 1.Register a User
|
||||
// export const registerUser = async (req, res) => {
|
||||
// try {
|
||||
@ -85,21 +352,23 @@ import { Config } from "../setting/Configration/Config_model.js";
|
||||
// };
|
||||
export const registerUser = async (req, res) => {
|
||||
try {
|
||||
const { name, email, password, phone, accessTo, role } = req.body;
|
||||
|
||||
const { name, email, phone, accessTo, role } = req.body;
|
||||
// console.log(req.body);
|
||||
const password = generatePassword(name, email);
|
||||
// console.log(password);
|
||||
// Check if user already exists
|
||||
let user = await User.findOne({ email });
|
||||
if (user) {
|
||||
// If user exists, update their details if needed
|
||||
user.name = name;
|
||||
user.password = password; // In a real application, you should hash this
|
||||
// user.password = password; // In a real application, you should hash this
|
||||
user.phone = phone;
|
||||
user.role = role;
|
||||
user.accessTo = accessTo;
|
||||
|
||||
// Save updates
|
||||
await user.save();
|
||||
|
||||
// console.log("finduser", user);
|
||||
// Respond with success and userId
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
@ -117,7 +386,7 @@ export const registerUser = async (req, res) => {
|
||||
role,
|
||||
accessTo,
|
||||
});
|
||||
|
||||
// console.log(user);
|
||||
// Generate uniqueId
|
||||
const currentYear = new Date().getFullYear().toString().slice(-2);
|
||||
const randomChars = crypto.randomBytes(4).toString("hex").toUpperCase();
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
getAllEmployee,
|
||||
deleteEmployeeById,
|
||||
updateEmployeeById,
|
||||
uploadPrincipaldistributors,
|
||||
} from "./userController.js";
|
||||
import { isAuthenticatedUser, authorizeRoles } from "../../middlewares/auth.js";
|
||||
|
||||
@ -30,7 +31,12 @@ router.route("/user/password/reset/:token").put(resetPassword);
|
||||
router.route("/user/logout").get(logout);
|
||||
|
||||
router.route("/user/details").get(isAuthenticatedUser, getUserDetails);
|
||||
|
||||
router
|
||||
.route('/principaldistributor/upload').post(
|
||||
isAuthenticatedUser,
|
||||
authorizeRoles('admin'),
|
||||
uploadPrincipaldistributors
|
||||
);
|
||||
router
|
||||
.route("/admin/users")
|
||||
.get(isAuthenticatedUser, authorizeRoles("admin", "Employee"), getAllUser);
|
||||
|
Loading…
Reference in New Issue
Block a user