Initial Version

This commit is contained in:
Ruslan845
2026-03-10 03:45:00 +09:00
commit 2c4fc7f933
128 changed files with 7617 additions and 0 deletions

View File

@@ -0,0 +1,155 @@
const asyncErrorHandler = require('../middlewares/helpers/asyncErrorHandler');
const Order = require('../models/orderModel');
const Product = require('../models/productModel');
const ErrorHandler = require('../utils/errorHandler');
const sendEmail = require('../utils/sendEmail');
// Create New Order
exports.newOrder = asyncErrorHandler(async (req, res, next) => {
const {
shippingInfo,
orderItems,
paymentInfo,
totalPrice,
} = req.body;
const orderExist = await Order.findOne({ paymentInfo });
if (orderExist) {
return next(new ErrorHandler("Order Already Placed", 400));
}
const order = await Order.create({
shippingInfo,
orderItems,
paymentInfo,
totalPrice,
paidAt: Date.now(),
user: req.user._id,
});
await sendEmail({
email: req.user.email,
templateId: process.env.SENDGRID_ORDER_TEMPLATEID,
data: {
name: req.user.name,
shippingInfo,
orderItems,
totalPrice,
oid: order._id,
}
});
res.status(201).json({
success: true,
order,
});
});
// Get Single Order Details
exports.getSingleOrderDetails = asyncErrorHandler(async (req, res, next) => {
const order = await Order.findById(req.params.id).populate("user", "name email");
if (!order) {
return next(new ErrorHandler("Order Not Found", 404));
}
res.status(200).json({
success: true,
order,
});
});
// Get Logged In User Orders
exports.myOrders = asyncErrorHandler(async (req, res, next) => {
const orders = await Order.find({ user: req.user._id });
if (!orders) {
return next(new ErrorHandler("Order Not Found", 404));
}
res.status(200).json({
success: true,
orders,
});
});
// Get All Orders ---ADMIN
exports.getAllOrders = asyncErrorHandler(async (req, res, next) => {
const orders = await Order.find();
if (!orders) {
return next(new ErrorHandler("Order Not Found", 404));
}
let totalAmount = 0;
orders.forEach((order) => {
totalAmount += order.totalPrice;
});
res.status(200).json({
success: true,
orders,
totalAmount,
});
});
// Update Order Status ---ADMIN
exports.updateOrder = asyncErrorHandler(async (req, res, next) => {
const order = await Order.findById(req.params.id);
if (!order) {
return next(new ErrorHandler("Order Not Found", 404));
}
if (order.orderStatus === "Delivered") {
return next(new ErrorHandler("Already Delivered", 400));
}
if (req.body.status === "Shipped") {
order.shippedAt = Date.now();
order.orderItems.forEach(async (i) => {
await updateStock(i.product, i.quantity)
});
}
order.orderStatus = req.body.status;
if (req.body.status === "Delivered") {
order.deliveredAt = Date.now();
}
await order.save({ validateBeforeSave: false });
res.status(200).json({
success: true
});
});
async function updateStock(id, quantity) {
const product = await Product.findById(id);
product.stock -= quantity;
await product.save({ validateBeforeSave: false });
}
// Delete Order ---ADMIN
exports.deleteOrder = asyncErrorHandler(async (req, res, next) => {
const order = await Order.findById(req.params.id);
if (!order) {
return next(new ErrorHandler("Order Not Found", 404));
}
await order.remove();
res.status(200).json({
success: true,
});
});

View File

