const CartItem = require("../models/CartItem"); const Order = require("../models/Order"); const User = require("../models/User"); const Food = require("../models/Food"); const Payment = require("../models/Payment"); const DiscountCode = require("../models/DiscountCode"); const StoreInfo = require("../models/StoreInfo"); const { body, validationResult } = require("express-validator"); const { res404, res500, checkValidations } = require("../plugins/controllersHelperFunctions"); const { _sr } = require("../plugins/serverResponses"); const axios = require("axios"); const zarinpal = require("./../zarinpal"); const { sendSingle, sendMulti } = require("./../plugins/pushNotif").notification; const { sendNotifyOrder } = require("./../socket/adminNotify"); const moment = require("moment-jalaali"); const { sms } = require("./../SMSModule"); const CronJob = require("cron").CronJob; /////////// variables const apiKey = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6ImRiYjIwMmRhYzAxYzFjNzgwYjgxNWQyZDgyMWNmNmY1Njk0MThhMGE3N2Q1M2Y0OTZkYzQzYTgxMmNmN2U3ZWJjNzI5MjY5YjkxMjA4MTYyIn0.eyJhdWQiOiIxNDk3OSIsImp0aSI6ImRiYjIwMmRhYzAxYzFjNzgwYjgxNWQyZDgyMWNmNmY1Njk0MThhMGE3N2Q1M2Y0OTZkYzQzYTgxMmNmN2U3ZWJjNzI5MjY5YjkxMjA4MTYyIiwiaWF0IjoxNjI3MzI2Mzc0LCJuYmYiOjE2MjczMjYzNzQsImV4cCI6MTYyOTkxODM3NCwic3ViIjoiIiwic2NvcGVzIjpbImJhc2ljIl19.hyKNSy4fmPps6yIdm33Wof-mES9ujh5lmI3VFWyecbkNCm9ATPwsZ9s53A3a1wPJmHfLBXpCcob5NGL-GjZlVfqfRBiReRMr_iniCjUOnqENfFwVEJutxI-xrzVe7PZzOgx1Vr6WwSUHvQ36eJSS1lBlHlqCgwRbkG0hs4YdZsKhzhfYdlAluNw9djjUAMbRWZVL0EluP9CYko4w8tB0KHUZMZYGQcevCfb_3OU9ygHo7B--Z5aTPfm7IK4eP0gHsZ_t857B3tu3ZJB1mkgxc2R9gZUflKqj1ZqkYiR0uMGP-571enXh6pYQLXL2k-gOxLIedCaE6XytxVXhENnotA"; const limit = 20; const zarinUrl = "https://www.zarinpal.com/pg/StartPay"; const timeToStart = 1800000; // const timeToStart = 1800000 ////////// functions const deg2rad = (deg) => { return deg * (Math.PI / 180); }; const _computeShippingCost = async (addresses, location) => { try { if (addresses.length && location) { const address = addresses[0]; const R = 6371; // Radius of the earth in km const dLat = deg2rad(address.location.coordinates[1] - location.coordinates[1]); // deg2rad below const dLon = deg2rad(address.location.coordinates[0] - location.coordinates[0]); const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(address.location.coordinates[1])) * Math.cos(deg2rad(location.coordinates[1])) * Math.sin(dLon / 2) * Math.sin(dLon / 2); const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // Distance in km return R * c; } else { return 0; } } catch (error) { return 0; } }; const _computeShippingCostByRoad = async (addresses, storeLocation) => { try { if (addresses.length && storeLocation) { const address = addresses.find((item2) => item2.used === true); const lng = address.location.coordinates[0]; const lat = address.location.coordinates[1]; const storeLng = storeLocation.coordinates[0]; const storeLat = storeLocation.coordinates[1]; const getDistance = await axios.get(`https://map.ir/routes/route/v1/driving/${lng},${lat};${storeLng},${storeLat}`, { headers: { "x-api-key": apiKey, }, }); if (getDistance.data.code !== "Ok") return new Error(_sr["fa"].response.unknownError); //@todo if distance under 1000 meter equal to 0 return getDistance.data.routes[0].distance <= 1000 ? 0 : Math.round(getDistance.data.routes[0].distance / 1000); } else { return 0; } } catch (error) { return 0; } }; const getMinutes = (str) => { var time = str.split(":"); return time[0] * 60 + time[1] * 1; }; const getMinutesNow = (timezone) => { var timeNow = new Date(); return timeNow.getUTCHours() * 60 + timeNow.getUTCMinutes(); }; const _computeHavePointPrice = async (items) => { try { let total = 0; for (const item of items) { if (item.havePoint) { let priceItem = item.price - (item.price * item.static_discount || 0 / 100); let totalPrice = priceItem * item.quantity; total += totalPrice; } } return total; } catch (error) { return 0; } }; //////////////////////////////////////////////////////////////////public ////////////////////////////////////// cart module.exports.addToCart = [ //// check start time and end time // async (req, res, next) => { // try { // const getTime = await StoreInfo.findOne() // // if (getTime) { // if (getTime?.open24){ // return next() // } else if (getTime?.utcStartTime && getTime?.utcEndTime) { // let start = getMinutes(getTime.utcStartTime) // let end = getMinutes(getTime.utcEndTime) // let now = getMinutesNow(getTime.timezone) // // if ( // (start < now && end > now) || (start > end && (now < end || now > start)) // ) { // return next() // } else if (start === end) { // return res.status(503).json({message: `در حال حاظر پذیرش سفارش نداریم`}) // }else { // return res.status(503).json({message: `پذیرش سفارش از ساعت ${getTime?.startTime} تا ${getTime?.endTime} می باشد`}) // } // // } else { // return next() // } // } else { // return next() // } // // } catch (error) { // return res500(res, _sr['fa'].response.unknownError) // } // }, [ body("product_id").custom((value, { req }) => { return Food.findById(value) .then((product) => { if (product) return true; else return Promise.reject(_sr["fa"].not_found.item_id); }) .catch((err) => { return Promise.reject(_sr["fa"].not_found.item_id); }); }), body("type").notEmpty().withMessage(`نوع عملی که باید انجام شود را بفرستید`), body("branchId") .notEmpty() .withMessage(_sr["fa"].required.field) .bail() .custom((value, { req }) => { return StoreInfo.findOne({ _id: value }).then((store) => { if (!store) return Promise.reject(_sr["fa"].not_found.item_id); else return true; }); }), ], checkValidations(validationResult), async (req, res) => { try { const { product_id, type, branchId } = req.body; const checkCart = await CartItem.findOne({ branchId, product_id, user_id: req.user._id }).populate("product_id"); if (checkCart) { if (Number(checkCart.quantity) > 0) { if (type === "positive") { checkCart.quantity = Number(checkCart.quantity) + 1; } else if (type === "negative") { checkCart.quantity = Number(checkCart.quantity) - 1; } await checkCart.save(); if (Number(checkCart.quantity) === 0 || checkCart.product_id.stock === 0) { await checkCart.deleteOne(); } } return res.json({ message: _sr["fa"].response.success_save }); } else { const addCart = await CartItem.create({ branchId, product_id, user_id: req.user._id, quantity: 1, }); if (!addCart) return res500(res, _sr["fa"].response.unknownError); return res.json({ message: _sr["fa"].response.success_save }); } } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.getCartItems = [ async (req, res) => { try { const branchId = req?.params?.branchId; const allCartItems = await CartItem.find({ branchId, user_id: req.user._id }) .populate({ path: "user_id", select: "-password -token", sort: { useRate: -1 }, }) .populate("product_id"); return res.json(allCartItems); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.updateCart = [ [ body("quantity") .notEmpty() .withMessage((value, { req }) => { return _sr["fa"].required.quantity; }) .bail() .isNumeric() .withMessage((value, { req }) => { return _sr["fa"].format.number; }), ], checkValidations(validationResult), (req, res) => { CartItem.findById(req.params.item_id) .then((item) => { if (!item) return res404(res, _sr["fa"].not_found.item_id); item.quantity = Number(req.body.quantity); item.save(); return res.json({ message: _sr["fa"].response.success_save }); }) .catch((err) => { return res404(res, err); }); }, ]; module.exports.deleteAllCartItem = [ (req, res) => { CartItem.deleteMany({ user_id: req.user._id }, (err, result) => { if (err) return res500(res, _sr["fa"].response.unknownError); else return res.json({ message: _sr["fa"].response.success_remove }); }); }, ]; /////////////////////////////////// reorder module.exports.reOrder = [ //////////////////// validation step // (req, res, next) => { // CartItem.find({user_id: req.user._id}) // .then(items => { // // check if cart is not empty // if (items.length) { // // check product stock // let outOfRun = [] // items.forEach(async (item, index) => { // await Food.findById(item.product_id) // .then(product => { // if (product.stock < item.quantity) { // outOfRun.push({ // product_id: product._id, // category_id: product.category, // stock: product.stock // }) // item.remove() // } // if (index + 1 === items.length) { // if (!outOfRun.length) return next() // else return res.status(422).json(outOfRun) // } // }) // }) // } else { // return res.status(404).json({message: _sr['fa'].response.cart_empty}) // } // }) // }, async (req, res) => { try { const orderId = req.params?.orderId; const checkOrder = await Order.findOne({ status: "delivered", user_id: req.user._id, _id: orderId }).populate("product_id"); if (!checkOrder) return res404(res, `سفارش کاربر یافت نشد`); await CartItem.deleteMany({ user_id: req.user._id }); for (const food of checkOrder.order_items) { if (food.product_id && !food.product_id?.deleted) { await CartItem.create({ product_id: food.product_id._id, user_id: req.user._id, quantity: food.quantity, }); } } return res.json({ message: _sr["fa"].response.success_save }); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; ////////////////////////////////////// order module.exports.addOrder = [ [ body("description").optional().isString().withMessage(`توضیحات سفارش باید به صورت رشته فرستاده شود`), body("bag").optional().isBoolean().withMessage(_sr["fa"].format.boolean), body("score").optional().isBoolean().withMessage(_sr["fa"].format.boolean), body("discountCode") .if((value, { req }) => { return value; }) .custom((value, { req }) => { return DiscountCode.findOne({ discount_code: value }) .then((discount) => { if (!discount) return Promise.reject(`کد تخفیف وارد شده صحیح نمیباشد`); if (Number(discount.discount_expire_date) > Date.now()) return Promise.reject(`تاریخ مصرف کد تخفیف به اتمام رشیده است`); if (discount.used_by.includes(req?.user?._id)) return Promise.reject(`کد تخفیف قبلا استفاده شده است`); if (!discount.isPublic) { if (discount?.discount_user_id?.toString() !== req?.user?._id.toString()) return Promise.reject(`کد تخفیف وارد شده صحیح نمیباشد`); } else return true; }) .catch((error) => { return Promise.reject(`کد تخفیف وارد شده صحیح نمیباشد`); }); }), body("branchId") .notEmpty() .withMessage(_sr["fa"].required.field) .bail() .custom((value, { req }) => { return StoreInfo.findOne({ _id: value }).then((store) => { if (!store) return Promise.reject(_sr["fa"].not_found.item_id); else return true; }); }), ], checkValidations(validationResult), //////////////////// validation step (req, res, next) => { CartItem.find({ branchId: req?.body?.branchId, user_id: req.user._id }).then((items) => { // check if cart is not empty if (items.length) { // check product stock let outOfRun = []; items.forEach(async (item, index) => { await Food.findById(item.product_id).then((product) => { if (product.stock < item.quantity) { outOfRun.push({ name: product.name, product_id: product._id, category_id: product.category, stock: product.stock, }); item.remove(); } if (index + 1 === items.length) { if (!outOfRun.length) return next(); else return res.status(422).json(outOfRun); } }); }); } else { return res.status(404).json({ message: _sr["fa"].response.cart_empty }); } }); }, //////////////////// save order async (req, res) => { try { const { branchId, description, bag, score, discountCode } = req.body; const cartItems = await CartItem.find({ branchId, user_id: req.user._id }).populate("product_id"); const getUserInfo = await User.findById(req.user._id); const getDiscountCode = await DiscountCode.findOne({ branchId, discount_code: discountCode }); if (!getUserInfo) return res404(res, `اطلاعات کاربر یافت نشد`); if (!cartItems.length) return res.status(404).json({ message: `هیچ محصولی در سبد خرید شما وجود ندارد` }); await Order.deleteMany({ branchId, status: "incomplete", user_id: req.user._id }); /// check order exist or not // const checkOrder = await Order.findOne({'status': 'incomplete', user_id: req.user._id}); // // if (checkOrder) { // await checkOrder.remove() // } const orderItems = []; for (const item of cartItems) { orderItems.push({ product_id: item.product_id._id, name: item.product_id.name, quantity: item.quantity, price: item.product_id.price, static_discount: item.product_id.static_discount, havePoint: item.product_id.havePoint, }); } if (score && bag) return res.status(422).json({ message: "استفاده همزمان از کیف پول و امتیاز برای خرید مجاز نمی باشد" }); const orderData = { branchId, user_id: req.user._id, number: Date.now(), order_items: orderItems, statuses: [ { status: "incomplete", }, ], description, bag, score, discount_code: getDiscountCode?.discount_code, discount_amount: getDiscountCode?.discount_amount, discount_menuType: getDiscountCode?.menuTypeId, }; await Order.create(orderData); return res.json({ message: _sr["fa"].response.success_save }); } catch (error) { console.log(error); return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.orderPay = [ [ body("branchId") .notEmpty() .withMessage(_sr["fa"].required.field) .bail() .custom((value, { req }) => { return StoreInfo.findOne({ _id: value }).then((store) => { if (!store) return Promise.reject(_sr["fa"].not_found.item_id); else return true; }); }), ], checkValidations(validationResult), (req, res, next) => { CartItem.find({ branchId: req?.body?.branchId, user_id: req.user._id }).then((items) => { // check if cart is not empty if (items.length) { // check product stock let outOfRun = []; items.forEach(async (item, index) => { await Food.findById(item.product_id).then((product) => { if (product.stock < item.quantity) { outOfRun.push({ product_id: product._id, category_id: product.category, stock: product.stock, }); item.remove(); } if (index + 1 === items.length) { if (!outOfRun.length) return next(); else return res.status(422).json(outOfRun); } }); }); } else { return res.status(404).json({ message: _sr["fa"].response.cart_empty }); } }); }, async (req, res) => { try { const branchId = req?.body?.branchId; const cartItems = await CartItem.find({ branchId, user_id: req.user._id }).populate("product_id"); const checkOrder = await Order.findOne({ branchId, status: "incomplete", user_id: req.user._id }); const getUserInfo = await User.findById(req.user._id); const getStoreInfo = await StoreInfo.findOne({ _id: branchId }); if (!checkOrder) return res404(res, "لطفا از مرحله سبد خرید دوباره ادامه دهید"); let pricePoint = Math.floor(getStoreInfo?.priceForChange / getStoreInfo?.pointForChange) || 0; let totalPricePoint = getStoreInfo?.totalPricePoint || 0; let pointForBuy = getStoreInfo?.pointForBuy || 0; let discount_percent = checkOrder?.discount_amount || 0; let discount_menuType = checkOrder?.discount_menuType; let specialDiscountMenuType = false; let routePrice = 0; let sum = 0; let sumFoodByPercent = 0; let sumFoodByPercentForDiscount = 0; let total = 0; let firstTotal = 0; let percent = 0; let tax = 0; if (!getUserInfo) return res404(res, `اطلاعات کاربر یافت نشد`); if (!cartItems.length) return res.status(404).json({ message: `هیچ محصولی در سبد خرید شما وجود ندارد` }); const orderItems = []; for (const item of cartItems) { orderItems.push({ product_id: item.product_id._id, name: item.product_id.name, quantity: item.quantity, price: item.product_id.price, static_discount: item.product_id.static_discount, havePoint: item.product_id.havePoint, }); const itemPercent = (item.product_id.price * item.product_id.static_discount) / 100; const sumPercent = itemPercent * item.quantity; const price = item.product_id.price; const sumPriceItem = price * item.quantity; let sumByPercentForDiscount = sumPriceItem - sumPercent; if (Boolean(discount_percent) && discount_menuType) { specialDiscountMenuType = true; if (item?.product_id?.category.type?.toString() === discount_menuType?.toString()) { sumFoodByPercentForDiscount += sumByPercentForDiscount; } } sum = sum + sumPriceItem; /// sum food price without percent percent = percent + sumPercent; /// sum all food percent } /// sum food price with percent sumFoodByPercent = sum - percent; /// compute shipping cost if (getStoreInfo) { if (getStoreInfo?.shippingType) { routePrice = getStoreInfo?.shippingCost || 0; } else { routePrice = (await _computeShippingCostByRoad(getUserInfo?.addresses, getStoreInfo?.location)) * (getStoreInfo?.shippingCost || 0) || 0; } /// compute tax of order if (getStoreInfo?.tax) { tax = (sumFoodByPercent * 9) / 100; } } /// compute discount code if (Boolean(discount_percent)) { let discountPercent = ((specialDiscountMenuType ? sumFoodByPercentForDiscount : sumFoodByPercent) * discount_percent) / 100; percent = percent + discountPercent; /// compute sum food with discount percent sumFoodByPercent = sumFoodByPercent - discountPercent; } /// compute total of order total = sumFoodByPercent + tax + routePrice; checkOrder.order_items = orderItems; checkOrder.createdOn = Date.now(); checkOrder.address = getUserInfo.addresses.find((item) => item.used); checkOrder.sum = Math.ceil(sum); checkOrder.routePrice = Math.ceil(routePrice); checkOrder.tax = Math.ceil(tax); checkOrder.percent = Math.ceil(percent); checkOrder.total = Math.ceil(total); checkOrder.pricePoint = pricePoint; firstTotal = Math.ceil(total); if (checkOrder.bag) { const payPrice = total - getUserInfo?.bagAmount; total = payPrice <= 0 ? 0 : payPrice; } if (checkOrder.score && pricePoint > 0) { const payScore = total - getUserInfo?.score * pricePoint; total = payScore <= 0 ? 0 : payScore; } checkOrder.payTotal = Math.ceil(total); console.log("total", total); console.log("payTotal", checkOrder?.payTotal); /// if total pay is zero dont move to pay method if (checkOrder?.payTotal <= 0) { /// if bag true use the bagAmount of user if (checkOrder?.bag) { getUserInfo.bagAmount -= firstTotal; // add point for user only for available product const computeAvaPro = await _computeHavePointPrice(checkOrder.order_items); /// add score for order if (computeAvaPro >= totalPricePoint && totalPricePoint > 0) { const point = Math.floor(computeAvaPro / totalPricePoint) * pointForBuy; if (point > 0) { getUserInfo.score = getUserInfo.score + point; getUserInfo.scoreLogs = [ { score: point, order_id: getUserInfo._id, forWhat: "buy", action: "increase", }, ]; } } await getUserInfo.save(); if (Boolean(discount_percent)) { const updateDiscount = await DiscountCode.findOne({ discount_code: checkOrder.discount_code }); if (!updateDiscount || Number(updateDiscount.discount_expire_date) > Date.now()) return res.status(403).json({ message: "مشکلی در پرداخت و ثبت سفارش پیش آمده است لطفا با پشتیبانی تماس بگیرید" }); updateDiscount.used_by.push(getUserInfo._id); await updateDiscount.save(); } const addPayment = await Payment.create({ user_id: getUserInfo._id, order_id: checkOrder._id, transactionId: Date.now(), refId: Date.now(), getPayment: true, action: "decreaseBag", status: "paid", cost: firstTotal, }); checkOrder.payment.push(addPayment._id); checkOrder.bagCost = firstTotal; } /// it was ok! /// if score true use the score of user if (checkOrder?.score && pricePoint > 0) { const point = Math.ceil(firstTotal / pricePoint); checkOrder.scoreCost = point * pricePoint; checkOrder.scorePoint = point; getUserInfo.score -= point; getUserInfo.scoreLogs = [ { score: point, order_id: checkOrder._id, forWhat: "buy", action: "decrease", }, ]; await getUserInfo.save(); } checkOrder.statuses.push({ status: "processing", }); checkOrder.status = "processing"; checkOrder.paymentStatus = "paid"; await checkOrder.save(); for (const food of checkOrder.order_items) { const getFood = await Food.findById(food.product_id); if (getFood) { getFood.stock = getFood.stock - food.quantity; // getFood.canReview.push(req.user._id)///add user id for review getFood.save(); } } /// remove cart item await CartItem.deleteMany({ user_id: getUserInfo._id }); //----------------------- send notif for admins ----------------- const fcmTokens = []; const allAdmins = await User.find({ scope: "admin" }); for (const admin of allAdmins) { if (admin.fcmToken) fcmTokens.push(admin.fcmToken); } const objNotif = { title: "سفارش جدید!", body: "یک سفارش جدید در پنل برگ من ثبت گردید", }; const payload = { notification: objNotif, }; const input = { registrationTokens: fcmTokens, payload, }; await sendMulti(input); sendNotifyOrder(checkOrder?.branchId); //---------------------------------------------------------------- //--------------------- send notif to user -------------------------- const messageUser = { title: "ثبت سفارش", body: "با تشکر از اعتماد شما سفارش شما با موفقیت ثبت شد", }; const payloadUser = { notification: messageUser, }; const inputUser = { registrationTokens: getUserInfo.fcmToken, payload: payloadUser, }; await sendSingle(inputUser); //------------------------------------------------------------------- //------------------------------- send sms -------------------------- const smsTemplate = `سفارش شما با موفقیت ثبت شد با تشکر از اعتماد شما برگ من لغو11`; const smsResult = await sms(getUserInfo.mobile_number, smsTemplate); if (!smsResult) { return res500(res, `مشکلی در ارسال پیامک پیش آمده است`); } //------------------------------------------------------------------- return res.json({ message: _sr["fa"].response.success_save }); } const request = await zarinpal.request(checkOrder?.payTotal, checkOrder?.number?.toString(), req.user); if (!request.status) { console.log(request); return res500(res, _sr["fa"].response.unknownError); } // add payment to order const addPayment = await Payment.create({ user_id: getUserInfo._id, order_id: checkOrder._id, transactionId: request.response.authority, cost: checkOrder.payTotal, }); if (addPayment) { checkOrder.payment = addPayment._id; await checkOrder.save(); } else { return res500(res, _sr["fa"].response.unknownError); } /// remove cart item await CartItem.deleteMany({ branchId, user_id: req.user._id }); return res.json({ paymentUrl: `${zarinUrl}/${request.response.authority}` }); } catch (error) { console.log(error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.getPaymentResponse = [ async (req, res) => { try { const checkPayment = await Payment.findOne({ transactionId: req?.query?.Authority }).populate("order_id"); const user = await User.findById(checkPayment.user_id); ///check duplicate transaction if (!checkPayment || checkPayment.getPayment || checkPayment.action === "decreaseBag") { return res.json({ status: false, fromWhere: user?.fromWhere || "app", message: "پرداخت ناموفق بود", }); } /// verify transaction const verify = await zarinpal.verify( checkPayment.action === "increaseBag" ? checkPayment.cost : checkPayment.order_id.payTotal, checkPayment.transactionId, ); console.log(verify); if (verify.status) { if (verify.code === 101) { console.log(verify); return res.json({ status: false, message: "پرداخت ناموفق بود", }); } checkPayment.status = "paid"; checkPayment.refId = verify?.response?.ref_id; checkPayment.getPayment = true; checkPayment.fee_type = verify?.response?.fee_type; checkPayment.card_hash = verify?.response?.card_hash; checkPayment.card_pan = verify?.response?.card_pan; checkPayment.fee = verify?.response?.fee; checkPayment.created_at = Date.now(); checkPayment.createdOn = Date.now(); await checkPayment.save(); /// only for buy food execute this action if (checkPayment.action === "payOrder") { const getOrder = await Order.findById(checkPayment.order_id._id); if (!getOrder) return res404(res, "سفارش پیدا نشد"); for (const food of getOrder.order_items) { const getFood = await Food.findById(food.product_id); if (getFood) { getFood.stock = getFood.stock - food.quantity; // getFood.canReview.push(req.user._id)///add user id for review getFood.save(); } } if (getOrder.discount_code) { const discount = await DiscountCode.findOne({ discount_code: getOrder.discount_code }); if (discount) { discount.used_by.push(getOrder.user_id); await discount.save(); } } if (user) { /// decrease score if (getOrder?.score) { getOrder.scorePoint = user.score; getOrder.scoreCost = user.score * getOrder?.pricePoint; user.scoreLogs = [ { score: user.score, order_id: getOrder._id, forWhat: "buy", action: "decrease", }, ]; user.score = 0; await user.save(); } /// decrease bag if (getOrder.bag) { const addPayment = await Payment.create({ user_id: user._id, order_id: getOrder._id, transactionId: Date.now(), refId: Date.now(), getPayment: true, action: "decreaseBag", status: "paid", cost: user.bagAmount, }); getOrder.payment.push(addPayment._id); getOrder.bagCost = user.bagAmount; user.bagAmount = 0; await user.save(); } if (!getOrder.score || !getOrder?.discount_code) { // add point for user only for available product const computeAvaPro = await _computeHavePointPrice(getOrder?.order_items); /// add score for order if (computeAvaPro >= getOrder?.totalPricePoint && getOrder?.totalPricePoint > 0) { const point = Math.floor(computeAvaPro / getOrder?.totalPricePoint) * getOrder?.pointForBuy; if (point > 0) { user.score = user.score + point; user.scoreLogs = [ { score: point, order_id: getOrder._id, forWhat: "buy", action: "increase", }, ]; await user.save(); } } } } getOrder.statuses.push({ status: "processing", }); getOrder.status = "processing"; getOrder.paymentStatus = "paid"; await getOrder.save(); //----------------------- send notif for admins ----------------- const fcmTokens = []; const allAdmins = await User.find({ scope: "admin" }); for (const admin of allAdmins) { if (admin.fcmToken) fcmTokens.push(admin.fcmToken); } const objNotif = { title: "سفارش جدید!", body: "یک سفارش جدید در پنل برگ من ثبت گردید", }; const payload = { notification: objNotif, }; const input = { registrationTokens: fcmTokens, payload, }; await sendMulti(input); sendNotifyOrder(getOrder?.branchId); //---------------------------------------------------------------- //--------------------- send notif to user -------------------------- const messageUser = { title: "ثبت سفارش", body: "با تشکر از اعتماد شما سفارش شما با موفقیت ثبت شد", }; const payloadUser = { notification: messageUser, }; const inputUser = { registrationTokens: user.fcmToken, payload: payloadUser, }; await sendSingle(inputUser); //------------------------------------------------------------------- //------------------------------- send sms -------------------------- const smsTemplate = `سفارش شما با موفقیت ثبت شد با تشکر از اعتماد شما برگ من لغو11`; const smsResult = await sms(user.mobile_number, smsTemplate); if (!smsResult) { return res500(res, `مشکلی در ارسال پیامک پیش آمده است`); } //------------------------------------------------------------------- } else if (checkPayment.action === "increaseBag") { if (!user) return res.json({ status: false, message: "مشکلی در افزایش موجودی کیف پول شما پیش آمده است لطفا با پشتیبانی تماس بگیرید", }); user.bagAmount = user.bagAmount + checkPayment?.cost; await user.save(); //--------------------- send notif to user -------------------------- const messageUser = { title: "افزایش موجودی", body: "با تشکر از اعتماد شما کیف پول شما با موفقیت شارژ شد برگ من", }; const payloadUser = { notification: messageUser, }; const inputUser = { registrationTokens: user.fcmToken, payload: payloadUser, }; await sendSingle(inputUser); //------------------------------------------------------------------- //------------------------------- send sms -------------------------- const smsTemplate = `با تشکر از اعتماد شما کیف پول شما با موفقیت شارژ شد برگ من لغو11`; const smsResult = await sms(user.mobile_number, smsTemplate); if (!smsResult) { return res500(res, `مشکلی در ارسال پیامک پیش آمده است`); } //------------------------------------------------------------------- } return res.json({ status: true, refId: verify?.response?.ref_id, fromWhere: user?.fromWhere || "app", message: "پرداخت با موفقیت انجام شد", }); } else { /// only for buy food execute this action if (checkPayment.action === "payOrder") { let getOrder = await Order.findById(checkPayment.order_id._id); if (getOrder) { getOrder.statuses.push({ status: "void", }); getOrder.status = "void"; getOrder.paymentStatus = "unpaid"; await getOrder.save(); } checkPayment.getPayment = true; checkPayment.created_at = new Date(); await checkPayment.save(); } return res.json({ status: false, fromWhere: user?.fromWhere || "app", message: "پرداخت ناموفق بود", }); } } catch (error) { console.log(error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.addAddressToOrder = [ (req, res) => { Order.findById(req.params.order_id) .then((order) => { if (!order.address) { User.findOne({ "addresses._id": req.body.address_id }) .then((user) => { order.address = user.addresses.id(req.body.address_id); // add processing status to order order.statuses.push({ status: "processing", }); order.save(); return res.json(order); }) .catch((err) => { return res500(res, err); }); } else { return res.status(500).json({ message: v_m[req.body.locale].response.already_has_address }); } }) .catch((err) => { return res404(res, err); }); }, ]; module.exports.addStatusToOrder = [ async (req, res) => { try { const order = await Order.findById(req.params.order_id).populate("user_id"); if (!order) return res404(res, "سفارش مورد نظر یافت نشد"); order.statuses.push({ status: req.body.status, }); order.status = req.body.status; order.save(); if (req.body.status === "delivered") { //--------------------- send notif to user -------------------------- const messageUser = { title: "ارسال سفارش", body: "سفارش شما ارسال گردید با تشکر برگ من", }; const payloadUser = { notification: messageUser, }; const inputUser = { registrationTokens: order?.user_id?.fcmToken, payload: payloadUser, }; await sendSingle(inputUser); //------------------------------------------------------------------- setTimeout(async () => { let smsTemplate = ""; if (order.user_id.fromWhere === "app") smsTemplate = `لطفا با ثبت نظر برای سفارش خود به ما برای خدمات بهتر کمک کنید با تشکر برگ من`; else smsTemplate = `لطفا با ثبت نظر برای سفارش خود به ما برای خدمات بهتر کمک کنید با تشکر برگ من لغو11 لینک : https://app.bargrestaurant.com/rate/${req.params.order_id}`; const smsResult = await sms(order?.user_id?.mobile_number, smsTemplate); //--------------------- send notif to user -------------------------- const messageUser = { title: "ثبت نظر", body: "لطفا با ثبت نظر برای سفارش خود به ما برای خدمات بهتر کمک کنید با تشکر", }; const payloadUser = { notification: messageUser, }; const inputUser = { registrationTokens: order?.user_id?.fcmToken, payload: payloadUser, }; await sendSingle(inputUser); //------------------------------------------------------------------- if (!smsResult) { console.log("order sms", smsResult); } }, timeToStart); } return res.json(order); } catch (error) { console.log(error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.changePayStatus = [ [ body("status") .notEmpty() .withMessage(_sr["fa"].required.field) .bail() .isIn(["refund", "unpaid", "paid"]) .withMessage("وضعیت ارسال شده صحیح نمی باشد"), ], checkValidations(validationResult), async (req, res) => { try { const targetOrder = await Order.findById(req.params.id); if (!targetOrder) return res404(res, "سفارش مورد نظر پیدا نشد"); const targetPayment = await Payment.findById(targetOrder.payment); if (targetPayment) { targetPayment.status = req.body.status; await targetPayment.save(); } targetOrder.paymentStatus = req.body.status; await targetOrder.save(); return res.json({ message: _sr["fa"].response.success_save }); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.getOrders = [ (req, res) => { const branchId = req?.params?.branchId; Order.find({ branchId, user_id: req.user._id, status: { $in: ["canceled", "processing", "sent", "delivered"] }, paymentStatus: "paid", }) .populate({ path: "order_items.product_id", select: "name canReview ratings", }) .sort({ _id: -1 }) .then((orders) => { const allOrders = []; for (const item of orders) { let clone = JSON.parse(JSON.stringify(item.order_items)); clone.map((food) => { // food.review = food?.product_id?.canReview?.includes(req.user._id.toString()) // food.rating = food?.product_id?.ratings?.find(rate => rate.user_id.toString() === req.user._id.toString() && rate?.order_id?.toString() === item?._id?.toString())?.rate || 0 food.rating = food?.product_id?.ratings?.find((rate) => rate?.user_id?.toString() === req?.user?._id.toString())?.rate || 0; }); allOrders.push({ _id: item._id, address: item.address, status: item.status, items: clone, orderType: item.orderType, review: item.rating.rate, created_at: item.createdOn, total: item.total, }); } return res.json(allOrders); }) .catch((err) => { console.log(err.message); return res500(res, _sr["fa"].response.unknownError); }); }, ]; module.exports.getOrdersForReport = [ async (req, res) => { try { const branchId = req?.params?.branchId; const orders = await Order.find({ branchId, status: { $in: ["canceled", "processing", "sent", "delivered"] }, paymentStatus: "paid", }); return res.json(orders); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.getOneOrderByUser = [ async (req, res) => { try { const targetOrder = await Order.findOne({ _id: req.params.id, user_id: req.user._id }).select("status"); if (!targetOrder) return res404(res, "سفارش مورد نظر پیدا نشد"); return res.json(targetOrder); } catch (error) { console.log("get one order by user |", error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.deleteOrder = [ async (req, res) => { try { const targetOrder = await Order.findById(req.params.id); if (!targetOrder) return res404(res, "سفارش مورد نظر پیدا نشد"); /// @todo maybe delete payment too await targetOrder.deleteOne(); return res.json({ message: _sr["fa"].response.success_remove }); } catch (error) { console.log("delete order: ", error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.increaseBag = [ [body("price").notEmpty().withMessage(`لطفا یک مقدار مشخص کنید`)], checkValidations(validationResult), async (req, res) => { try { const cost = req.body.price; const user = await User.findById(req.user._id); if (!user) return res404(res, `اطلاعات کاربر پیدا نشد`); const request = await zarinpal.request(cost, "کیف پول", req.user); if (!request.status) { console.log(request); return res500(res, _sr["fa"].response.unknownError); } // add payment to order await Payment.create({ user_id: user._id, order_id: null, transactionId: request.response.authority, cost: cost, action: "increaseBag", }); return res.json({ paymentUrl: `${zarinUrl}/${request.response.authority}` }); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; /////// admin panel module.exports.getOneOrder = [ (req, res) => { Order.findById(req.params.id) .populate({ path: "user_id", select: "first_name last_name scoreLogs", }) .populate("order_items.product_id") .populate("payment") .then((order) => { return res.json(order); }) .catch((err) => { return res404(res, err); }); }, ]; module.exports.search = [ async (req, res) => { try { let { branchId, number, orderStatus, paymentStatus, userId, date } = req.body; let findQuery = { branchId, status: { $nin: ["incomplete", "void"] }, }; findQuery["$and"] = []; findQuery["$or"] = []; /** search by number */ if (number && !_.isEmpty(number)) { findQuery["$and"].push({ number, }); } /** search by orderStatus */ if (orderStatus && !_.isEmpty(orderStatus)) { findQuery["$and"].push({ status: { $in: orderStatus, }, }); } /** search by paymentStatus */ if (paymentStatus && !_.isEmpty(paymentStatus)) { findQuery["$and"].push({ paymentStatus: { $in: paymentStatus, }, }); } /** search by user_id */ if (userId && !_.isEmpty(userId)) { findQuery["$and"].push({ user_id: userId, }); } /** search by date */ if (date && !_.isEmpty(date)) { if (date.length === 1) { findQuery["$and"].push({ createdOn: { $gte: moment(date[0]).startOf("days"), $lt: moment(date[0]).endOf("days"), }, }); } else { findQuery["$and"].push({ createdOn: { $gte: new Date(date[0]), $lt: new Date(date[1]), }, }); } } _.isEmpty(findQuery["$and"]) && delete findQuery["$and"]; _.isEmpty(findQuery["$or"]) && delete findQuery["$or"]; /** get news */ const orders = await Order.paginate(findQuery, { page: req.query.page, limit, populate: [{ path: "user_id", select: "first_name last_name" }], sort: { _id: -1, }, }); /** show result */ return res.json(orders); } catch (error) { console.log(error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.reports = [ // [ // body('startDate') // .notEmpty().withMessage(_sr['fa'].required.date), // // body('endDate') // .notEmpty().withMessage(_sr['fa'].required.date), // ], // checkValidations(validationResult), async (req, res) => { try { const branchId = req?.params?.branchId; let findQuery = { branchId, status: { $nin: ["incomplete", "void"] }, }; let { startDate, endDate } = req.body; // if (!startDate || !endDate){ // findQuery.createdOn = { // createdOn: { // $gte: moment().startOf('days'), // $lt: moment().endOf('days') // } // } // }else { if (startDate && endDate) { findQuery.createdOn = { $gte: new Date(startDate), $lt: new Date(endDate), }; } else if (startDate) { findQuery.createdOn = { $gte: moment(startDate), $lt: new Date(), }; } else if (endDate) { findQuery.createdOn = { // $gte: '', $lt: moment(endDate), }; } // } /** search by date */ // if (startDate || endDate && !_.isEmpty(date)) { // if (date.length === 1) { // findQuery.createdOn = { // $gte: moment(startDate), // $lt: moment(startDate) // } // } else { // findQuery.createdOn = { // $gte: new Date(date[0]), // $lt: new Date(date[1]) // } // } // } else { // // } /** get news */ const orders = await Order.find(findQuery).populate({ path: "user_id", select: "first_name last_name" }).sort({ _id: -1 }); let result = { count: orders?.length || 0, total: orders?.reduce((total, item) => { return total + item?.total; }, 0) || 0, payOnline: orders?.reduce((total, item) => { return total + item?.payTotal; }, 0) || 0, routePrice: orders?.reduce((total, item) => { return total + item?.routePrice; }, 0) || 0, bagCost: orders?.reduce((total, item) => { return total + item?.bagCost; }, 0) || 0, scorePoint: orders?.reduce((total, item) => { return total + item?.scorePoint; }, 0) || 0, scoreCost: orders?.reduce((total, item) => { return total + item?.scoreCost; }, 0) || 0, }; /** show result */ return res.json(result); } catch (error) { console.log(error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; //////////////////////////////////// compute price module.exports.computePrice = [ //////////////////// validation step (req, res, next) => { const branchId = req?.params?.branchId; CartItem.find({ branchId, user_id: req.user._id }).then((items) => { // check if cart is not empty if (items.length) { // check product stock let outOfRun = []; items.forEach(async (item, index) => { await Food.findById(item.product_id).then((product) => { if (product.stock < item.quantity) { outOfRun.push({ product_id: product._id, category_id: product.category, stock: product.stock, }); item.remove(); } if (index + 1 === items.length) { if (!outOfRun.length) return next(); else return res.status(422).json(outOfRun); } }); }); } else { return res.status(404).json({ message: _sr["fa"].response.cart_empty }); } }); }, async (req, res) => { try { const branchId = req?.params?.branchId; const cartItems = await CartItem.find({ branchId, user_id: req.user._id }).populate({ path: "product_id", populate: { path: "category", model: "FoodCategory", }, }); const checkOrder = await Order.findOne({ branchId, status: "incomplete", user_id: req.user._id }); const getUserInfo = await User.findById(req.user._id); const getStoreInfo = await StoreInfo.findOne({ _id: branchId }); const product = []; const userAddress = getUserInfo.addresses.find((item) => item.used === true) || null; let specialDiscountMenuType = false; let discount_percent = checkOrder?.discount_amount || 0; let discount_menuType = checkOrder?.discount_menuType; let routePrice = 0; let sum = 0; let sumFoodByPercent = 0; let sumFoodByPercentForDiscount = 0; let total = 0; let percent = 0; let tax = 0; if (!getUserInfo) return res404(res, `اطلاعات کاربر یافت نشد`); if (!cartItems.length) return res.status(404).json({ message: `هیچ محصولی در سبد خرید شما وجود ندارد` }); if (checkOrder) { const orderItems = []; for (const item of cartItems) { orderItems.push({ product_id: item.product_id._id, name: item.product_id.name, quantity: item.quantity, price: item.product_id.price, static_discount: item.product_id.static_discount, havePoint: item.product_id.havePoint, }); product.push({ product: item.product_id, quantity: item.quantity, }); const itemPercent = (item.product_id.price * item.product_id.static_discount) / 100; const sumPercent = itemPercent * item.quantity; const price = item.product_id.price; const sumPriceItem = price * item.quantity; let sumByPercentForDiscount = sumPriceItem - sumPercent; if (Boolean(discount_percent) && discount_menuType) { specialDiscountMenuType = true; if (item?.product_id?.category.type?.toString() === discount_menuType?.toString()) { sumFoodByPercentForDiscount += sumByPercentForDiscount; } } sum = sum + sumPriceItem; /// sum food price without percent percent = percent + sumPercent; /// sum all food percent } /// sum food price with percent sumFoodByPercent = sum - percent; /// compute shipping cost if (getStoreInfo) { if (getStoreInfo?.shippingType) { routePrice = getStoreInfo?.shippingCost || 0; } else { routePrice = (await _computeShippingCostByRoad(getUserInfo?.addresses, getStoreInfo?.location)) * (getStoreInfo?.shippingCost || 0) || 0; } /// compute tax of order if (getStoreInfo?.tax) { tax = (sumFoodByPercent * 9) / 100; } } /// compute discount code if (Boolean(discount_percent)) { let discountPercent = ((specialDiscountMenuType ? sumFoodByPercentForDiscount : sumFoodByPercent) * discount_percent) / 100; percent = percent + discountPercent; /// compute sum food with discount percent sumFoodByPercent = sumFoodByPercent - discountPercent; } /// compute total of order total = sumFoodByPercent + tax + routePrice; checkOrder.order_items = orderItems; checkOrder.createdOn = Date.now(); checkOrder.sum = Math.ceil(sum); checkOrder.routePrice = Math.ceil(routePrice); checkOrder.tax = Math.ceil(tax); checkOrder.percent = Math.ceil(percent); checkOrder.total = Math.ceil(total); checkOrder.pricePoint = getStoreInfo?.pricePoint; if (checkOrder.bag) { const payPrice = total - getUserInfo?.bagAmount; total = payPrice <= 0 ? 0 : payPrice; } if (checkOrder.score && getStoreInfo?.pricePoint > 0) { const payScore = total - getUserInfo?.score * getStoreInfo?.pricePoint; total = payScore <= 0 ? 0 : payScore; } checkOrder.payTotal = Math.ceil(total); checkOrder.save(); } return res.json({ usePoint: getStoreInfo?.usePointWhenPay, product, userAddress, sum: Math.ceil(sum), routePrice: Math.ceil(routePrice), tax: Math.ceil(tax), percent: Math.ceil(percent), total: Math.ceil(checkOrder.payTotal), }); } catch (error) { console.log(error.message); return res500(res, _sr["fa"].response.unknownError); } }, ]; ////////////////////////////////////// get list of all orders for admin module.exports.getAllOrders = [ async (req, res) => { try { const branchId = req?.params?.branchId; const orders = await Order.paginate( { branchId, status: { $nin: ["incomplete", "void"] } }, { page: req.query.page || 1, limit, populate: [{ path: "user_id", select: "first_name last_name" }], sort: { _id: -1 }, }, ); return res.json(orders); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; ///////////////////////////////////// get payment list module.exports.getAllPaymentByUser = [ async (req, res) => { try { const getAll = await Payment.find({ user_id: req.user._id }).sort({ _id: -1 }); return res.json(getAll); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; module.exports.getAllPaymentByAdmin = [ async (req, res) => { try { const getAll = await Payment.paginate( { user_id: req.params.id }, { page: req.query.page || 1, limit, sort: { _id: -1 }, }, ); return res.json(getAll); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; //////////////////////////////////// get all foods for rates module.exports.getAllRateFood = [ async (req, res) => { try { const getOrder = await Order.findOne({ _id: req.params.order_id, user_id: req.user._id, status: "delivered", paymentStatus: "paid", }).populate({ path: "order_items.product_id", select: "name ratings", }); if (!getOrder) return res404(res, `سفارش مورد نظر پیدا نشد`); return res.json(getOrder); } catch (e) { return res500(res, _sr["fa"].response.unknownError); } }, ]; /////////////////////////////////// rate order module.exports.rateOrderAndFood = [ [body("rateOrder").notEmpty().withMessage(_sr["fa"].required.field)], checkValidations(validationResult), async (req, res) => { try { const orderId = req?.params?.order_id; const { rateOrder, reason, foods } = req.body; const getOrder = await Order.findOne({ _id: orderId, user_id: req.user._id, status: "delivered", paymentStatus: "paid", }); if (!getOrder) return res404(res, `سفارش مورد نظر پیدا نشد`); //// add rate for all foods for (const food of foods) { const data = { rate: food.rate, comment: food.comment, order_id: getOrder._id, user_id: getOrder.user_id, }; //// check food exist or not const getFood = await Food.findById(food?.product_id?._id); if (getFood && getOrder?.order_items.some((item) => item?.product_id?._id?.toString() === getFood?._id?.toString())) { getFood.ratings.push(data); let rateSUM = 0; getFood?.ratings?.forEach((item) => (rateSUM += Number(item.rate))); getFood.rate = (rateSUM / getFood?.ratings?.length).toFixed(1); await getFood.save(); } } //// add rate to order getOrder.rating = { rate: rateOrder, reasonForBad: reason, }; await getOrder.save(); return res.json({ message: _sr["fa"].response.success_save }); } catch (e) { return res500(res, _sr["fa"].response.unknownError); } }, ]; ////////////////////////////////// buy club module.exports.buyClub = [ [body("clubId").notEmpty().withMessage(_sr["fa"].required.field)], checkValidations(validationResult), async (req, res) => { try { const clubId = req.body?.clubId; const user = await User.findById(req.user._id); if (!user) return res404(res, "اطلاعات کاربر یافت نشد"); const club = await Food.findOne({ _id: clubId, club: true }); if (!club) return res404(res, "کلاب مورد نظر پیدا نشد"); if (user.score < club.point) return res.status(422).json({ message: "امتیاز شما برای خرید این محصول کافی نمی باشد" }); const data = { user_id: user._id, score: true, scorePoint: club.point, scoreCost: club.price, orderType: "club", number: Date.now(), address: user?.addresses.find((item) => item.used), createdOn: Date.now(), paymentStatus: "paid", statuses: [ { status: "processing", }, ], status: "processing", order_items: [ { product_id: club._id, name: club.name, quantity: 1, price: club.price, point: club.point, havePoint: true, }, ], sum: club.point, routePrice: 0, tax: 0, percent: 0, total: club.price, }; const order = await Order.create(data); if (!order) return res500(res, _sr["fa"].response.unknownError); user.score -= club.point; user.scoreLogs = [ { score: club.point, order_id: order._id, forWhat: "buy", action: "decrease", }, ]; await user.save(); club.stock -= club?.clubQuantity || 1; await club.save(); return res.json({ message: _sr["fa"].response.success_save }); } catch (error) { return res500(res, _sr["fa"].response.unknownError); } }, ]; ////////////////////////////////// test notif module.exports.testNotif = [ async (req, res) => { try { sendNotifyOrder("6126313206f2593a6a4f71db"); return res.json({}); } catch (error) { return res500(res, error.message); } }, ]; module.exports.chromeNotif = [ async (req, res) => { try { const fcmTokens = []; const allAdmins = await User.find({ scope: "admin" }); for (const admin of allAdmins) { if (admin.fcmToken) fcmTokens.push(admin.fcmToken); } const objNotif = { title: "سفارش جدید!", body: "یک سفارش جدید در پنل برگ من ثبت گردید", }; const payload = { notification: objNotif, data: { routeName: "test", type: "bazaar", routeType: "viewBazaar", }, }; console.log(fcmTokens); const input = { registrationTokens: fcmTokens, payload, }; console.log(input); const test = await sendMulti(input); return res.json(test); // const payload = JSON.stringify({ // title: 'Push notifications with Service Workers', // }); // // webPush.sendNotification('test', payload) // .catch(error => console.error(error)); } catch (error) {} }, ];