Created
July 9, 2025 07:28
-
-
Save meshv94/e00e685c4f3fe2f4f358748b84afab50 to your computer and use it in GitHub Desktop.
Revisions
-
meshv94 created this gist
Jul 9, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,658 @@ exports.grocery_payment_new = async (req, res) => { try { const schema = Joi.object().keys({ allCart_id: Joi.array().min(1).required(), deliveryType: Joi.string().required(), address_id: Joi.string().optional(), total_price: Joi.number().required(), promo_code: Joi.string().allow("").optional(), payment_mode: Joi.string().allow("").optional(), delivery_date: Joi.string().required(), delivery_option: Joi.string().allow("").optional(), order_id: Joi.string().allow("").optional(), time_slot: Joi.string().allow("").optional(), starttime: Joi.number().required(), endtime: Joi.number().required(), // expresstime: Joi.number().required(), payment_token: Joi.number().optional(), deliveryCharge: Joi.number().optional(), // convienceCharge: Joi.number().optional(), // weight: Joi.number().required(), sqr_amount: Joi.number().allow("").optional(), order_comments: Joi.string().allow("").optional(), // no_of_person: Joi.number().allow("").optional(), // no_of_child: Joi.number().allow("").optional(), ussd_phone_number: Joi.number().allow("").optional(), // has_cutlery: Joi.boolean().optional(), item_out_of_stock_options: Joi.number().allow("").optional(), service_fees: Joi.number().allow(0).optional(), service_fees_list: Joi.string().allow("").optional() }); const validateQuery = Joi.validate(req.body, schema, { abortEarly: true }); if (validateQuery.error) { if (validateQuery.error.details && validateQuery.error.details[0].message) { res.status(200).json({ status_code: status.BAD_REQUEST, message: validateQuery.error.details[0].message }); } else { res.status(200).json({ status_code: status.BAD_REQUEST, message: validateQuery.error.message }); } return; } var { deliveryCharge, allCart_id, deliveryType, address_id, promo_code, total_price, payment_mode, delivery_date, delivery_option, time_slot, starttime, endtime, payment_token, ussd_phone_number } = req.body var service_fees = (req.body.service_fees)?req.body.service_fees:0 var service_fees_list = (req.body.service_fees_list)?req.body.service_fees_list:"" //comment this n add new one on 25-12-2021 as check non-operating module wise logic // var checkifItsHoliday = await checkIsHoliday(delivery_date, starttime) var checkifItsHoliday = await checkIsHoliday(delivery_date, starttime, 'NewGrocery') if (checkifItsHoliday == "yes") { var reqLanguage = req.headers.language var sendHolidayMessage = settingsFoodHolidayMessageSw if (reqLanguage == "en") { sendHolidayMessage = settingsFoodHolidayMessageEn } res.status(200).json({ status_code: 400, message: sendHolidayMessage }) return } const isItemOutOfStock = await checkCartItemOutOfStock(allCart_id); if (isItemOutOfStock.is_item_out_of_stock) { return res.status(200).send({ status_code: 422, message: isItemOutOfStock.error_msg }); } var promo_code_discount = 0 var cash_discount = 0 if (promo_code) { if (promo_code != "") { var checkIsPromoExpired = "No" var loggedInUserId = req.user._id var promoDetails = await getAppliedPromocode(loggedInUserId, "New Grocery", "applied", ""); // console.log("::::::: promo_code promoDetails promoDetails promoDetails :::: ", promoDetails) if (promoDetails) { if (promoDetails.promocode_id != null) { promo_code_discount = promoDetails.discount if (promoDetails.promo_code_type == "Cash Discount") { cash_discount = promoDetails.discount } if (promoDetails.free_delivery_charge == true) { deliveryCharge = 0 } /* Check promo code allowed payment methods */ var paymentMethod = await convertPaymentMethod(payment_mode) var allowedPaymentMethods = promoDetails.promocode_id.payment_methods if (allowedPaymentMethods.includes(paymentMethod) == false) { res.status(200).json({ status_code: 400, message: req.lang.Invalid_Promo_code }) return } /* check minimum order */ var totalOrderAmount = total_price + deliveryCharge if (totalOrderAmount < promoDetails.promocode_id.minimumOrder) { res.status(200).json({ status_code: 400, message: req.lang.Invalid_Promo_code + " Minimum amount to use this promocode is " + promoDetails.promocode_id.minimumOrder }) return } } else { checkIsPromoExpired = "Yes" } } else { checkIsPromoExpired = "Yes" } if (checkIsPromoExpired == "Yes") { res.status(200).json({ status_code: 400, message: req.lang.Promo_code_expired }) return } } } var sqr_amount = 0 if (typeof sqr_amount != 'undefined' && req.body.sqr_amount) { sqr_amount = req.body.sqr_amount } var userComments = "" if (typeof req.body.order_comments != 'undefined' && req.body.order_comments) { userComments = req.body.order_comments } // var noOfPerson = "" // var noOfChilds = "" // if (typeof req.body.no_of_person != 'undefined' && req.body.no_of_person && req.body.no_of_person != '') { // noOfPerson = req.body.no_of_person // } // if (typeof req.body.no_of_child != 'undefined' && req.body.no_of_child && req.body.no_of_child != '') { // noOfChilds = req.body.no_of_child // } var charges = await calculateConvenienceCharge(allCart_id, deliveryType) var convienceCharge = charges.packagingCharge var dukaConvienceCharge = charges.convienceCharge var reCalcTotalPrice = await reCalculateGroceryCartTotal(allCart_id) var totalCalculatedAmount = reCalcTotalPrice + convienceCharge + service_fees var ussd_phone_number = "" if (typeof ussd_phone_number != 'undefined' && req.body.ussd_phone_number) { ussd_phone_number = req.body.ussd_phone_number console.log("ussd_phone_number inside", ussd_phone_number) } if (starttime == 0 || starttime == "0") { starttime = moment.tz(moment(), 'Africa/Dar_es_Salaam').format('HH'); //h or HH } if (time_slot == "" || time_slot == null) { if (deliveryType == "Home_Delivery") { let currentNowTime = moment().add(8, 'm').tz(newLocalTimeZone).format('H:mm'); let currentNowEnd = moment().add(2, 'hours').tz(newLocalTimeZone).format('H:mm'); // "time_slot":"19:00 hours - 22:00 hours", time_slot = currentNowTime + " hours - " + currentNowEnd + " hours" } else if (deliveryType == 'Pick_Up') { let currentNowTimeAM = moment().add(8, 'm').tz(newLocalTimeZone).format('hh:mm a'); let currentNowEndAM = moment().add(2, 'hours').tz(newLocalTimeZone).format('hh:mm a'); //10:00 am to 11:00 am //h:mm a time_slot = currentNowTimeAM + " to " + currentNowEndAM } } // console.log("created time_slot: Place Order ", time_slot) let settings = await GroceryvendorLocation(allCart_id) if (settings) { if (deliveryType != 'Pick_Up') { // let settings = await SettingsModel.findOne({type:"User"}) if (req.body.total_price < settings.minimum_order) { commonFun.sendNotification(req.user, EN.Minimum_Order_REST, EN.Minimum_Order_REST, SW.Minimum_Order_REST, 3, "Minimum Order", new Date(), 0, "") var lang = req.user.selected_language var message = EN.Minimum_Order_REST if (lang == 'sw') message = SW.Minimum_Order_REST /* sendNotification(req.user, EN.Minimum_order_error + "" + formatNumber(settings.minimum_order), EN.Minimum_order_error + "" + formatNumber(settings.minimum_order), SW.Minimum_order_error + "" + formatNumber(settings.minimum_order), 3, "Minimum Order", new Date(), 0, "") var lang = req.user.selected_language var message = EN.Minimum_order_error + "" + formatNumber(settings.minimum_order) if (lang == 'sw') message = SW.Minimum_order_error + "" + formatNumber(settings.minimum_order) */ res.status(200).send({ status_code: 400, message: message }) //:"minimum order violated" return } } var checkRestStatus = await getGroceryVendorOpenStatus(settings._id) // console.log("checkRestStatus checkRestStatuscheckRestStatus checkRestStatus ", checkRestStatus) // add delivery_date in condition on 03-12-2021 as allow later order for close restaurant if ((checkRestStatus == "0" && delivery_date == 'NOW') || (checkRestStatus == 0 && delivery_date == 'NOW')) { // if (checkRestStatus == "0" || checkRestStatus == 0) { var ResStatusMsg = (EN.Restuarant_Not_available).replace("%RestaurantName%", settings.name).replace("%RestOpenHours%", settings.open_time).replace("%RestclosingHours%", settings.close_time) if (req.selected_language == "en") { ResStatusMsg = (EN.Restuarant_Not_available).replace("%RestaurantName%", settings.name).replace("%RestOpenHours%", settings.open_time).replace("%RestclosingHours%", settings.close_time) } else { ResStatusMsg = (SW.Restuarant_Not_available).replace("%RestaurantName%", settings.name).replace("%RestOpenHours%", settings.open_time).replace("%RestclosingHours%", settings.close_time) } res.status(200).send({ status_code: 400, message: ResStatusMsg }) return } } //check if user has quickrewards balance or not var requestMsidn = "" if (NODEENV != "development") { if (sqr_amount) { if (sqr_amount > 0) { requestMsidn = "255" + req.user.mobile_number var checkQRBalance = await getUserQuickRewardsbalance(requestMsidn) checkQRBalance = 1111 if (checkQRBalance == 0) { res.status(200).send({ status_code: 400, message: "Insufficient Balance" }) return } } } } // const inactive_status = await checkFIROrRestInactiveStatus(allCart_id); // if (!inactive_status.is_fir_or_rest_active) { // return res.status(200).send({ status_code: 400, message: inactive_status.error_msg }); // } let order_id = await generate(5); let transid = order_id var { allCart_id, total_price } = req.body total_price = totalCalculatedAmount var cartdata = { allCart_id, transid, total_price } cartdata.user_id = req.user._id // let findQueryCustAcceptedOrder = { // 'user_id': cartdata.user_id, // 'status': { $nin: ["Order Placed", "New", "Cancelled", "Pending"] }, // "isPlaced": true, // } // let customer_accepted_order_length = await GroceryCartHistoryModel.find(findQueryCustAcceptedOrder).count() // var is_first_order = true // if (customer_accepted_order_length > 0) { // is_first_order = false // //isFirstOrder // } var data = { transid: transid, allCart_id: allCart_id, total_price: total_price, user_id: req.user._id, is_paid: false, isPlaced: false, isCancelled: false, deliveryCharge: deliveryCharge, convienceCharge: convienceCharge, is_modified: "0", order_comments: userComments, service_fees:service_fees, service_fees_list, service_fees_list, dukaConvienceCharge:dukaConvienceCharge} carthistory = new GroceryCartHistoryModel(data) let carthi = await carthistory.save() .then(async (saveData) => { return saveData }).catch(async err => { console.log(err) }) // var delivery_date = await get_delivery_date_grocery(delivery_date, starttime) var populatequery = { path: 'product_id', populate: { path: 'grocery_vendor_id', model: "groceryvendors", } } console.log('$allCart_id[0]$',allCart_id[0]) let check_data = await GroceryCartModel.findOne({ _id: allCart_id[0] }).populate(populatequery) console.log('$check_data.product_id.grocery_vendor_id.is_selected_day_vendor$',check_data.product_id.grocery_vendor_id.is_selected_day_vendor) var delivery_date = await get_delivery_date_grocery(delivery_date, starttime,check_data.product_id.grocery_vendor_id.is_selected_day_vendor,check_data.delivery_date) // return false if (deliveryType == "Home_Delivery") { if (!req.body.address_id || req.body.address_id == '') { responses.sendErrorDuka("Address missing 18755 ", res) return } } let result = await grocery_masterpass_selcom_place_order_new(order_id, deliveryCharge, allCart_id, deliveryType, address_id, promo_code, total_price, payment_mode, delivery_date, delivery_option, time_slot, starttime, endtime, payment_token, req.user, sqr_amount) console.log(order_id, + " place order result: 18762---" + result) if (result == "true") { var billingAddress = {} if (address_id === "" || address_id.length === 0 || !address_id || deliveryType == "Pick_Up") { // add condition on 1-2-2022 as send user data in billing data var billingAddress = await AddressModel.findOne({ user_id: req.user._id }) } else { var billingAddress = await AddressModel.findOne({ _id: address_id }) } var postcode_or_pobox = "12345" var billing = { firstname: billingAddress.name, lastname: billingAddress.name, address_1: billingAddress.detail_address, city: billingAddress.city, state_or_region: billingAddress.area, postcode_or_pobox: postcode_or_pobox, // country:billingAddress.country_code, country: "TZ", phone: "255" + req.user.mobile_number // phone: "255656724750" } if (billing.postcode_or_pobox == "" || billing.postcode_or_pobox == "0" || billing.postcode_or_pobox == null) { billing.postcode_or_pobox = 12345 } if (billing.state_or_region == "" || billing.state_or_region == "0" || billing.state_or_region == null) { billing.state_or_region = "N/A" } let result = "" var gateway_buyer_uuid = req.user.gateway_buyer_uuid var buyer_userid = req.user._id var no_of_items = 10 var redirect_url = Buffer.from(web_server_url + "redirect.html").toString('base64') var webhook = Buffer.from(server_url + "v2/new_grocery_add_card_callback").toString('base64') const webhook_selcom_pesa=server_url + "v2/new_grocery_add_card_callback" var currency = "TZS" var buyer_name = req.user.name var buyer_email = req.user.emailId.trim() // var buyer_phone = req.user.mobile_number var buyer_phone = "255" + req.user.mobile_number var findQryResturant = { transid: transid } // var foodVendorDetails = await getResturantDetails(findQryResturant); var vendor = DUKA_Food_VENDOR var payable_amount_qr = total_price payable_amount_qr = total_price + Number(deliveryCharge) + parseInt(dukaConvienceCharge) - Number(cash_discount) if (buyer_email == "") { buyer_email = buyer_phone + DEFAULT_EMAIL_DOMAIN } const requestBody = { "vendor": vendor, "order_id": order_id, "buyer_name": buyer_name, "buyer_userid": buyer_userid, "buyer_email": buyer_email, "buyer_phone": buyer_phone, // "amount": total_price, "amount": payable_amount_qr, "currency": currency, // "billing": billing, "no_of_items": no_of_items, "webhook": webhook, "redirect_url": redirect_url, // "tillvendor": resturantTillvendor, "sqr_amount": sqr_amount, "payment_methods": "ALL", "billing.firstname": billing.firstname, "billing.lastname": billing.lastname, "billing.address_1": billing.address_1, "billing.city": billing.city, "billing.state_or_region": billing.state_or_region, "billing.postcode_or_pobox": billing.postcode_or_pobox, "billing.country": billing.country, "billing.phone": billing.phone, "merchant_remarks": payment_mode } console.log(order_id, "before grocery_payment_new flight: card create order>>>>") let resultdelcomapi = await selcomapigw.sendRequest(NODEENV, '/v1/checkout/create-order', 'post', DUKA_FOOD_API_KEY, DUKA_FOOD_API_SECRET, order_id, requestBody).then(result => { if (result) { console.log(order_id, " Result Success grocery_payment_new ", result) if (result.result == "SUCCESS") { groceryCreateOrder(total_price, transid, req.user._id, sqr_amount).then( async orderResultData => { console.log(order_id, " Neew Order==> ", orderResultData) if (ussd_phone_number != "") { let Order_list_data = await OrderQueueModel.find({ allCart_id: { $in: allCart_id }, payment_mode: "Mobile Money", isCancelled: false}); console.log('Allcart_id ==>', allCart_id) console.log('Mobile Money Water OrderQueueData', Order_list_data.length, Order_list_data) if(Order_list_data.length > 0){ return res.status(415).json({ status_code: 415, message: Order_list_data[0].isPlaced ? "Your Order has already been placed" : "Your Mobile Money request is still under process kindly wait for some time" }); } if(payment_mode=="Selcom Pesa"){ let newrewestres = await commonFun.selcomPesaPay(order_id, ussd_phone_number).then(async resultUssd => { console.log(order_id, "push result ", resultUssd); await commonFun.saveMobileMoneyLogs(order_id, requestBody, resultUssd ); if (resultUssd.result == "SUCCESS") { GroceryCartHistoryModel.findByIdAndUpdate({ _id: orderResultData._id }, { selcom_reference: resultUssd.reference }).then( async cart => { } ) try { // var suborderId = await logSuborder( orderResultData._id, req) var suborderId = await logTempSuborder( orderResultData._id, req) } catch (error) { return res.status(200).json({ status_code: 416, message: "Your Order is already placed!" }) } console.log(order_id, 'response trandid-------- 17723 ----', suborderId) var subOrderDetail = await OrderQueueModel.find({ linkedTransid: suborderId }).exec() suborderId = subOrderDetail[0].transid var success_res = req.lang.Order_Placed_Successfully_msg.replace("%number%", suborderId); const data = { response: { reference: resultUssd.reference, resultcode: resultUssd.resultcode, result: resultUssd.result, order_id: suborderId, transid: subOrderDetail[0]._id }, message: success_res, status_code: 200 } try{ await SelcomPesaUserModel.create({ user_id: req.user._id, user_name: resultUssd.data[0].name, mobile_no: resultUssd.data[0].msisdn }); }catch(e){ console.log("Error In Selcom Pesa Details Saving",e) } console.log(order_id, "response to user 17740 --", data) res.status(200).json(data) //res.send(data) } else if (resultUssd.result == "FAIL") { const dataError = { response: { reference: resultUssd.reference, resultcode: resultUssd.resultcode, result: resultUssd.result, order_id: orderResultData.transid, transid: orderResultData._id }, message: resultUssd.message, status_code: parseInt(resultUssd.resultcode) } console.log(order_id, "response to user failure 17756--", dataError) //res.send(dataError) res.status(200).json(dataError) } }).catch(error => { var body = JSON.stringify(error) console.log("error response data***********\n: ", error) console.log(error) const dataError = { response: { reference: "", resultcode: "", result: "", order_id: orderResultData.transid, transid: orderResultData._id }, message: "Something went wrong", status_code: 424 } console.log("response to user failure 17777", dataError) //res.send(dataError) res.status(200).json(dataError) }) }else{ let newrewestres = await commonFun.ussd_push(transid, ussd_phone_number).then(async resultUssd => { console.log(order_id, "push result ", resultUssd); await commonFun.saveMobileMoneyLogs(order_id, requestBody, resultUssd ); if (resultUssd.result == "SUCCESS") { GroceryCartHistoryModel.findByIdAndUpdate({ _id: orderResultData._id }, { selcom_reference: resultUssd.reference }).then( async cart => { } ) try { // var suborderId = await logSuborder( orderResultData._id, req) var suborderId = await logTempSuborder( orderResultData._id, req) } catch (error) { return res.status(200).json({ status_code: 416, message: "Your Order is already placed!" }) } console.log(order_id, 'response trandid-------- 17723 ----', suborderId) var subOrderDetail = await OrderQueueModel.find({ linkedTransid: suborderId }).exec() suborderId = subOrderDetail[0].transid var success_res = req.lang.Order_Placed_Successfully_msg.replace("%number%", suborderId); const data = { response: { reference: resultUssd.reference, resultcode: resultUssd.resultcode, result: resultUssd.result, order_id: suborderId, transid: subOrderDetail[0]._id }, message: success_res, status_code: 200 } console.log(order_id, "response to user 17740 --", data) res.status(200).json(data) //res.send(data) } else if (resultUssd.result == "FAIL") { const dataError = { response: { reference: resultUssd.reference, resultcode: resultUssd.resultcode, result: resultUssd.result, order_id: orderResultData.transid, transid: orderResultData._id }, message: resultUssd.message, status_code: parseInt(resultUssd.resultcode) } console.log(order_id, "response to user failure 17756--", dataError) //res.send(dataError) res.status(200).json(dataError) } }).catch(error => { var body = JSON.stringify(error) console.log("error response data***********\n: ", error) console.log(error) const dataError = { response: { reference: "", resultcode: "", result: "", order_id: orderResultData.transid, transid: orderResultData._id }, message: "Something went wrong", status_code: 424 } console.log("response to user failure 17777", dataError) //res.send(dataError) res.status(200).json(dataError) }) } } else { try { // var suborderId = await logSuborder( orderResultData._id, req) var suborderId = await logTempSuborder( orderResultData._id, req) } catch (error) { return res.status(200).json({ status_code: 416, message: "Your Order is already placed!" }) } // add below on 18-11-2021 as separate transid for linked order logic var subOrderDetail = await OrderQueueModel.find({ linkedTransid: suborderId }).exec() suborderId = subOrderDetail[0].transid var success_res = req.lang.Order_Placed_Successfully_msg.replace("%number%", suborderId); const resData = { response: { result: result.result, order_id: suborderId, payment_token: result.data[0].payment_token, payment_status: "PENDING", qr: result.data[0].qr, till_number: '' }, message: success_res, status_code: 200 } console.log(order_id, ' resData ---- 17800 ----', resData) res.status(200).json(resData) } }) } else { const resData = { response: { result: result.result, order_id: order_id, payment_token: '', payment_status: '', qr: '', till_number: '' }, message: "invalid after create order api", status_code: 424 } console.log(order_id, ' resData ---- 17819 ----', resData) res.status(200).json(resData) } } else { const resData = { response: { result: result.result, order_id: order_id, payment_token: '', payment_status: '', qr: '', till_number: '' }, message: "result not true after create order api", status_code: 424 } res.status(200).json(resData) } }) } else { const toSend = { response: { result: result.result, order_id: order_id, payment_token: '', payment_status: '', qr: '', till_number: '' }, message: "something went wrong", status_code: 424 } res.status(200).json(toSend) } } catch (e) { console.log("food grocery_payment_new checkout/create-order") console.log("AfterError Inside outer") console.log(e) responses.sendErrorDuka(err.message, res) } }