@@ -0,0 +1,141 @@
const asyncErrorHandler = require('../middlewares/helpers/asyncErrorHandler');
// const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const paytm = require('paytmchecksum');
const https = require('https');
const Payment = require('../models/paymentModel');
const ErrorHandler = require('../utils/errorHandler');
const { v4: uuidv4 } = require('uuid');
const axios = require('axios');
exports.processPayment = asyncErrorHandler(async (req, res, next) => {
const { amount, email, phoneNo } = req.body;
var params = {};
/* initialize an array */
params["MID"] = process.env.PAYTM_MID;
params["WEBSITE"] = process.env.PAYTM_WEBSITE;
params["CHANNEL_ID"] = process.env.PAYTM_CHANNEL_ID;
params["INDUSTRY_TYPE_ID"] = process.env.PAYTM_INDUSTRY_TYPE;
params["ORDER_ID"] = "oid" + uuidv4();
params["CUST_ID"] = process.env.PAYTM_CUST_ID;
params["TXN_AMOUNT"] = JSON.stringify(amount);
// params["CALLBACK_URL"] = `${req.protocol}://${req.get("host")}/api/v1/callback`;
params["CALLBACK_URL"] = `https://${req.get("host")}/api/v1/callback`;
params["EMAIL"] = email;
params["MOBILE_NO"] = phoneNo;
let paytmChecksum = paytm.generateSignature(params, process.env.PAYTM_MERCHANT_KEY);
paytmChecksum.then(function (checksum) {
let paytmParams = {
...params,
"CHECKSUMHASH": checksum,
};
res.status(200).json({
paytmParams
});
}).catch(function (error) {
console.log(error);
});
});
// Paytm Callback
exports.paytmResponse = (req, res, next) => {
// console.log(req.body);
let paytmChecksum = req.body.CHECKSUMHASH;
delete req.body.CHECKSUMHASH;
let isVerifySignature = paytm.verifySignature(req.body, process.env.PAYTM_MERCHANT_KEY, paytmChecksum);
if (isVerifySignature) {
// console.log("Checksum Matched");
var paytmParams = {};
paytmParams.body = {
"mid": req.body.MID,
"orderId": req.body.ORDERID,
};
paytm.generateSignature(JSON.stringify(paytmParams.body), process.env.PAYTM_MERCHANT_KEY).then(function (checksum) {
paytmParams.head = {
"signature": checksum
};
/* prepare JSON string for request */
var post_data = JSON.stringify(paytmParams);
var options = {
/* for Staging */
hostname: 'securegw-stage.paytm.in',
/* for Production */
// hostname: 'securegw.paytm.in',
port: 443,
path: '/v3/order/status',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': post_data.length
}
};
// Set up the request
var response = "";
var post_req = https.request(options, function (post_res) {
post_res.on('data', function (chunk) {
response += chunk;
});
post_res.on('end', function () {
let { body } = JSON.parse(response);
// let status = body.resultInfo.resultStatus;
// res.json(body);
addPayment(body);
// res.redirect(`${req.protocol}://${req.get("host")}/order/${body.orderId}`)
res.redirect(`https://${req.get("host")}/order/${body.orderId}`)
});
});
// post the data
post_req.write(post_data);
post_req.end();
});
} else {
console.log("Checksum Mismatched");
}
}
const addPayment = async (data) => {
try {
await Payment.create(data);
} catch (error) {
console.log("Payment Failed!");
}
}
exports.getPaymentStatus = asyncErrorHandler(async (req, res, next) => {
const payment = await Payment.findOne({ orderId: req.params.id });
if (!payment) {
return next(new ErrorHandler("Payment Details Not Found", 404));
}
const txn = {
id: payment.txnId,
status: payment.resultInfo.resultStatus,
}
res.status(200).json({
success: true,
txn,
});
});

View File

