Untitled
unknown
plain_text
a month ago
19 kB
3
Indexable
Never
const mongoose = require('mongoose'); const User = require('../Models/userModel.js'); const SubCategory = require('../Models/subcategoryModel.js'); const Group = require('../Models/groupModel.js'); const Brand = require('../Models/brandModel.js'); const Category = require('../Models/categoryModel.js'); const Product = require('../Models/productModel.js'); const AppError = require('../utils/appError.js'); const catchAsync = require('../utils/catchAsync.js'); const { isDecimal } = require('validator'); const Client = require('../Models/clientModel.js'); const Cart = require('../Models/cartModel.js'); const Order = require('../Models/orderModel.js'); const Retailer = require('../Models/retailerModel.js'); const Notification = require('../Models/notificationModel.js'); const Offer = require('../Models/offerModel.js'); const Socket = require('../socket/socketIndex.js'); const valid = require('../utils/validationfunctions.js'); const XLSX = require('xlsx'); /////////////// exports.AddOrder = catchAsync(async (req, res, next) => { const { productDetails, billingDetails, userId } = req.body; const session = await mongoose.startSession(); try { session.startTransaction(); let total = 0; const user = await checkUser(userId, next); // await checkProductDetails(productDetails,session,next); if (!Array.isArray(productDetails)) { return next(new AppError('products Details not array', 400)); } if (productDetails.length < 1) { return next(new AppError('no products in this order', 400)); } for (const prod of productDetails) { const product = await Product.findById(toObjectId(prod.product, next)); if (!product) { return next(new AppError('Product not found', 400)); } if (prod.quantity < 1) { return next(new AppError('invalid Quantity value', 400)); } if (product.quantity < prod.quantity) { return next(new AppError('Quantity for this Product not found', 400)); } product.quantity = product.quantity - prod.quantity; prod.initialPrice = product.pricing.initialPrice; if (user.role == 'client') { prod.price = product.pricing.publicPrice; } else if (user.role == 'retailer') { const retailer = await Retailer.findById({ _id: user.profile }).select('pricingType'); prod.price = product.pricing.discountPrices[retailer.pricingType - 1]; } else { return next(new AppError("this user isn't client or retailer", 400)); } if (product.offer) { const offer = await Offer.findById(product.offer); if (offer.status == true) { prod.price = Number.parseFloat(prod.price * (1 - offer.discount / 100)).toFixed(2); } } total += prod.price * prod.quantity; await product.save({ session: session }); } await checkbillingDetails(billingDetails, next); const order = await Order.create( [ { products: productDetails, cart_address: billingDetails, totalPrice: Number.parseFloat(total).toFixed(2), ordered_by: user._id } ], { session } ); if (user.role == 'client') { await Client.updateOne({ _id: user.profile }, { $push: { orders: order[0]._id } }, { session }); } else if (user.role == 'retailer') { await Retailer.updateOne({ _id: user.profile }, { $push: { orders: order[0]._id } }, { session }); } const users = await User.find({ $or: [{ role: 'manager' }, { role: 'admin' }, { role: 'subadmin' }] }); const usersIds = []; for (let i = 0; i < users.length; i++) { const notification = await Notification.create([{ content: 'new order', type: 'order' }], { session }); await User.updateOne({ _id: users[i]._id }, { $push: { notifications: notification[0]._id } }, { session }); usersIds.push({ id: users[i]._id.toString(), data: notification }); } Socket.SocketConnectedList(usersIds); await session.commitTransaction(); session.endSession(); res.status(200).json({ message: 'Order added successfully', order: order }); } catch (error) { await session.abortTransaction(); session.endSession(); return next(error); } }); /////////////// const checkUser = async (userId, next) => { const user = await User.findById(toObjectId(userId, next)); if (!user) { return next(new AppError('User not found', 400)); } switch (user.role) { case 'client': const client = await Client.findById(user.profile); if (!client) { return next(new AppError('Client profile not found', 400)); } break; case 'retailer': const retailer = await Retailer.findById(user.profile); if (!retailer) { return next(new AppError('Retailer profile not found', 400)); } break; default: return next(new AppError('this role does not have access for this function', 401)); } return user; }; const checkbillingDetails = async (billingDetails, next) => { if (!valid.isValidPhoneNumber(billingDetails.phone)) { return next(new AppError('Phone is required', 400)); } if (!billingDetails.city) { return next(new AppError('city is required', 400)); } if (!billingDetails.zipCode) { return next(new AppError('zip_code is required', 400)); } if (!billingDetails.address) { return next(new AppError('adresse is required', 400)); } if (!billingDetails.first_name) { return next(new AppError('first name is required', 400)); } if (!billingDetails.last_name) { return next(new AppError('last name is required', 400)); } }; exports.getOrders = catchAsync(async (req, res, next) => { const { id } = req.params; let orders = null; const user = await checkUser(id, next); if (user.role == 'client') { const pathsAndFields = { path: 'orders', populate: { path: 'products.product', select: ['name'] } }; orders = await Client.find({ _id: user.profile }).populate(pathsAndFields); } if (user.role == 'retailer') { const pathsAndFields = { path: 'orders', select: ['products'], populate: { path: 'products.product', select: ['name'] } }; orders = await Retailer.find({ _id: user.profile }).populate(pathsAndFields); } const data = orders[0].orders.reduce((result, order) => { let obj = {}; obj.item_count = order.products.length; obj.id = order._id; obj.totalPrice = order.totalPrice; obj.status = order.status; obj.createdAt = order.createdAt; result.push(obj); return result; }, []); res.status(200).json({ message: 'success', orders: data }); }); exports.getOrderDetails = catchAsync(async (req, res, next) => { const { id } = req.params; const pathsAndFields = { path: 'products.product', select: ['name', 'images'] }; const order = await Order.findById(toObjectId(id, next)).populate(pathsAndFields); res.status(200).json({ message: 'success', order: order }); }); exports.changeOrderStatus = catchAsync(async (req, res, next) => { const { id, status } = req.body; const order_id = toObjectId(id, next); const session = await mongoose.startSession(); try { session.startTransaction(); const order = await Order.updateOne({ _id: order_id }, { status: status }, { runValidators: true }, { session }); if (order.matchedCount > 0) { const users = await Order.aggregate([ { $match: { _id: order_id } }, { $lookup: { from: 'users', localField: 'ordered_by', foreignField: '_id', pipeline: [{ $project: { name: 1 } }], as: 'user' } } ]); const usersIds = []; for (let i = 0; i < users[0].user.length; i++) { const notification = await Notification.create( [{ content: 'Your order status has been changed, new status :' + status + '', type: 'order' }], { session } ); await User.updateOne({ _id: users[0].user[i]._id }, { $push: { notifications: notification[0]._id } }); usersIds.push({ id: users[0].user[i]._id.toString(), data: notification }); } Socket.SocketConnectedList(usersIds); await session.commitTransaction(); session.endSession(); res.status(200).json({ status: 'success', order: order }); } else { res.status(400).json({ status: 'error', message: 'order id invalid' }); } } catch (error) { await session.abortTransaction(); session.endSession(); return next(error); } }); exports.AddTrackingAndColis = catchAsync(async (req, res, next) => { const { tracking_number, colis_number, orderId } = req.query; console.log('****, ', orderId); const order = await Order.findById(toObjectId(orderId, next)); if (!order) { return next(new AppError('Order not found', 400)); } if (tracking_number) { order.nb_tracking = tracking_number; } if (colis_number) { order.nb_colis = colis_number; } await order.save(); res.status(200).json({ message: 'success', data: order }); }); exports.filterOrders = catchAsync(async (req, res, next) => { const { category, status, startDate, endDate, limitDate } = req.body; const page = parseInt(req.query.page); const limit = parseInt(req.query.limit); if (!page || !limit) { return next(new AppError('page and limit required', 400)); } let category_filter = {}; let filter = {}; if (category) { const Id = toObjectId(category, next); let id_category = await Category.findById(Id); if (id_category) { //arrayAND.push({ categories: Id }); category_filter.categories = Id; } else { return next(new AppError('invalid categorie value', 400)); } } if (status == 'pending' || status == 'processing' || status == 'cancel' || status == 'delivered') { filter.status = status; } if (limitDate) { var currentDate = new Date(); let days = parseInt(limitDate); currentDate.setDate(currentDate.getDate() - days); filter.createdAt = { $gte: currentDate }; } if (startDate && !endDate) { let date = new Date(startDate); if (date == 'Invalid Date') { return next(new AppError('Invalid Date', 400)); } filter.createdAt = { $gte: date }; } if (!startDate && endDate) { let date = new Date(endDate); date.setDate(date.getDate() + 1); if (date == 'Invalid Date') { return next(new AppError('Invalid Date', 400)); } filter.createdAt = { $lte: date }; } if (startDate && endDate) { let start_date = new Date(startDate); let end_date = new Date(endDate); end_date.setDate(end_date.getDate() + 1); if (start_date == 'Invalid Date' || end_date == 'Invalid Date') { return next(new AppError('Invalid Date', 400)); } filter.createdAt = { $gte: start_date, $lte: end_date }; } const results = await Order.aggregate([ { $match: filter }, { $sort: { createdAt: -1 } }, { $lookup: { from: 'products', localField: 'products.product', foreignField: '_id', pipeline: [{ $match: category_filter }], as: 'product' } }, { $lookup: { from: 'users', localField: 'ordered_by', foreignField: '_id', pipeline: [{ $project: { name: 1 } }], as: 'clientName' } }, { $limit: (page - 1) * limit + limit }, { $skip: (page - 1) * limit } ]); const data = results.reduce((result, order) => { if (order.product.length > 0) { let obj = {}; obj.units = order.products.length; obj.id = order._id; obj.product = {}; obj.product.name = order.product[0]?.name; obj.product.image = order.product[0]?.images[0]; obj.price = order.totalPrice; obj.status = order.status; obj.nb_tracking = order?.nb_tracking || ''; obj.nb_colis = order?.nb_colis || ''; obj.clientName = order.clientName[0]?.name; result.push(obj); } return result; }, []); const count = await Order.find(filter).count(); res.status(200).json({ status: 'success', count, data }); }); exports.OrdersToExcel = catchAsync(async (req, res, next) => { const { category, status, startDate, endDate, limitDate } = req.query; let category_filter = {}; let filter = {}; if (category) { const Id = toObjectId(category, next); let id_category = await Category.findById(Id); if (id_category) { //arrayAND.push({ categories: Id }); category_filter.categories = Id; } else { return next(new AppError('invalid categorie value', 400)); } } if (status == 'pending' || status == 'processing' || status == 'cancel' || status == 'delivered') { filter.status = status; } if (limitDate) { var currentDate = new Date(); let days = parseInt(limitDate); currentDate.setDate(currentDate.getDate() - days); filter.createdAt = { $gte: currentDate }; } if (startDate && !endDate) { let date = new Date(startDate); if (date == 'Invalid Date') { return next(new AppError('Invalid Date', 400)); } filter.createdAt = { $gte: date }; } if (!startDate && endDate) { let date = new Date(endDate); date.setDate(date.getDate() + 1); if (date == 'Invalid Date') { return next(new AppError('Invalid Date', 400)); } filter.createdAt = { $lte: date }; } if (startDate && endDate) { let start_date = new Date(startDate); let end_date = new Date(endDate); end_date.setDate(end_date.getDate() + 1); if (start_date == 'Invalid Date' || end_date == 'Invalid Date') { return next(new AppError('Invalid Date', 400)); } filter.createdAt = { $gte: start_date, $lte: end_date }; console.log('date :', end_date); } const results = await Order.aggregate([ { $match: filter }, { $sort: { createdAt: -1 } }, { $lookup: { from: 'products', localField: 'products.product', foreignField: '_id', pipeline: [{ $match: category_filter }], as: 'product' } }, { $lookup: { from: 'users', localField: 'ordered_by', foreignField: '_id', pipeline: [{ $project: { name: 1 } }], as: 'clientName' } } ]); const flatData = results .map((order) => { return { 'Order ID': order._id.toString(), 'First Name': order?.cart_address?.first_name, 'Last Name': order?.cart_address?.last_name, Phone: order?.cart_address?.phone, City: order?.cart_address?.city, 'Zip Code': order?.cart_address?.zipCode, Address: order?.cart_address?.address, Units: order?.products.length, 'Total Price': order?.totalPrice, Status: order.status, 'Created At': formatDateToYYYYMMDD(order?.createdAt), 'Updated At': formatDateToYYYYMMDD(order?.updatedAt), 'Tracking Number': order?.nb_tracking, 'Number of Parcels': order?.nb_colis }; }) .flat(); const worksheet = XLSX.utils.json_to_sheet(flatData); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, 'Orders'); // Generate Excel file buffer const excelBuffer = XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' }); res.setHeader('Content-Disposition', 'attachment; filename="OrdersData.xlsx"'); res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); // Send the buffer as a response return res.send(excelBuffer); }); function formatDateToYYYYMMDD(date) { if (date) { if (!(date instanceof Date)) { throw new Error('Invalid date object'); } const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-based, so add 1 const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; } } exports.getListOrders = catchAsync(async (req, res, next) => { const results = await Order.aggregate([ { $lookup: { from: 'products', localField: 'products.0.product', foreignField: '_id', pipeline: [{ $project: { name: 1, images: 1 } }], as: 'product' } }, { $lookup: { from: 'users', localField: 'ordered_by', foreignField: '_id', pipeline: [{ $project: { name: 1 } }], as: 'clientName' } } ]); const data = results.reduce((result, order) => { let obj = {}; obj.units = order.products.length; obj.id = order._id; obj.product = {}; obj.product.name = order.product[0]?.name; obj.product.image = order.product[0]?.images[0]; obj.price = order.totalPrice; obj.status = order.status; obj.clientName = order.clientName[0]?.name; result.push(obj); return result; }, []); res.status(200).json({ status: 'success', data: data }); }); exports.getListOrdersByUser = catchAsync(async (req, res, next) => { const { id } = req.params; let orders = null; const user = await checkUser(id, next); if (user.role == 'client') { const pathsAndFields = { path: 'orders', populate: { path: 'products.0.product', select: ['name', 'images'] } }; orders = await Client.find({ _id: user.profile }).populate(pathsAndFields); } if (user.role == 'retailer') { const pathsAndFields = { path: 'orders', populate: { path: 'products.0.product', select: ['name', 'images'] } }; orders = await Retailer.find({ _id: user.profile }).populate(pathsAndFields); } const data = orders[0].orders.reduce((result, order) => { let obj = {}; obj.item_count = order.products.length; obj.id = order._id; obj.totalPrice = order.totalPrice; obj.status = order.status; obj.createdAt = order.createdAt; obj.name = order.products[0].product?.name; obj.image = order.products[0]?.product?.images[0]; result.push(obj); return result; }, []); res.status(200).json({ message: 'success', orders: data }); }); exports.getOrderInvoce = catchAsync(async (req, res, next) => { const { id } = req.params; const pathsAndFields = [ { path: 'products.product', select: ['name', 'images'] }, { path: 'ordered_by', select: ['name', 'phone,email'] } ]; const order = await Order.findById(toObjectId(id, next)).populate(pathsAndFields); res.status(200).json({ message: 'success', order: order }); }); const toObjectId = (id, next) => { try { return new mongoose.Types.ObjectId(id); } catch (e) { return next(new AppError('Invalid id.', 401)); } };
Leave a Comment