Files
mahyargdz dff1adc5bf
deploy to danak / build_and_deploy (push) Has been cancelled
update: the sms service to use new sms panel
2025-02-16 13:37:56 +03:30

1929 lines
62 KiB
JavaScript

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) {}
},
];