@@ -0,0 +1,312 @@
const Product = require('../models/productModel');
const asyncErrorHandler = require('../middlewares/helpers/asyncErrorHandler');
const SearchFeatures = require('../utils/searchFeatures');
const ErrorHandler = require('../utils/errorHandler');
const cloudinary = require('cloudinary');
// Get All Products
exports.getAllProducts = asyncErrorHandler(async (req, res, next) => {
const resultPerPage = 12;
const productsCount = await Product.countDocuments();
// console.log(req.query);
const searchFeature = new SearchFeatures(Product.find(), req.query)
.search()
.filter();
let products = await searchFeature.query;
let filteredProductsCount = products.length;
searchFeature.pagination(resultPerPage);
products = await searchFeature.query.clone();
res.status(200).json({
success: true,
products,
productsCount,
resultPerPage,
filteredProductsCount,
});
});
// Get All Products ---Product Sliders
exports.getProducts = asyncErrorHandler(async (req, res, next) => {
const products = await Product.find();
res.status(200).json({
success: true,
products,
});
});
// Get Product Details
exports.getProductDetails = asyncErrorHandler(async (req, res, next) => {
const product = await Product.findById(req.params.id);
if (!product) {
return next(new ErrorHandler("Product Not Found", 404));
}
res.status(200).json({
success: true,
product,
});
});
// Get All Products ---ADMIN
exports.getAdminProducts = asyncErrorHandler(async (req, res, next) => {
const products = await Product.find();
res.status(200).json({
success: true,
products,
});
});
// Create Product ---ADMIN
exports.createProduct = asyncErrorHandler(async (req, res, next) => {
let images = [];
if (typeof req.body.images === "string") {
images.push(req.body.images);
} else {
images = req.body.images;
}
const imagesLink = [];
for (let i = 0; i < images.length; i++) {
const result = await cloudinary.v2.uploader.upload(images[i], {
folder: "products",
});
imagesLink.push({
public_id: result.public_id,
url: result.secure_url,
});
}
const result = await cloudinary.v2.uploader.upload(req.body.logo, {
folder: "brands",
});
const brandLogo = {
public_id: result.public_id,
url: result.secure_url,
};
req.body.brand = {
name: req.body.brandname,
logo: brandLogo
}
req.body.images = imagesLink;
req.body.user = req.user.id;
let specs = [];
req.body.specifications.forEach((s) => {
specs.push(JSON.parse(s))
});
req.body.specifications = specs;
const product = await Product.create(req.body);
res.status(201).json({
success: true,
product
});
});
// Update Product ---ADMIN
exports.updateProduct = asyncErrorHandler(async (req, res, next) => {
let product = await Product.findById(req.params.id);
if (!product) {
return next(new ErrorHandler("Product Not Found", 404));
}
if (req.body.images !== undefined) {
let images = [];
if (typeof req.body.images === "string") {
images.push(req.body.images);
} else {
images = req.body.images;
}
for (let i = 0; i < product.images.length; i++) {
await cloudinary.v2.uploader.destroy(product.images[i].public_id);
}
const imagesLink = [];
for (let i = 0; i < images.length; i++) {
const result = await cloudinary.v2.uploader.upload(images[i], {
folder: "products",
});
imagesLink.push({
public_id: result.public_id,
url: result.secure_url,
});
}
req.body.images = imagesLink;
}
if (req.body.logo.length > 0) {
await cloudinary.v2.uploader.destroy(product.brand.logo.public_id);
const result = await cloudinary.v2.uploader.upload(req.body.logo, {
folder: "brands",
});
const brandLogo = {
public_id: result.public_id,
url: result.secure_url,
};
req.body.brand = {
name: req.body.brandname,
logo: brandLogo
}
}
let specs = [];
req.body.specifications.forEach((s) => {
specs.push(JSON.parse(s))
});
req.body.specifications = specs;
req.body.user = req.user.id;
product = await Product.findByIdAndUpdate(req.params.id, req.body, {
new: true,
runValidators: true,
useFindAndModify: false,
});
res.status(201).json({
success: true,
product
});
});
// Delete Product ---ADMIN
exports.deleteProduct = asyncErrorHandler(async (req, res, next) => {
const product = await Product.findById(req.params.id);
if (!product) {
return next(new ErrorHandler("Product Not Found", 404));
}
for (let i = 0; i < product.images.length; i++) {
await cloudinary.v2.uploader.destroy(product.images[i].public_id);
}
await product.remove();
res.status(201).json({
success: true
});
});
// Create OR Update Reviews
exports.createProductReview = asyncErrorHandler(async (req, res, next) => {
const { rating, comment, productId } = req.body;
const review = {
user: req.user._id,
name: req.user.name,
rating: Number(rating),
comment,
}
const product = await Product.findById(productId);
if (!product) {
return next(new ErrorHandler("Product Not Found", 404));
}
const isReviewed = product.reviews.find(review => review.user.toString() === req.user._id.toString());
if (isReviewed) {
product.reviews.forEach((rev) => {
if (rev.user.toString() === req.user._id.toString())
(rev.rating = rating, rev.comment = comment);
});
} else {
product.reviews.push(review);
product.numOfReviews = product.reviews.length;
}
let avg = 0;
product.reviews.forEach((rev) => {
avg += rev.rating;
});
product.ratings = avg / product.reviews.length;
await product.save({ validateBeforeSave: false });
res.status(200).json({
success: true
});
});
// Get All Reviews of Product
exports.getProductReviews = asyncErrorHandler(async (req, res, next) => {
const product = await Product.findById(req.query.id);
if (!product) {
return next(new ErrorHandler("Product Not Found", 404));
}
res.status(200).json({
success: true,
reviews: product.reviews
});
});
// Delete Reveiws
exports.deleteReview = asyncErrorHandler(async (req, res, next) => {
const product = await Product.findById(req.query.productId);
if (!product) {
return next(new ErrorHandler("Product Not Found", 404));
}
const reviews = product.reviews.filter((rev) => rev._id.toString() !== req.query.id.toString());
let avg = 0;
reviews.forEach((rev) => {
avg += rev.rating;
});
let ratings = 0;
if (reviews.length === 0) {
ratings = 0;
} else {
ratings = avg / reviews.length;
}
const numOfReviews = reviews.length;
await Product.findByIdAndUpdate(req.query.productId, {
reviews,
ratings: Number(ratings),
numOfReviews,
}, {
new: true,
runValidators: true,
useFindAndModify: false,
});
res.status(200).json({
success: true,
});
});

