File: /var/www/javago-nodeserver-hotfixes/src/services/order/order.services.js
import PredefinedItemImageDB from "../../models/pre_defined_item_images.model.js";
import AddonSizeCafeItemDB from "../../models/addon_size_cafe_items.model.js";
import CafeMenuItemSizeDB from "../../models/cafe_menu_item_sizes.model.js";
import UserFavouriteCafeDB from "../../models/user_favorite_cafes.model.js";
import LoyaltyStampDB from "../../models/manage_loyalty_stamps.model.js";
import GroupCoffeeRunDB from "../../models/group_coffee_run.model.js";
import NotificationDB from "../../models/notification_list.model.js";
import CafeMenuItemDB from "../../models/cafe_menu_items.model.js";
import CafeTimingDB from "../../models/cafe_timings.model.js";
import GroupMemberDB from "../../models/group_members.model.js";
import { messages } from "../../config/response.messages.js";
import AddonSizeDB from "../../models/addon_sizes.model.js";
import GroupDB from "../../models/groups.model.js";
import OrderDB from "../../models/orders.model.js";
import CafeDB from "../../models/cafes.model.js";
import UserDB from "../../models/users.model.js";
import InHouseOrderItems from "../../models/in_house_order_items.model.js";
import CafeGoToOrdersDB from "../../models/cafe_go_to_orders.model.js";
import * as config from "../../config/config.js";
import SizeDB from "../../models/sizes.model.js";
import * as Helper from "../../helper/index.js";
import Sequelize, { json } from "sequelize";
import { Op } from "sequelize";
import moment from "moment";
import coffeeRunInHouseOrders from "../../models/coffee_run_inhouse_order.model.js";
import schedule from "../../helper/schedule.js";
import notification from "../../helper/notification.js";
import CafeloyaltyStampExcludedItemsDB from "../../models/cafe_loyalty_stamp_excluded_items.model.js";
// create Group
export async function saveGroupCoffeeRun(data, loggedInUser) {
try {
let request_unique_id = (
await Helper.generateRandomString(15)
).toUpperCase();
let createRequestArr = [];
if (data.type === 0) {
data.users.forEach(async (element) => {
createRequestArr.push({
request_unique_id: request_unique_id,
type: data.type,
group_id: data.group_id,
user_id: element.id,
is_contributor_person: element.is_contributor_person,
request_created_by: loggedInUser.id,
request_endtime: data.request_endtime,
created_at: moment().unix(),
updated_at: moment().unix(),
});
});
} else {
data.users.forEach(async (element) => {
createRequestArr.push({
request_unique_id: request_unique_id,
cafe_id: data.cafe_id,
group_id: data.group_id,
user_id: element.id,
is_contributor_person: element.is_contributor_person,
request_created_by: loggedInUser.id,
request_endtime: data.request_endtime,
created_at: moment().unix(),
updated_at: moment().unix(),
});
});
}
var requestResults = await GroupCoffeeRunDB.bulkCreate(createRequestArr, {
returning: true,
});
var notificationData = requestResults
.filter((e) => e.dataValues.user_id != loggedInUser.id)
.map((e) => {
return {
sender_id: loggedInUser.id,
receiver_id: e.dataValues.user_id,
reference_id: e.dataValues.id,
notification_type: 2,
is_read: 0,
created_at: moment().unix(),
updated_at: moment().unix(),
};
});
await NotificationDB.bulkCreate(notificationData);
const coffeRun = await GroupCoffeeRunDB.findOne({
where: {
request_unique_id: request_unique_id,
user_id: loggedInUser.id,
},
include: [
{
model: CafeDB,
required: false,
attributes: ["id"],
include: [
{
model: CafeGoToOrdersDB,
required: false,
attributes: ["id"],
where: {
user_id: loggedInUser.id,
},
},
],
},
],
});
await notification.createCoffeeRunNotification({
loggedInUser: loggedInUser.name,
userIds: notificationData.map((e) => e.receiver_id),
cafe_id: data.cafe_id,
group_id: data.group_id,
request_endtime: data.request_endtime,
});
await schedule.createSchedule({
sender_id: loggedInUser.id,
time: coffeRun.dataValues.request_endtime,
receiver_id: notificationData[0].receiver_id,
reference_id: coffeRun.dataValues.id,
coffeeRunId: coffeRun.dataValues.request_unique_id,
});
return coffeRun;
} catch (error) {
throw new Error(error);
}
}
//get cafe list by group id and edit time
export async function getGroupCoffeeRun(data) {
try {
if ([null, undefined, 0, "", "0"].includes(data.cafe_id)) {
let check = await GroupCoffeeRunDB.findOne({
where: {
group_id: data.group_id,
request_endtime: {
[Op.gte]: moment().unix(),
},
},
});
if (check) {
data.cafe_id = check.cafe_id;
} else {
return [];
}
}
let result = await GroupCoffeeRunDB.findAll({
order: [["id", "DESC"]],
where: {
group_id: parseInt(data.group_id),
cafe_id: parseInt(data.cafe_id),
request_endtime: {
[Op.gte]: moment().unix(),
},
order_id: null,
request_endtime: {
[Op.gte]: moment().unix(),
},
},
order: [["id", "DESC"]],
include: [
{
model: UserDB,
as: "creator_data",
where: {
is_deleted: 0,
is_active: 1,
},
required: true,
attributes: ["id", "name", "profile_picture", "email"],
},
{
model: GroupDB,
where: {
is_active: 1,
},
include: [
{
model: GroupMemberDB,
as: "group_details",
attributes: ["id", "user_id"],
include: [
{
model: UserDB,
as: "user_data",
attributes: ["id", "name", "email", "profile_picture"],
where: { is_deleted: 0, is_active: 1, is_verified: 1 },
},
],
},
],
required: true,
attributes: [
"id",
"group_name",
"group_profile",
"created_at",
"group_code",
],
},
{
model: UserDB,
as: "user_data",
where: {
is_deleted: 0,
is_active: 1,
},
required: true,
attributes: ["id", "name", "profile_picture", "email"],
},
],
attributes: [
"id",
"request_unique_id",
"is_contributor_person",
"is_order_place",
"order_id",
"request_endtime",
"created_at",
"cafe_id",
],
});
return result;
} catch (error) {
console.log(error);
throw new Error(error);
}
}
// check same time group cafe run can create or not
export async function checkSameGroupCafeRunEndTime(data) {
try {
return await GroupCoffeeRunDB.findOne({
where: {
group_id: data.group_id,
user_id: data.loggedInUser.id,
request_endtime: {
[Op.gte]: moment().unix(),
},
},
include: [
{
model: CafeDB,
required: false,
attributes: ["id"],
include: [
{
model: CafeGoToOrdersDB,
required: false,
attributes: ["id"],
where: {
user_id: data.loggedInUser.id,
},
},
],
},
],
});
} catch (error) {
return null;
}
}
// place order
export async function placeOrder(data) {
try {
let todayDayId = new Date().getDay();
let currentTime = moment().format("HH:mm");
if (data.group_coffee_run_id) {
let checkRequestEndTime = await GroupCoffeeRunDB.findOne({
where: {
request_unique_id: data.group_coffee_run_id,
},
});
if (!checkRequestEndTime) {
return {
status: 203,
message: messages.group_coffee_run_wrong_passed,
result: {},
};
} else if (
checkRequestEndTime &&
checkRequestEndTime.request_endtime < moment().unix()
) {
return {
status: 203,
message: messages.group_coffee_run_end_time_up,
result: {},
};
}
}
let itemsArray = data.order_item_array.map(function (currentValue) {
return currentValue.item_id;
});
let result = await CafeDB.findOne({
where: {
id: data.cafe_id,
is_active: 1,
deleted_at: 0,
},
include: [
{
model: CafeTimingDB,
where: {
day: todayDayId,
open_time: {
[Op.lte]: currentTime,
},
close_time: {
[Op.gte]: currentTime,
},
},
required: false,
attributes: ["id"],
as: "time_sheet_data",
},
{
model: CafeMenuItemDB,
where: {
id: {
[Op.in]: itemsArray,
},
},
include: [
{
model: CafeMenuItemSizeDB,
required: false,
include: [
{
model: SizeDB,
required: false,
attributes: ["size_name"],
},
],
attributes: ["item_size_price"],
},
{
model: AddonSizeCafeItemDB,
required: false,
include: [
{
model: AddonSizeDB,
required: false,
attributes: ["addon_size_price"],
},
],
attributes: ["addon_size_id"],
},
],
required: false,
attributes: [
"id",
"item_price",
"status",
"item_deleted_at",
"item_name",
],
},
],
attributes: ["id"],
});
let final_result;
if (!result) {
final_result = {
status: 203,
message: messages.cafe_is_not_available,
};
} else if (result && result.time_sheet_data.length == 0) {
final_result = {
status: 203,
message: messages.cafe_has_been_closed,
};
} else if (result && result.cafe_menu_items.length == 0) {
final_result = {
status: 203,
message: messages.cafe_selected_items_not_avaialble,
};
} else if (result && result.cafe_menu_items.length) {
let message = "";
let items_prices = 0;
for (let index = 0; index < result.cafe_menu_items.length; index++) {
const element = result.cafe_menu_items[index];
if (element.status == 0 || element.item_deleted_at > 0) {
message += element.item_name;
if (
result.cafe_menu_items.length > 1 &&
index != parseInt(result.cafe_menu_items.length) - 1
) {
message += ", ";
}
}
if (
data.order_item_array.some(
(children) =>
children.item_size == "Regular" && children.item_id == element.id
)
) {
var qty = 1;
data.order_item_array.map((children) => {
if (children.item_id == element.id) {
qty = children.item_quantity;
}
});
items_prices = items_prices + Number(element.item_price) * qty;
// now check addons prices
for (let i = 0; i < data.order_item_array.length; i++) {
const element1 = data.order_item_array[i];
if (element1.item_id == element.id) {
for (let j = 0; j < element1.addon_sizes.length; j++) {
const element2 = element1.addon_sizes[j];
let check = 0;
element.addon_size_cafe_items.map((grandChildren) => {
if (
grandChildren.addon_size_id == element2.addon_size_id &&
element1.item_id == element.id
) {
check = grandChildren.addon_size.addon_size_price;
}
});
items_prices += check;
}
}
}
} else if (
data.order_item_array.some(
(children) =>
children.item_size != "Regular" && children.item_id == element.id
)
) {
for (let i = 0; i < data.order_item_array.length; i++) {
const element1 = data.order_item_array[i];
if (
element1.item_size != "Regular" &&
element.cafe_menu_item_sizes.some(
(children) =>
children.size.size_name == element1.item_size &&
element1.item_id == element.id
)
) {
var tmp = 0;
element.cafe_menu_item_sizes.map(function (childrenElement) {
if (childrenElement.size.size_name == element1.item_size) {
tmp = childrenElement.item_size_price;
}
});
items_prices += tmp ? tmp * element1.item_quantity : 0;
}
// now check addons prices
if (element1.item_id == element.id) {
for (let j = 0; j < element1.addon_sizes.length; j++) {
const element2 = element1.addon_sizes[j];
let check = 0;
element.addon_size_cafe_items.map((grandChildren) => {
if (
grandChildren.addon_size_id == element2.addon_size_id &&
element1.item_id == element.id
) {
check = grandChildren.addon_size.addon_size_price;
}
});
items_prices += check;
}
}
}
}
}
if (message) {
final_result = {
status: 203,
message: message + " items not available",
result: result,
};
} else if (
message == "" &&
Number(items_prices) != Number(data.items_amount)
) {
final_result = {
status: 203,
message: messages.item_price_updated_error,
result: result,
};
} else {
if (data.loyalty_stamp_id) {
let checkLoyaltyStamp = await LoyaltyStampDB.findOne({
where: {
id: parseInt(data.loyalty_stamp_id),
},
});
if (checkLoyaltyStamp) {
final_result = {
status: 200,
message: messages.data_found,
result: result,
};
} else {
final_result = {
status: 203,
message: messages.redeem_code_no_longer_available,
result: result,
};
}
} else {
final_result = {
status: 200,
message: messages.data_found,
result: result,
};
}
}
console.log(items_prices);
}
return final_result;
} catch (error) {
throw new Error(error);
}
}
// save order
export async function saveOrder(data) {
try {
for (let index = 0; index < data.order_item_array.length; index++) {
const element = data.order_item_array[index];
let itemImageData = await CafeMenuItemDB.findByPk(element.item_id, {
include: [
{
model: PredefinedItemImageDB,
as: "image_data",
required: true,
},
],
});
element.item_image = itemImageData
? itemImageData.image_data.item_image
: "";
}
let result = await OrderDB.create({
order_number: await Helper.generateRandomString(6, true),
user_id: data.loggedInUser,
cafe_id: data.cafe_id,
group_id: data.group_id ? data.group_id : null,
group_coffee_run_id: data.group_coffee_run_id
? data.group_coffee_run_id
: null,
loyalty_stamp_id: data.loyalty_stamp_id ? data.loyalty_stamp_id : null,
is_main_order: data.is_main_order,
order_item_array: JSON.stringify(data.order_item_array),
additional_note: data.additional_note,
total_amount: data.total_amount ? Number(data.total_amount) : 0,
tax: data.tax ? Number(data.tax) : 0,
service_charge: data.service_charge ? Number(data.service_charge) : 0,
other_charge: data.other_charge ? Number(data.other_charge) : 0,
transaction_id: data.transaction_id,
discount_amount: data.discount_amount ? Number(data.discount_amount) : 0,
order_placed_at: moment().unix(),
status: 1,
created_at: moment().unix(),
updated_at: moment().unix(),
});
if (data.group_coffee_run_id) {
await GroupCoffeeRunDB.update(
{ order_id: result.id, updated_at: moment().unix() },
{
where: {
request_unique_id: data.group_coffee_run_id,
user_id: data.loggedInUser,
},
returning: true,
plain: true,
}
);
let returnDoc = await GroupCoffeeRunDB.findOne({
where: {
request_unique_id: data.group_coffee_run_id,
},
});
await OrderDB.update(
{
request_unique_id: returnDoc.request_unique_id,
},
{
where: {
id: result.id,
},
}
);
}
if (typeof result.order_item_array == "string")
result.order_item_array = JSON.parse(result.order_item_array);
let send_notification_exists = await GroupCoffeeRunDB.findOne({
where: {
request_unique_id: result.dataValues.group_coffee_run_id,
user_id: result.dataValues.user_id,
request_created_by: {
[Op.ne]: result.dataValues.user_id,
},
is_contributor_person: 1,
},
attributes: ["id", "request_created_by", "order_id"],
});
console.log(send_notification_exists);
if (send_notification_exists) {
await NotificationDB.create({
sender_id: result.dataValues.user_id,
receiver_id: send_notification_exists.request_created_by,
reference_id: send_notification_exists.id,
notification_type: 5,
is_read: 0,
created_at: moment().unix(),
updated_at: moment().unix(),
});
notification.payOrderNotification({
loggedInUser: send_notification_exists.request_created_by,
orderId: result.dataValues.id,
groupId: data.group_id,
senderId: result.dataValues.user_id,
});
console.log("Notification sent.");
} else {
console.log("Notification not sent because record does not exist.");
}
return result;
} catch (error) {
throw new Error(error);
}
}
// get order list
export async function getOrder(userId, data) {
try {
if ([null, undefined, "", 0].includes(data.page)) data.page = 1;
data.page = parseInt(data.page);
let result = await OrderDB.paginate({
page: data.page,
paginate: parseInt(config.config.limit),
where: {
user_id: userId,
},
include: [
{
model: CafeDB,
where: {
is_active: 1,
deleted_at: 0,
},
include: [
{
model: UserFavouriteCafeDB,
as: "user_favorite_cafes",
required: false,
where: {
is_favorite: 1,
user_id: parseInt(userId),
},
attributes: ["is_favorite", "user_id"],
},
],
required: false,
attributes: [
"id",
"cafe_name",
"phone",
"latitude",
"bio",
"email",
"cafe_tax",
"longitude",
"address",
"banner_image",
"postcode",
],
},
{
model: GroupDB,
required: false,
attributes: ["id", "group_name", "group_profile"],
include: [
{
model: GroupMemberDB,
as: "group_details",
attributes: ["id", "user_id"],
include: [
{
model: UserDB,
as: "user_data",
attributes: ["id", "name", "email", "profile_picture"],
where: { is_deleted: 0, is_active: 1, is_verified: 1 },
},
],
},
],
},
],
attributes: [
"id",
"order_number",
"created_at",
"updated_at",
"order_item_array",
"additional_note",
"total_amount",
"tax",
"discount_amount",
"order_placed_at",
"order_collected_at",
"status",
],
order: [["id", "DESC"]],
});
result = JSON.stringify(result);
result = JSON.parse(result);
for (let index = 0; index < result.docs.length; index++) {
const element = result.docs[index];
element.group_coffee_run = await GroupCoffeeRunDB.findAll({
where: {
order_id: element.id,
},
include: [
{
model: UserDB,
attributes: ["id", "name", "profile_picture", "email"],
required: true,
where: {
is_deleted: 0,
is_active: 1,
},
as: "user_data",
},
{
model: UserDB,
attributes: ["id", "name", "profile_picture", "email"],
required: true,
where: {
is_deleted: 0,
is_active: 1,
},
as: "creator_data",
},
],
attributes: [
"id",
"request_unique_id",
"is_contributor_person",
"is_order_place",
"request_endtime",
],
});
element.cafe.is_favorite =
element.cafe.user_favorite_cafes.length > 0 ? 1 : 0;
element.cafe.distance = 0;
element.cafe.time_sheet_data = [];
delete element.cafe.user_favorite_cafes;
}
return result;
} catch (error) {
throw new Error(error);
}
}
export async function getOrderDetails(id) {
try {
let result = await OrderDB.findByPk(id, {
attributes: [
"id",
"order_number",
"group_id",
"cafe_id",
"total_amount",
"tax",
"service_charge",
"other_charge",
"order_item_array",
"discount_amount",
"order_placed_at",
"transaction_id",
],
include: [
{
model: UserDB,
attributes: ["name", "profile_picture", "email"],
},
],
});
return result;
} catch (error) {
throw new Error(error);
}
}
export async function updateOrderDetails(id, transaction_id) {
try {
let result = await OrderDB.update(
{
transaction_id: transaction_id,
},
{
where: { id: id },
}
);
return result;
} catch (error) {
throw new Error(error);
}
}
// get Individual order list
export async function getIndividualOrder(user_id, order_id, cafe_id) {
try {
let result = await OrderDB.findOne({
where: {
user_id: user_id,
id: order_id,
cafe_id: cafe_id,
},
include: [
{
model: CafeDB,
where: {
is_active: 1,
deleted_at: 0,
},
include: [
{
model: UserFavouriteCafeDB,
as: "user_favorite_cafes",
required: false,
where: {
is_favorite: 1,
user_id: parseInt(user_id),
},
attributes: ["is_favorite", "user_id"],
},
],
required: false,
attributes: [
"id",
"cafe_name",
"phone",
"latitude",
"longitude",
"address",
"banner_image",
"postcode",
],
},
{
model: GroupDB,
required: false,
attributes: ["id", "group_name", "group_profile"],
include: [
{
model: GroupMemberDB,
as: "group_details",
attributes: ["id", "user_id"],
include: [
{
model: UserDB,
as: "user_data",
attributes: ["id", "name", "email", "profile_picture"],
where: { is_deleted: 0, is_active: 1, is_verified: 1 },
},
],
},
],
},
],
attributes: [
"id",
"order_number",
"created_at",
"updated_at",
"order_item_array",
"additional_note",
"total_amount",
"tax",
"discount_amount",
"order_placed_at",
"order_collected_at",
"status",
],
});
return result;
} catch (error) {
throw new Error(error);
}
}
// change order status
export async function changeOrderStatus(orderId, data) {
try {
let check = await OrderDB.findByPk(orderId);
if (!check) {
return {
status: 501,
message: messages.wrong_order_id_applied,
};
}
if (check.status == parseInt(data.flag)) {
if (check.status == 1) {
return {
status: 409,
message:
messages.order_has_been_already_placed +
" at " +
check.order_placed_at,
data: {
cafe_id: check.cafe_id,
},
};
}
return {
status: 409,
message:
messages.order_has_been_already_collected +
" at " +
check.order_collected_at,
data: {
cafe_id: check.cafe_id,
},
};
}
let updateObj = {
status: parseInt(data.flag),
updated_at: moment().unix(),
};
if (parseInt(data.flag) == 1) {
updateObj.order_placed_at = moment().unix();
} else {
updateObj.order_collected_at = moment().unix();
}
let result = await OrderDB.update(updateObj, {
where: {
id: orderId,
},
});
return {
status: 202,
message:
parseInt(data.flag) == 1
? messages.order_has_been_placed
: messages.order_has_been_collected,
data: {
cafe_id: check.cafe_id,
},
};
} catch (error) {
throw new Error(error);
}
}
// Get Total Order cafe wise
export async function getAllCafeOrders(user_id, cafe_id) {
try {
return await OrderDB.count({
where: {
user_id: parseInt(user_id),
cafe_id: cafe_id,
status: 2,
loyalty_stamp_id: null,
// cafe_coupon_expired_time: 0
},
});
} catch (error) {
throw new Error(error);
}
}
// Get Total Order cafe wise
export async function getcouponOrder(user_id, cafe_id) {
try {
const orders = await OrderDB.findAll({
where: {
user_id: parseInt(user_id),
cafe_id: cafe_id,
status: 2,
loyalty_stamp_id: null,
},
});
const LoyltyStamp = await LoyaltyStampDB.findOne({
where: {
cafe_id: cafe_id,
},
});
// Get excluded items for this cafe's loyalty stamp
const excludedItems = await CafeloyaltyStampExcludedItemsDB.findAll({
where: {
stamp_id: LoyltyStamp.id,
},
});
const excludedItemsId = excludedItems.map((item) => item.item_id);
// Process orders and count
const processedOrderCount = await Promise.all(
orders.map(async (order) => {
// Parse the order item array
const orderItemArray = JSON.parse(order.order_item_array);
// Get details for each item in the order
const itemDetailsPromises = orderItemArray.map(async (orderItem) => {
const itemDetails = await CafeMenuItemDB.findOne({
where: {
id: orderItem.item_id,
cafe_id: cafe_id,
},
});
return itemDetails ? itemDetails.dataValues : null;
});
// Resolve all item details
const itemDetailsArray = await Promise.all(itemDetailsPromises);
// Check if all items are excluded
const allItemsExcluded = itemDetailsArray.every(
(itemDetails) =>
itemDetails && excludedItemsId.includes(itemDetails.id)
);
// Return true if at least one item is not excluded
return !allItemsExcluded;
})
);
// Count the number of orders with at least one non-excluded item
const orderCount = processedOrderCount.filter(Boolean).length;
return orderCount;
} catch (error) {
throw new Error(error);
}
}
// Get Total Order
export async function getUniversalOrders(user_id) {
try {
return await OrderDB.count({
where: {
user_id: parseInt(user_id),
status: 2,
universal_coupon_expired_time: 0,
},
});
} catch (error) {
throw new Error(error);
}
}
// Get last universal expires time
export async function getLastExpireDateUniversal(user_id) {
try {
return await OrderDB.findOne({
where: {
user_id: parseInt(user_id),
status: 2,
universal_coupon_expired_time: {
[Op.ne]: 0,
},
},
order: [["id", "DESC"]],
});
} catch (error) {
throw new Error(error);
}
}
// Get last universal expires time
export async function getLastExpireCafeDate(user_id, cafe_id) {
try {
return await OrderDB.findOne({
where: {
user_id: parseInt(user_id),
status: 2,
cafe_id: cafe_id,
cafe_coupon_expired_time: {
[Op.ne]: 0,
},
},
order: [["id", "DESC"]],
});
} catch (error) {
throw new Error(error);
}
}
//Get cafe universal stamp
export async function getUniversalStamp() {
try {
let nonUniversal = await LoyaltyStampDB.findOne({
where: {
cafe_id: null,
is_universal: 1,
},
});
return nonUniversal;
} catch (error) {
throw new Error(error);
}
}
//Get cafe stemp by cafe ID
export async function getStampsByCafe(cafe_id) {
try {
let nonUniversal = await LoyaltyStampDB.findOne({
where: {
cafe_id: parseInt(cafe_id),
is_universal: 0,
},
});
return nonUniversal;
} catch (error) {
throw new Error(error);
}
}
//update coupons by cafe
export async function updateCouponByCafeId(
user_id,
coupon_id,
cafe_id,
stamp_no,
stamp_expires_in
) {
try {
let orderIds = [];
let expireDay = moment().unix();
let orderDetails = await OrderDB.findAll({
where: {
user_id: parseInt(user_id),
status: 2,
cafe_coupon_expired_time: 0,
cafe_id: cafe_id,
},
attributes: ["id"],
order: [["id", "ASC"]],
limit: stamp_no,
});
for (let i = 0; i < orderDetails.length; i++) {
orderIds.push(orderDetails[i].id);
}
return await OrderDB.update(
{
cafe_coupon_order_id: coupon_id,
cafe_coupon_expired_time: moment(expireDay, "X")
.add(stamp_expires_in, "days")
.unix(),
},
{
where: {
cafe_id: parseInt(cafe_id),
user_id: user_id,
id: {
[Op.in]: orderIds,
},
},
}
);
} catch (error) {
console.log("error: ", error);
throw new Error(error);
}
}
//update universal coupons
export async function updateUniversalCoupon(
user_id,
coupon_id,
stamp_no,
stamp_expires_in
) {
try {
let orderIds = [];
let expireDay = moment().unix();
let orderDetails = await OrderDB.findAll({
where: {
user_id: parseInt(user_id),
status: 2,
universal_coupon_expired_time: 0,
},
attributes: ["id"],
order: [["id", "ASC"]],
limit: stamp_no,
});
for (let i = 0; i < orderDetails.length; i++) {
orderIds.push(orderDetails[i].id);
}
return await OrderDB.update(
{
universal_coupon_order_id: coupon_id,
universal_coupon_expired_time: moment(expireDay, "X")
.add(stamp_expires_in, "days")
.unix(),
},
{
where: {
user_id: user_id,
id: {
[Op.in]: orderIds,
},
},
}
);
} catch (error) {
throw new Error(error);
}
}
// Get Loyalty list
export async function loyaltyList(data, query) {
try {
// Ensure page is a number and defaults to 1 if not provided
const page = query.page ? parseInt(query.page, 10) : 1;
const limit = 10;
const offset = (page - 1) * limit;
// Group orders by cafe
let loyaltyDetails = await OrderDB.findAndCountAll({
limit: limit,
offset: offset,
order: [["id", "ASC"]],
attributes: ["id", "order_item_array", "user_id", "cafe_id"],
include: [
{
model: CafeDB,
attributes: ["id", "cafe_name"],
include: [
{
model: LoyaltyStampDB,
attributes: [
"id",
"stamp_no",
"cafe_id",
"offer_text",
"stamp_color",
],
},
],
},
],
where: {
user_id: data,
status: 2,
cafe_coupon_expired_time: 0,
cafe_coupon_order_id: null,
},
});
// Group orders by cafe
const cafeGroupedOrders = loyaltyDetails.rows.reduce((acc, order) => {
const cafeId = order.cafe_id;
console.log(cafeId);
if (!acc[cafeId]) {
acc[cafeId] = {
user_id: order.user_id,
cafe_id: cafeId,
cafe: {
...order.cafe.dataValues,
order_items: [],
},
Count: 0,
};
}
// Add order items
acc[cafeId].cafe.order_items.push({
id: order.id,
order_item_array: order.order_item_array,
});
return acc;
}, {});
// Process orders for counting
const processedCafeOrders = await Promise.all(
Object.values(cafeGroupedOrders).map(async (cafeOrder) => {
let orderC = 0;
// Process order items to determine if order should be counted
const processedOrderItems = await Promise.all(
cafeOrder.cafe.order_items.map(async (orderItem) => {
const itemArray = JSON.parse(orderItem.order_item_array);
const itemDetailsPromises = itemArray.map(async (item) => {
const itemDetails = await CafeMenuItemDB.findOne({
where: {
id: item.item_id,
cafe_id: cafeOrder.cafe_id,
},
});
return itemDetails ? itemDetails.dataValues : null;
});
const itemDetailsArray = await Promise.all(itemDetailsPromises);
const excludedItems = await CafeloyaltyStampExcludedItemsDB.findAll(
{
where: {
stamp_id: cafeOrder.cafe.manage_loyalty_stamps[0].id,
},
}
);
const excludedItemsId = excludedItems.map((item) => item.item_id);
console.log(excludedItemsId);
console.log(itemDetailsArray);
// Check if all items are excluded
const allItemsExcluded = itemDetailsArray.every(
(itemDetails) =>
itemDetails && excludedItemsId.includes(itemDetails.id)
);
if (!allItemsExcluded) {
orderC++;
}
return !allItemsExcluded;
})
);
// Determine if any order items should be counted
//cafeOrder.Count = processedOrderItems.some(Boolean) ? 1 : 0;
cafeOrder.Count = orderC;
return cafeOrder;
})
);
// Calculate total processed count
const totalProcessedCount = processedCafeOrders.reduce(
(total, order) => total + order.Count,
0
);
// Calculate total pages
const totalPages = Math.ceil(loyaltyDetails.count / limit);
return {
docs: processedCafeOrders,
pages: totalPages,
total: loyaltyDetails.count,
totalProcessedCount: totalProcessedCount,
currentPage: page,
};
} catch (error) {
console.error("Error in loyaltyList:", error);
throw new Error(`Failed to retrieve loyalty details: ${error.message}`);
}
}
export async function loyaltyListold(data, query) {
try {
let loyaltyDetails = await OrderDB.paginate({
paginate: 10,
page: query.page,
order: [["id", "ASC"]],
attributes: [
"user_id",
"cafe_id",
[Sequelize.fn("COUNT", Sequelize.col("orders.id")), "Count"],
],
include: [
{
model: CafeDB,
attributes: ["id", "cafe_name"],
include: [
{
model: LoyaltyStampDB,
attributes: ["stamp_no", "cafe_id", "offer_text", "stamp_color"],
},
],
},
],
distinct: false,
col: "status",
group: ["cafe_id"],
where: {
user_id: data,
status: 2,
cafe_coupon_expired_time: 0,
cafe_coupon_order_id: null,
},
});
return loyaltyDetails;
} catch (error) {
throw new Error(error);
}
}
// Get universal Loyalty list
export async function universalCardList(user_id) {
try {
return await OrderDB.count({
where: {
user_id: parseInt(user_id),
// universal_coupon_order_id: null,
universal_coupon_expired_time: 0,
status: 2,
},
});
} catch (error) {
throw new Error(error);
}
}
// get redeem code
export async function getRedeemCode(data) {
try {
let final_result = {
universal: {},
nonUniversal: {},
};
let checkTotalOrder = await OrderDB.count({
where: {
user_id: data.userId,
status: 2,
},
});
let nonUniversal = await LoyaltyStampDB.findOne({
where: {
cafe_id: parseInt(data.cafe_id),
is_universal: 0,
},
});
let universal = await LoyaltyStampDB.findOne({
where: {
cafe_id: null,
is_universal: 1,
},
});
let checkTotalRedeem = await OrderDB.count({
where: {
user_id: parseInt(data.userId),
loyalty_stamp_id: universal.id,
status: 2,
},
});
let checkTotalCafeRedeem = await OrderDB.count({
where: {
user_id: parseInt(data.userId),
loyalty_stamp_id: parseInt(data.cafe_id),
status: 2,
},
});
if (universal.stamp_no <= checkTotalOrder) {
let deno =
checkTotalRedeem > 0
? checkTotalOrder - checkTotalRedeem * universal.stamp_no
: checkTotalOrder;
final_result.universal = deno >= universal.stamp_no ? universal : {};
}
if (nonUniversal.stamp_no <= checkTotalOrder) {
let deno =
checkTotalCafeRedeem > 0
? checkTotalOrder - checkTotalCafeRedeem * nonUniversal.stamp_no
: checkTotalOrder;
final_result.nonUniversal =
deno >= nonUniversal.stamp_no ? nonUniversal : {};
}
return final_result;
} catch (error) {
throw new Error(error);
}
}
// apply redeem code
export async function applyRedeemCode(order_id) {
try {
let final_result = await OrderDB.update(
{
cafe_coupon_order_id: order_id,
},
{
where: {
id: order_id,
},
}
);
return final_result;
} catch (error) {
throw new Error(error);
}
}
export async function orderListByGroup(data) {
try {
if ([null, undefined, "", 0].includes(data.page)) data.page = 1;
data.page = parseInt(data.page);
let result = await OrderDB.paginate({
page: data.page,
paginate: parseInt(config.config.limit),
where: {
group_id: parseInt(data.group_id),
},
include: [
{
model: CafeDB,
where: {
is_active: 1,
deleted_at: 0,
},
include: [
{
model: UserFavouriteCafeDB,
as: "user_favorite_cafes",
required: false,
where: {
is_favorite: 1,
user_id: parseInt(data.userId),
},
attributes: ["is_favorite", "user_id"],
},
],
required: false,
attributes: [
"id",
"cafe_name",
"phone",
"latitude",
"bio",
"email",
"cafe_tax",
"longitude",
"address",
"banner_image",
"postcode",
],
},
{
model: GroupDB,
required: false,
attributes: ["id", "group_name", "group_profile"],
include: [
{
model: GroupMemberDB,
as: "group_details",
attributes: ["id", "user_id"],
include: [
{
model: UserDB,
as: "user_data",
attributes: ["id", "name", "email", "profile_picture"],
where: { is_deleted: 0, is_active: 1, is_verified: 1 },
},
],
},
],
},
],
attributes: [
"id",
"order_number",
"created_at",
"updated_at",
"order_item_array",
"additional_note",
"total_amount",
"tax",
"discount_amount",
"order_placed_at",
"order_collected_at",
"status",
],
order: [["id", "DESC"]],
});
result = JSON.stringify(result);
result = JSON.parse(result);
for (let index = 0; index < result.docs.length; index++) {
const element = result.docs[index];
element.group_coffee_run = await GroupCoffeeRunDB.findAll({
where: {
order_id: element.id,
},
include: [
{
model: UserDB,
attributes: ["id", "name", "profile_picture", "email"],
required: true,
where: {
is_deleted: 0,
is_active: 1,
},
as: "user_data",
},
{
model: UserDB,
attributes: ["id", "name", "profile_picture", "email"],
required: true,
where: {
is_deleted: 0,
is_active: 1,
},
as: "creator_data",
},
],
attributes: [
"id",
"request_unique_id",
"is_contributor_person",
"is_order_place",
"request_endtime",
],
});
element.cafe.is_favorite =
element.cafe.user_favorite_cafes.length > 0 ? 1 : 0;
element.cafe.distance = 0;
element.cafe.time_sheet_data = [];
if (typeof element.order_item_array == "string")
element.order_item_array = JSON.parse(element.order_item_array);
delete element.cafe.user_favorite_cafes;
}
return result;
} catch (error) {
throw new Error(error);
}
}
//get cafe list by group id and edit time
export async function getGroupCoffeeRunOrders(coffeeRunId, groupId, user_id) {
try {
let groupCoffeeRun;
groupCoffeeRun = await GroupCoffeeRunDB.findOne({
where: {
group_id: groupId,
},
order: [["id", "DESC"]],
attributes: [
"request_unique_id",
"cafe_id",
"group_id",
"request_endtime",
"type",
"request_created_by",
],
});
if (groupCoffeeRun == null) {
return null;
}
var inHouseOrders = [];
var orderDetails = [];
if (groupCoffeeRun.dataValues.type == 0) {
inHouseOrders = await coffeeRunInHouseOrders.findAll({
where: {
coffee_run_id: groupCoffeeRun.dataValues.request_unique_id,
},
include: [
{
model: UserDB,
attributes: ["id", "name"],
},
],
});
} else {
orderDetails = await OrderDB.findAll({
where: {
group_coffee_run_id: groupCoffeeRun.dataValues.request_unique_id,
},
attributes: [
"order_number",
"order_item_array",
"total_amount",
"tax",
"discount_amount",
"service_charge",
"other_charge",
"created_at",
"order_collected_at",
"transaction_id",
],
include: [
{
model: UserDB,
attributes: ["id", "name"],
},
],
});
}
const orderCollected = orderDetails.find(
(e) => e.dataValues.order_collected_at != 0
);
const inHouseOrderCollected = inHouseOrders.find(
(e) => e.dataValues.order_collected_at != 0
);
if (orderCollected || inHouseOrderCollected) {
return null;
}
var cafeDetails = null;
if (groupCoffeeRun.dataValues.type == 1) {
cafeDetails = await CafeDB.findOne({
where: {
id: groupCoffeeRun.dataValues.cafe_id,
},
include: [
{
model: UserFavouriteCafeDB,
as: "user_favorite_cafes",
required: false,
where: {
is_favorite: 1,
user_id: parseInt(user_id),
},
attributes: ["is_favorite"],
},
],
attributes: [
"id",
"cafe_name",
"banner_image",
"address",
"latitude",
"longitude",
],
});
}
const groupDetails = await GroupDB.findOne({
where: {
id: groupCoffeeRun.dataValues.group_id,
},
attributes: ["group_name", "group_profile"],
include: [
{
model: GroupMemberDB,
as: "group_details",
attributes: ["user_id"],
include: [
{
model: UserDB,
as: "user_data",
attributes: ["name", "profile_picture", "email"],
},
],
},
],
});
return {
cafe_details: cafeDetails,
group_details: groupDetails,
coffe_run: groupCoffeeRun,
order_details: orderDetails,
in_house_orders: inHouseOrders,
};
} catch (error) {
throw new Error(error);
}
}
//mark order collected
export async function markOrderCollected(coffeeRunId, type) {
try {
let updatedOrders;
if (type == 1) {
updatedOrders = await OrderDB.update(
{
order_collected_at: moment().unix(),
status: 2,
},
{
where: {
group_coffee_run_id: coffeeRunId,
status: 1,
},
}
);
} else {
updatedOrders = await coffeeRunInHouseOrders.update(
{
order_collected_at: moment().unix(),
},
{
where: {
coffee_run_id: coffeeRunId,
},
}
);
}
if (updatedOrders[0] === 0) {
return null;
}
//Update endtime if it is greater than current time
const currentTimeUnix = moment().unix();
await GroupCoffeeRunDB.update(
{ request_endtime: currentTimeUnix },
{
where: {
request_unique_id: coffeeRunId,
request_endtime: { [Op.gt]: currentTimeUnix },
},
}
);
return updatedOrders[0];
} catch (error) {
throw new Error(error);
}
}
export async function getPastCoffeeRunOrders(user_id) {
try {
const cafeOrders = await GroupCoffeeRunDB.findAll({
where: {
user_id: user_id,
[Op.or]: [
{
in_house_order_id: {
[Op.ne]: null,
},
},
{
order_id: {
[Op.ne]: null,
},
},
],
},
attributes: ["id", "user_id", "order_id", "in_house_order_id"],
order: [["id", "DESC"]],
include: [
{
model: GroupDB,
attributes: ["group_name"],
},
{
model: CafeDB,
attributes: ["cafe_name"],
},
{
model: OrderDB,
required: false,
attributes: [
"id",
"order_item_array",
"total_amount",
"tax",
"discount_amount",
"created_at",
"order_collected_at",
],
},
{
model: coffeeRunInHouseOrders,
required: false,
attributes: [
"id",
"in_house_order_items",
"customized_order",
"created_at",
"order_collected_at",
],
},
],
});
return cafeOrders;
} catch (error) {
throw new Error(error);
}
}
//Non Universal Card List
export async function nonuniversalCardList(user_id, cafe_id) {
try {
// Initialize the processed orders counter
let processedOrdersCount = 0;
// Fetch the loyalty stamp details
const stamp = await LoyaltyStampDB.findOne({
where: {
cafe_id: parseInt(cafe_id),
},
});
// Fetch the excluded items for this stamp
const excludedItems = await CafeloyaltyStampExcludedItemsDB.findAll({
where: {
stamp_id: stamp.id,
},
});
// Extract all item_ids from the results (make sure it's an array)
const excludedItemsId = excludedItems.map((item) => item.item_id); // Use item_id instead of cafe_menu_id
// Fetch all orders based on the given criteria
const orders = await OrderDB.findAll({
where: {
user_id: parseInt(user_id),
cafe_id: parseInt(cafe_id),
universal_coupon_expired_time: 0,
// status: 2,
},
});
// Loop through each order to get item details
for (const order of orders) {
// Parse the order's item array
const orderItemArray = JSON.parse(order.order_item_array);
const itemDetailsPromises = orderItemArray.map(async (orderItem) => {
const itemDetails = await CafeMenuItemDB.findOne({
where: {
id: orderItem.item_id, // Directly use item_id
cafe_id: parseInt(cafe_id), // Optional: include cafe_id for more precise matching
},
});
return itemDetails.dataValues; // Extract item details
});
// Wait for all item detail queries to complete
const itemDetailsArray = await Promise.all(itemDetailsPromises);
// Now check if all items in the order belong to the excludedItemsId
const allItemsExcluded = itemDetailsArray.every(
(itemDetails) => excludedItemsId.includes(itemDetails.id) // Use item_id from item details
);
if (allItemsExcluded) {
continue; // Skip this order
}
// If order is not skipped, increment the processed orders counter
processedOrdersCount++;
}
// Return the count of processed orders
console.log(processedOrdersCount);
return processedOrdersCount;
} catch (error) {
console.log(error);
throw new Error(error);
}
}
export async function nonuniversalCardListold(user_id, cafe_id) {
try {
return await OrderDB.count({
where: {
user_id: parseInt(user_id),
cafe_id: parseInt(cafe_id),
// universal_coupon_order_id: null,
universal_coupon_expired_time: 0,
status: 2,
},
});
} catch (error) {
throw new Error(error);
}
}
//Get cafe universal stamp
export async function getnonUniversalStamp(cafe_id) {
try {
let nonUniversal = await LoyaltyStampDB.findOne({
where: {
cafe_id: cafe_id,
is_universal: 0,
},
});
return nonUniversal;
} catch (error) {
throw new Error(error);
}
}
//Categories coupon can be applied
export async function getcategoriesForCoupon(cafe_id) {
try {
let cafeStamp = await LoyaltyStampDB.findOne({
where: {
cafe_id: cafe_id,
},
});
let categories;
categories = cafeStamp.stamp_applicable_to_categories;
return categories;
} catch (error) {
throw new Error(error);
}
}