View File

@@ -0,0 +1,262 @@
const User = require('../models/userModel');
const asyncErrorHandler = require('../middlewares/helpers/asyncErrorHandler');
const sendToken = require('../utils/sendToken');
const ErrorHandler = require('../utils/errorHandler');
const sendEmail = require('../utils/sendEmail');
const crypto = require('crypto');
const cloudinary = require('cloudinary');
// Register User
exports.registerUser = asyncErrorHandler(async (req, res, next) => {
const myCloud = await cloudinary.v2.uploader.upload(req.body.avatar, {
folder: "avatars",
width: 150,
crop: "scale",
});
const { name, email, gender, password } = req.body;
const user = await User.create({
name,
email,
gender,
password,
avatar: {
public_id: myCloud.public_id,
url: myCloud.secure_url,
},
});
sendToken(user, 201, res);
});
// Login User
exports.loginUser = asyncErrorHandler(async (req, res, next) => {
const { email, password } = req.body;
if(!email || !password) {
return next(new ErrorHandler("Please Enter Email And Password", 400));
}
const user = await User.findOne({ email}).select("+password");
if(!user) {
return next(new ErrorHandler("Invalid Email or Password", 401));
}
const isPasswordMatched = await user.comparePassword(password);
if(!isPasswordMatched) {
return next(new ErrorHandler("Invalid Email or Password", 401));
}
sendToken(user, 201, res);
});
// Logout User
exports.logoutUser = asyncErrorHandler(async (req, res, next) => {
res.cookie("token", null, {
expires: new Date(Date.now()),
httpOnly: true,
});
res.status(200).json({
success: true,
message: "Logged Out",
});
});
// Get User Details
exports.getUserDetails = asyncErrorHandler(async (req, res, next) => {
const user = await User.findById(req.user.id);
res.status(200).json({
success: true,
user,
});
});
// Forgot Password
exports.forgotPassword = asyncErrorHandler(async (req, res, next) => {
const user = await User.findOne({email: req.body.email});
if(!user) {
return next(new ErrorHandler("User Not Found", 404));
}
const resetToken = await user.getResetPasswordToken();
await user.save({ validateBeforeSave: false });
// const resetPasswordUrl = `${req.protocol}://${req.get("host")}/password/reset/${resetToken}`;
const resetPasswordUrl = `https://${req.get("host")}/password/reset/${resetToken}`;
// const message = `Your password reset token is : \n\n ${resetPasswordUrl}`;
try {
await sendEmail({
email: user.email,
templateId: process.env.SENDGRID_RESET_TEMPLATEID,
data: {
reset_url: resetPasswordUrl
}
});
res.status(200).json({
success: true,
message: `Email sent to ${user.email} successfully`,
});
} catch (error) {
user.resetPasswordToken = undefined;
user.resetPasswordExpire = undefined;
await user.save({ validateBeforeSave: false });
return next(new ErrorHandler(error.message, 500))
}
});
// Reset Password
exports.resetPassword = asyncErrorHandler(async (req, res, next) => {
// create hash token
const resetPasswordToken = crypto.createHash("sha256").update(req.params.token).digest("hex");
const user = await User.findOne({
resetPasswordToken,
resetPasswordExpire: { $gt: Date.now() }
});
if(!user) {
return next(new ErrorHandler("Invalid reset password token", 404));
}
user.password = req.body.password;
user.resetPasswordToken = undefined;
user.resetPasswordExpire = undefined;
await user.save();
sendToken(user, 200, res);
});
// Update Password
exports.updatePassword = asyncErrorHandler(async (req, res, next) => {
const user = await User.findById(req.user.id).select("+password");
const isPasswordMatched = await user.comparePassword(req.body.oldPassword);
if(!isPasswordMatched) {
return next(new ErrorHandler("Old Password is Invalid", 400));
}
user.password = req.body.newPassword;
await user.save();
sendToken(user, 201, res);
});
// Update User Profile
exports.updateProfile = asyncErrorHandler(async (req, res, next) => {
const newUserData = {
name: req.body.name,
email: req.body.email,
}
if(req.body.avatar !== "") {
const user = await User.findById(req.user.id);
const imageId = user.avatar.public_id;
await cloudinary.v2.uploader.destroy(imageId);
const myCloud = await cloudinary.v2.uploader.upload(req.body.avatar, {
folder: "avatars",
width: 150,
crop: "scale",
});
newUserData.avatar = {
public_id: myCloud.public_id,
url: myCloud.secure_url,
}
}
await User.findByIdAndUpdate(req.user.id, newUserData, {
new: true,
runValidators: true,
useFindAndModify: true,
});
res.status(200).json({
success: true,
});
});
// ADMIN DASHBOARD
// Get All Users --ADMIN
exports.getAllUsers = asyncErrorHandler(async (req, res, next) => {
const users = await User.find();
res.status(200).json({
success: true,
users,
});
});
// Get Single User Details --ADMIN
exports.getSingleUser = asyncErrorHandler(async (req, res, next) => {
const user = await User.findById(req.params.id);
if(!user) {
return next(new ErrorHandler(`User doesn't exist with id: ${req.params.id}`, 404));
}
res.status(200).json({
success: true,
user,
});
});
// Update User Role --ADMIN
exports.updateUserRole = asyncErrorHandler(async (req, res, next) => {
const newUserData = {
name: req.body.name,
email: req.body.email,
gender: req.body.gender,
role: req.body.role,
}
await User.findByIdAndUpdate(req.params.id, newUserData, {
new: true,
runValidators: true,
useFindAndModify: false,
});
res.status(200).json({
success: true,
});
});
// Delete Role --ADMIN
exports.deleteUser = asyncErrorHandler(async (req, res, next) => {
const user = await User.findById(req.params.id);
if(!user) {
return next(new ErrorHandler(`User doesn't exist with id: ${req.params.id}`, 404));
}
await user.remove();
res.status(200).json({
success: true
});
});