HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux ip-10-0-8-47 6.8.0-1021-aws #23~22.04.1-Ubuntu SMP Tue Dec 10 16:31:58 UTC 2024 aarch64
User: ubuntu (1000)
PHP: 8.1.2-1ubuntu2.22
Disabled: NONE
Upload Files
File: /var/www/javago-api-updates/src/services/cafe/cafe.services.js
import AddonSizeCafeItemDB from "../../models/addon_size_cafe_items.model.js";
import PreDefinedImageDB from "../../models/pre_defined_item_images.model.js";
import CafeMenuItemSizeDB from "../../models/cafe_menu_item_sizes.model.js";
import userFavoriteCafes from "../../models/user_favorite_cafes.model.js";
import SuggestedItemDB from "../../models/suggested_items.model.js";
import CafeMenuItemDB from "../../models/cafe_menu_items.model.js";
import CafeTimingDB from "../../models/cafe_timings.model.js";
import cafeFilters from "../../models/cafe_filters.model.js";
import AddonSizeDB from "../../models/addon_sizes.model.js";
import CafeMenuDB from "../../models/cafe_menu.model.js";
import sequelize from "../../config/database.config.js";
import AddonDB from "../../models/addons.model.js";
import SizeDB from "../../models/sizes.model.js";
import LoyaltyStampDB from "../../models/manage_loyalty_stamps.model.js";
import OrderDB from "../../models/orders.model.js";
import CafeDB from "../../models/cafes.model.js";
import MenuCategoryOrder from "../../models/MenuCategoryOrder.model.js";
import { json, Op } from "sequelize";
import { config } from "../../config/config.js";
import moment from "moment";
import CafeGoToOrders from "../../models/cafe_go_to_orders.model.js";
import CafeManagement from "../../models/CafeManagement.model.js";
import CafeClickCollectTiming from "../../models/CafeClickCollectTiming.model.js";
let USER_SEARCH_LIMIT = config.limit;
let distance = config.distance;

// get all cafe listing
export async function getAllCafeList(data) {
  try {
    let todayDayId = new Date().getDay();
    let currentTime = moment().format("HH:mm");
    if ([null, undefined, "", 0].includes(data.page)) data.page = 1;
    data.page = parseInt(data.page);
    const haversine = `(
      3959 * acos(
          cos(radians(${data.latitude}))
          * cos(radians(latitude))
          * cos(radians(longitude) - radians(${data.longitude}))
          + sin(radians(${data.latitude})) * sin(radians(latitude))
      )
    )`;
    let whereObject = {
      deleted_at: 0,
      is_active: 1,
      signup_completed: 1,
      profile_completed: 1,
      menu_completed: 1,
      loyalty_completed: 1,
      is_admin_approved: 1,
      // is_active: 1,
      // '$employee.manager.id$': id
    };
    //2 vegan
    if (data.filter_flag == 2) {
      whereObject.cafe_filter = {
        [Op.like]: ["%3%"],
      };
    }
    // 3 bubble tea
    else if (data.filter_flag == 3) {
      whereObject.cafe_filter = {
        [Op.like]: ["%4%"],
      };
    }
    // 4 desserts
    else if (data.filter_flag == 4) {
      whereObject.cafe_filter = {
        [Op.like]: ["%5%"],
      };
    }
    // 5 sandwiches
    else if (data.filter_flag == 5) {
      whereObject.cafe_filter = {
        [Op.like]: ["%6%"],
      };
    } else {
    }
    let cafeDetails = await CafeDB.paginate({
      page: data.page,
      paginate: parseInt(USER_SEARCH_LIMIT),
      where: whereObject,
      include: [
        {
          model: userFavoriteCafes,
          as: "user_favorite_cafes",
          where: {
            user_id: data.user_id,
            is_favorite: 1,
          },
          attributes: ["is_favorite", "user_id"],
          required: false,
        },
        {
          model: CafeTimingDB,
          as: "time_sheet_data",
          required: false,
          where: {
            day: todayDayId,
            is_active: 1,
            open_time: {
              [Op.lte]: currentTime,
            },
            close_time: {
              [Op.gte]: currentTime,
            },
          },
        },
      ],
      attributes: [
        "id",
        "cafe_name",
        "cafe_type",
        "bio",
        "cafe_tax",
        "phone",
        "banner_image",
        "address",
        "latitude",
        "longitude",
        [sequelize.literal(`round(${haversine})`), "distance"],
      ],
      order: [
        ["distance", "asc"],
        ["id", "desc"],
      ],
      subQuery: false,
      // having: sequelize.literal(`distance <= ${distance}`),
    });
    cafeDetails = JSON.stringify(cafeDetails);
    cafeDetails = JSON.parse(cafeDetails);
    for (let i = 0; i < cafeDetails.docs.length; i++) {
      cafeDetails.docs[i].is_favorite =
        cafeDetails.docs[i].user_favorite_cafes.length > 0 ? 1 : 0;
      cafeDetails.docs[i].is_open = cafeDetails.docs[i].time_sheet_data.length
        ? 1
        : 0;
      cafeDetails.docs[i].distance = cafeDetails.docs[i].distance
        ? cafeDetails.docs[i].distance
        : 0;
      let checkTotalOrder = await OrderDB.count({
        where: {
          user_id: data.user_id,
          cafe_id: parseInt(cafeDetails.docs[i].id),
          status: 2,
          cafe_coupon_expired_time: 0,
        },
      });
      let nonUniversal = await LoyaltyStampDB.findOne({
        where: {
          cafe_id: parseInt(cafeDetails.docs[i].id),
          is_universal: 0,
        },
        attributes: ["stamp_no"],
      });
      const stampNo = nonUniversal.stamp_no;
      const completed = checkTotalOrder % stampNo;
      let remaining = completed === 0 ? stampNo : stampNo - completed;
      if (!remaining || isNaN(remaining)) {
        remaining = 0;
      }
      cafeDetails.docs[i].reward = nonUniversal ? remaining : 0;
    }
    cafeDetails.docs.sort((p1, p2) =>
      p1.is_open < p2.is_open ? 1 : p1.is_open > p2.is_open ? -1 : 0
    );
    return cafeDetails;
  } catch (error) {
    throw new Error(error);
  }
}

export async function getSearchedCafe(data) {
  try {
    const query = data.query;
    const haversine = `(
      3959 * acos(
          cos(radians(${data.latitude}))
          * cos(radians(latitude))
          * cos(radians(longitude) - radians(${data.longitude}))
          + sin(radians(${data.latitude})) * sin(radians(latitude))
      )
    )`;
    let result = CafeDB.findAll({
      where: {
        cafe_name: {
          [Op.like]: `%${query}%`,
        },
        is_admin_approved: 1,
      },
      attributes: [
        "id",
        "cafe_name",
        "cafe_type",
        "bio",
        "cafe_tax",
        "phone",
        "banner_image",
        "address",
        "latitude",
        "longitude",
        [sequelize.literal(`round(${haversine})`), "distance"],
      ],
    });
    return result;
  } catch (error) {
    throw new Error(error);
  }
}

// feature cafe list
export async function getFeatureCafeList(data) {
  try {
    let todayDayId = new Date().getDay();
    let currentTime = moment().format("HH:mm");
    if ([null, undefined, "", 0].includes(data.page)) data.page = 1;
    data.page = parseInt(data.page);
    const haversine = `(
      3959 * acos(
          cos(radians(${data.latitude}))
          * cos(radians(latitude))
          * cos(radians(longitude) - radians(${data.longitude}))
          + sin(radians(${data.latitude})) * sin(radians(latitude))
      )
    )`;
    let whereObject = {
      deleted_at: 0,
      is_active: 1,
      signup_completed: 1,
      profile_completed: 1,
      menu_completed: 1,
      loyalty_completed: 1,
      is_admin_approved: 1,
    };
    let cafeDetails = await CafeDB.paginate({
      page: data.page,
      paginate: parseInt(USER_SEARCH_LIMIT),
      where: whereObject,
      include: [
        {
          model: userFavoriteCafes,
          as: "user_favorite_cafes",
          where: {
            user_id: data.user_id,
            is_favorite: 1,
          },
          attributes: ["is_favorite", "user_id"],
          required: false,
        },
        {
          model: CafeTimingDB,
          as: "time_sheet_data",
          required: false,
          where: {
            day: todayDayId,
            open_time: {
              [Op.lte]: currentTime,
            },
            close_time: {
              [Op.gte]: currentTime,
            },
          },
        },
      ],
      attributes: {
        include: [
          [
            sequelize.literal(`(
            SELECT COUNT(*)
            FROM orders where orders.cafe_id = cafes.id
        )`),
            "totalOrder",
          ],
          "id",
          "cafe_name",
          "cafe_type",
          "bio",
          "cafe_tax",
          "phone",
          "banner_image",
          "address",
          "latitude",
          "longitude",
          [sequelize.literal(`round(${haversine})`), "distance"],
        ],
        exclude: [
          "cafe_filter",
          "website",
          "otp",
          "cafe_type",
          "is_active",
          "approved",
          "signup_completed",
          "profile_completed",
          "menu_completed",
          "loyalty_completed",
          "is_listed",
          "is_open",
          "deleted_at",
          "created_at",
          "updated_at",
          "remember_token",
          "postcode",
          "password",
        ],
      },

      order: [["totalOrder", "ASC"]],
      subQuery: false,
      // having: sequelize.literal(`distance <= ${distance}`),
    });
    cafeDetails = JSON.stringify(cafeDetails);
    cafeDetails = JSON.parse(cafeDetails);
    for (let i = 0; i < cafeDetails.docs.length; i++) {
      cafeDetails.docs[i].is_favorite =
        cafeDetails.docs[i].user_favorite_cafes.length > 0 ? 1 : 0;
      cafeDetails.docs[i].is_open = cafeDetails.docs[i].time_sheet_data.length
        ? 1
        : 0;
      cafeDetails.docs[i].distance = cafeDetails.docs[i].distance
        ? cafeDetails.docs[i].distance
        : 0;
      let checkTotalOrder = await OrderDB.count({
        where: {
          user_id: data.user_id,
          cafe_id: parseInt(cafeDetails.docs[i].id),
          status: 2,
          loyalty_stamp_id: null,
        },
      });
      let nonUniversal = await LoyaltyStampDB.findOne({
        where: {
          cafe_id: parseInt(cafeDetails.docs[i].id),
          is_universal: 0,
        },
        attributes: ["stamp_no"],
      });
      // cafeDetails.docs[i].reward = nonUniversal.stamp_no - checkTotalOrder;
      const stampNo = nonUniversal.stamp_no;
      const completed = checkTotalOrder % stampNo;
      let remaining = completed === 0 ? stampNo : stampNo - completed;
	if (!remaining || isNaN(remaining)) {
        remaining = 0;
      }

      cafeDetails.docs[i].reward = nonUniversal ? remaining : 0;
    }
    cafeDetails.docs.sort((p1, p2) =>
      p1.is_open < p2.is_open ? 1 : p1.is_open > p2.is_open ? -1 : 0
    );
    return cafeDetails;
  } catch (error) {
    throw new Error(error);
  }
}

// get favorites cafe listing

export async function getFavoritesCafeList(data) {
  try {
    let todayDayId = new Date().getDay();
    let currentTime = moment().format("HH:mm");
    if ([null, undefined, "", 0].includes(data.page)) data.page = 1;
    data.page = parseInt(data.page);
    const haversine = `(
      3959 * acos(
          cos(radians(${data.latitude}))
          * cos(radians(latitude))
          * cos(radians(longitude) - radians(${data.longitude}))
          + sin(radians(${data.latitude})) * sin(radians(latitude))
      )
    )`;
    let cafeDetails = await CafeDB.paginate({
      where: {
        deleted_at: 0,
        is_active: 1,
        signup_completed: 1,
        profile_completed: 1,
        menu_completed: 1,
        loyalty_completed: 1,
      },
      include: [
        {
          model: userFavoriteCafes,
          as: "user_favorite_cafes",
          required: true,
          where: {
            is_favorite: 1,
            user_id: parseInt(data.user_id),
          },
          attributes: ["is_favorite", "user_id"],
        },
        {
          model: CafeTimingDB,
          as: "time_sheet_data",
          required: false,
          where: {
            day: todayDayId,
            open_time: {
              [Op.lte]: currentTime,
            },
            close_time: {
              [Op.gte]: currentTime,
            },
          },
        },
      ],
      attributes: [
        "id",
        "cafe_name",
        "cafe_type",
        "bio",
        "cafe_tax",
        "phone",
        "banner_image",
        "address",
        "latitude",
        "longitude",
        [sequelize.literal(`round(${haversine})`), "distance"],
      ],
      order: [["distance", "asc"]],
      page: data.page,
      paginate: parseInt(USER_SEARCH_LIMIT),
      subQuery: false,
    });
    cafeDetails = JSON.stringify(cafeDetails);
    cafeDetails = JSON.parse(cafeDetails);
    for (let i = 0; i < cafeDetails.docs.length; i++) {
      cafeDetails.docs[i].is_favorite =
        cafeDetails.docs[i].user_favorite_cafes.length > 0 ? 1 : 0;
      cafeDetails.docs[i].is_open = cafeDetails.docs[i].time_sheet_data.length
        ? 1
        : 0;
      cafeDetails.docs[i].distance = cafeDetails.docs[i].distance
        ? cafeDetails.docs[i].distance
        : 0;
      let checkTotalOrder = await OrderDB.count({
        where: {
          user_id: data.user_id,
          cafe_id: parseInt(cafeDetails.docs[i].id),
          status: 2,
          cafe_coupon_expired_time: 0,
        },
      });
      let nonUniversal = await LoyaltyStampDB.findOne({
        where: {
          cafe_id: parseInt(cafeDetails.docs[i].id),
          is_universal: 0,
        },
        attributes: ["stamp_no"],
      });
      // cafeDetails.docs[i].reward = nonUniversal ? nonUniversal.stamp_no - checkTotalOrder : 0;
      const stampNo = nonUniversal.stamp_no;
      const completed = checkTotalOrder % stampNo;
      let remaining = completed === 0 ? stampNo : stampNo - completed;
	if (!remaining || isNaN(remaining)) {
        remaining = 0;
      }

      cafeDetails.docs[i].reward = nonUniversal ? remaining : 0;
    }
    cafeDetails.docs.sort((p1, p2) =>
      p1.is_open < p2.is_open ? 1 : p1.is_open > p2.is_open ? -1 : 0
    );
    return cafeDetails;
  } catch (error) {
    throw new Error(error);
  }
}

//get cafe by search cafe name

// get favorites cafe listing

export async function getCafeByName(data) {
  try {
    let todayDayId = new Date().getDay();
    let currentTime = moment().format("HH:mm");
    const haversine = `(
      3959 * acos(
          cos(radians(${data.latitude}))
          * cos(radians(latitude))
          * cos(radians(longitude) - radians(${data.longitude}))
          + sin(radians(${data.latitude})) * sin(radians(latitude))
      )
    )`;
    let cafeDetails = await CafeDB.paginate({
      page: parseInt(data.page),
      paginate: parseInt(USER_SEARCH_LIMIT),
      where: {
        deleted_at: 0,
        is_active: 1,
        signup_completed: 1,
        profile_completed: 1,
        menu_completed: 1,
        loyalty_completed: 1,
        is_admin_approved: 1,
        cafe_name: {
          [Op.like]: `%${data.cafe_name}%`,
        },
      },
      include: [
        {
          model: userFavoriteCafes,
          as: "user_favorite_cafes",
          required: false,
          where: {
            is_favorite: 1,
            user_id: parseInt(data.user_id),
          },
          attributes: ["is_favorite", "user_id"],
        },
        {
          model: CafeTimingDB,
          as: "time_sheet_data",
          required: false,
          where: {
            day: todayDayId,
            open_time: {
              [Op.lte]: currentTime,
            },
            close_time: {
              [Op.gte]: currentTime,
            },
          },
        },
      ],
      attributes: [
        "id",
        "cafe_name",
        "cafe_type",
        "bio",
        "cafe_tax",
        "phone",
        "banner_image",
        "address",
        "latitude",
        "longitude",
        [sequelize.literal(`round(${haversine})`), "distance"],
      ],
      order: [
        ["distance", "asc"],
        ["id", "desc"],
      ],
      subQuery: false,
    });
    cafeDetails = JSON.stringify(cafeDetails);
    cafeDetails = JSON.parse(cafeDetails);
    for (let i = 0; i < cafeDetails.docs.length; i++) {
      cafeDetails.docs[i].is_favorite =
        cafeDetails.docs[i].user_favorite_cafes.length > 0 ? 1 : 0;
      let checkTotalOrder = await OrderDB.count({
        where: {
          user_id: data.user_id,
          cafe_id: parseInt(cafeDetails.docs[i].id),
          status: 2,
          cafe_coupon_expired_time: 0,
        },
      });
      let nonUniversal = await LoyaltyStampDB.findOne({
        where: {
          cafe_id: parseInt(cafeDetails.docs[i].id),
          is_universal: 0,
        },
        attributes: ["stamp_no"],
      });
      cafeDetails.docs[i].reward = nonUniversal
        ? nonUniversal.stamp_no - checkTotalOrder
        : 0;
    }
    return cafeDetails;
  } catch (error) {
    throw new Error(error);
  }
}

// find cafe in favorites list

export async function findFavoriteCafeById(cafe_id, user_id) {
  try {
    let cafeDetails = await userFavoriteCafes.findAll({
      where: {
        cafe_id: parseInt(cafe_id),
        user_id: parseInt(user_id),
      },
    });
    return cafeDetails;
  } catch (error) {
    throw new Error(error);
  }
}

//favorite or unfavorite cafe

export async function favoriteCafeUpdate(user_id, cafe_id, updateData) {
  try {
    return await userFavoriteCafes.update(updateData, {
      where: {
        cafe_id: cafe_id,
        user_id: user_id,
      },
    });
  } catch (error) {
    throw new Error(error);
  }
}

export async function deleteFavoriteCafe(user_id, cafe_id) {
  try {
    return await userFavoriteCafes.destroy({
      where: {
        cafe_id: cafe_id,
        user_id: user_id,
      },
    });
  } catch (error) {
    throw new Error(error);
  }
}

export async function favoriteCafeAdd(favoriteCafeData) {
  try {
    return await userFavoriteCafes.create(favoriteCafeData);
  } catch (error) {
    throw new Error(error);
  }
}

// request cafe API
export async function requestCafe(cafeData) {
  try {
    return await CafeDB.create(cafeData);
  } catch (error) {
    throw new Error(error);
  }
}

// find request cafe API
export async function findRequestCafe(cafeData) {
  try {
    return await CafeDB.findOne({
      where: {
        email: cafeData.email,
      },
    });
  } catch (error) {
    throw new Error(error);
  }
}

// get cafe filter list

export async function cafeFilterList(data) {
  try {
    let option = {
      where: {
        is_active: 1,
      },
      page: data.page,
      paginate: 10,
      attributes: ["id", "name", "image", "color", "light_color"],
      order: [["id", "ASC"]],
    };
    return await cafeFilters.paginate(option);
  } catch (error) {
    throw new Error(error);
  }
}

// get cafe item category
export async function getCafeItemCatgory(data) {
  try {
    if (["", null, undefined, 0].includes(data.page)) {
      data.page = 1;
    }
    data.page = parseInt(data.page);

    // Step 1: Define category base filter
    const whereObject = {
      cafe_id: parseInt(data.cafe_id),
      cafe_menu_deleted_at: 0,
    };

    // Step 2: Get category order map for this cafe
    const orderRows = await MenuCategoryOrder.findAll({
      where: { cafe_id: data.cafe_id },
    });

    const categoryOrderMap = {};
    orderRows.forEach((row) => {
      categoryOrderMap[row.name] = row.order_number;
    });

    // Step 3: Fetch all categories (pagination removed because we'll paginate after filtering)
    const allCategories = await CafeMenuDB.findAll({
      where: whereObject,
      attributes: ["id", "cafe_id", "menu_name"],
    });

    // Step 4: Filter only those categories which have items
    const categoriesWithItems = [];

    for (let category of allCategories) {
      const itemCount = await CafeMenuItemDB.count({
        where: {
          cafe_menu_id: category.id,
          item_deleted_at: 0,
          status: 1,
        },
      });

      if (itemCount > 0) {
        categoriesWithItems.push(category);
      }
    }

    // Step 5: Sort by MenuCategoryOrder.order_number
    categoriesWithItems.sort((a, b) => {
      const orderA = categoryOrderMap[a.menu_name] ?? Number.MAX_SAFE_INTEGER;
      const orderB = categoryOrderMap[b.menu_name] ?? Number.MAX_SAFE_INTEGER;
      return orderA - orderB;
    });

    // Step 6: Paginate manually
    const pageSize = 35;
    const start = (data.page - 1) * pageSize;
    const paginatedDocs = categoriesWithItems.slice(start, start + pageSize);

    // Step 7: Return the result
    return {
      page: data.page,
      pages: Math.ceil(categoriesWithItems.length / pageSize),
      total: categoriesWithItems.length,
      docs: paginatedDocs,
    };
  } catch (error) {
    console.log(error);
    throw new Error(error);
  }
}

export async function getCafeItemCatgoryold(data) {
  try {
    // Validate and parse the page number
    if (["", null, undefined, 0].includes(data.page)) {
      data.page = 1;
    }
    data.page = parseInt(data.page);

    // Define the search criteria for categories
    let whereObject = {
      cafe_id: parseInt(data.cafe_id),
      cafe_menu_deleted_at: 0,
    };

    // Define the options for pagination and sorting
    let option = {
      where: whereObject,
      page: data.page,
      paginate: 35,
      attributes: ["id", "cafe_id", "menu_name"],
      order: [["id", "DESC"]],
    };

    // Fetch the categories with pagination
    let result = await CafeMenuDB.paginate(option);

    // Initialize an array to store categories with items
    let categoriesWithItems = [];

    // Check if each category has at least one item
    for (let category of result.docs) {
      let itemCount = await CafeMenuItemDB.count({
        where: {
          cafe_menu_id: category.id,
          item_deleted_at: 0,
          status: 1,
        },
      });
      // Add the category to the result if it has items
      if (itemCount > 0) {
        categoriesWithItems.push(category);
      }
    }

    // Return the categories with items
    return {
      ...result,
      docs: categoriesWithItems,
    };
  } catch (error) {
    throw new Error(error);
  }
}

//old function of cafe item category
// export async function getCafeItemCatgory(data) {
//   try {
//     if (['', null, undefined, 0].includes(data.page)) {
//       data.page = 1
//     }
//     data.page = parseInt(data.page)
//     let whereObject = {}
//     whereObject.cafe_id = parseInt(data.cafe_id)
//     whereObject.cafe_menu_deleted_at = 0
//     let option = {
//       where: whereObject,
//       page: data.page,
//       paginate: 10,
//       attributes: ['id', 'cafe_id', 'menu_name'],
//       order: [['id', 'DESC']],
//     }
//     let result = [];
//     result = await CafeMenuDB.paginate(option)
//     return result
//   } catch (error) {
//     throw new Error(error)
//   }
// }

// get cafe item list by category ID
export async function getCafeItemList(data) {
  try {
    if (["", null, undefined, 0].includes(data.page)) {
      data.page = 1;
    }
    if (["", null, undefined].includes(parseInt(data.filter))) {
      data.filter = "";
    }
    let whereObject = {};
    whereObject.cafe_menu_id = parseInt(data.menu_id);
    whereObject.item_deleted_at = 0;
    whereObject.status = 1;
    if (data.filter) {
      whereObject.item_type = {
        [Op.in]: data.filter.split(","),
      };
    }
    let option = {
      where: whereObject,
      page: parseInt(data.page),
      paginate: 10,
      include: [
        {
          model: PreDefinedImageDB,
          as: "image_data",
          attributes: ["item_name", "item_image"],
          required: true,
        },
        {
          model: AddonSizeCafeItemDB,
          include: [
            {
              model: AddonSizeDB,
              attributes: ["addon_size_name", "addon_size_price", "status"],
              required: false,
              where: {
                addon_size_deleted_at: 0,
              },
              include: [
                {
                  model: AddonDB,
                  required: false,
                  attributes: ["id", "addon_name"],
                },
              ],
            },
          ],
          required: false,
          attributes: ["id", "addon_size_id"],
        },
        {
          model: CafeMenuItemSizeDB,
          required: false,
          attributes: ["id", "item_size_price", "size_id"],
          include: [
            {
              model: SizeDB,
              attributes: ["id", "size_name"],
            },
          ],
        },
      ],
      attributes: [
        "id",
        "cafe_id",
        "cafe_menu_id",
        "item_name",
        "item_price",
        "item_description",
        "item_type",
      ],
      order: [["id", "DESC"]],
    };
    let result = await CafeMenuItemDB.paginate(option);
    result = JSON.stringify(result);
    result = JSON.parse(result);
    for (let index = 0; index < result.docs.length; index++) {
      const element = result.docs[index];
      element.cafe_menu_item_sizes.unshift({
        id: 0,
        item_size_price: element.item_price,
        size_id: 0,
        size: {
          id: 0,
          size_name: "Regular",
        },
      });
      element.cafe_menu_item_sizes.sort((a, b) =>
        a.size.id > b.size.id ? 1 : b.size.id > a.size.id ? -1 : 0
      );
      delete result.addon_size_cafe_items;
    }
    return result;
  } catch (error) {
    throw new Error(error);
  }
}

// cafe details
export async function getCafeDetails(id, userData) {
  try {
    const haversine = `(
      3959 * acos(
          cos(radians(${userData.user_latitude}))
          * cos(radians(latitude))
          * cos(radians(longitude) - radians(${userData.user_longitude}))
          + sin(radians(${userData.user_latitude})) * sin(radians(latitude))
      )
    )`;
    let result = await CafeDB.findOne({
      where: {
        id: parseInt(id),
      },
      attributes: [
        "id",
        "cafe_name",
        "phone",
        "cafe_tax",
        "bio",
        "email",
        "banner_image",
        "address",
        "latitude",
        "longitude",
        "stripe_account_id",
        "stripe_customer_id",
        [sequelize.literal(`round(${haversine})`), "distance"],
      ],
      include: [
        {
          model: CafeTimingDB,
          as: "time_sheet_data",
        },
        {
          model: userFavoriteCafes,
          as: "user_favorite_cafes",
          where: {
            user_id: userData.user_id,
            is_favorite: 1,
          },
          attributes: ["is_favorite", "user_id"],
          required: false,
        },
        {
          model: CafeGoToOrders,
          required: false,
          as: "cafe_go_to_orders",
          where: {
            user_id: userData.user_id,
          },
        },
        {
          model: CafeManagement,
        },
        {
          model: CafeClickCollectTiming,
        },
      ],
    });
    if (result) {
      result = JSON.stringify(result);
      result = JSON.parse(result);
      result.is_favorite = result.user_favorite_cafes.length > 0 ? 1 : 0;
    }
    return result;
  } catch (error) {
    throw new Error(error);
  }
}

// get cafe item details
export async function getCafeItemDetails(id) {
  try {
    let result = await CafeMenuItemDB.findOne({
      where: {
        id: id,
        status: 1,
        item_deleted_at: 0,
      },
      include: [
        {
          model: CafeDB,
          as: "cafe_data",
          attributes: ["cafe_name", "phone", "cafe_tax"],
        },
        {
          model: PreDefinedImageDB,
          as: "image_data",
          attributes: ["item_name", "item_image"],
        },
        {
          model: AddonSizeCafeItemDB,
          include: [
            {
              model: AddonSizeDB,
              required: true,
              attributes: ["addon_size_name", "addon_size_price"],
              where: {
                addon_size_deleted_at: 0,
                status: 1,
              },
              include: [
                {
                  model: AddonDB,
                  attributes: ["id", "addon_name"],
                },
              ],
            },
          ],
          attributes: ["id", "addon_size_id", "addon_size_price"], // Include addon_size_price
        },
        {
          model: CafeMenuItemSizeDB,
          attributes: ["id", "item_size_price", "size_id"],
          include: [
            {
              model: SizeDB,
              attributes: ["id", "size_name"],
            },
          ],
        },
      ],
      attributes: [
        "id",
        "item_name",
        "item_description",
        "item_image_id",
        "item_type",
        "item_price",
      ],
    });

    if (result) {
      result = JSON.stringify(result);
      result = JSON.parse(result);
      let tmp = [];
      let addon_size_cafe_items = [];
      for (
        let index = 0;
        index < result.addon_size_cafe_items.length;
        index++
      ) {
        const element = result.addon_size_cafe_items[index];
        if (!tmp.includes(element.addon_size.addon.id)) {
          tmp.push(element.addon_size.addon.id);
          let addon_sizes = [
            {
              addon_id: element.addon_size.addon.id,
              addon_name: element.addon_size.addon.addon_name,
              id: element.id,
              addon_size_id: element.addon_size_id,
              addon_size_name: element.addon_size.addon_size_name,
              addon_size_price: element.addon_size_price, // Return as addon_size_price
            },
          ];
          addon_size_cafe_items.push({
            addon_id: element.addon_size.addon.id,
            addon_name: element.addon_size.addon.addon_name,
            list: addon_sizes,
          });
        } else {
          let index = addon_size_cafe_items.findIndex(
            (size) => size.addon_id == element.addon_size.addon.id
          );
          addon_size_cafe_items[index]["list"].push({
            addon_id: element.addon_size.addon.id,
            addon_name: element.addon_size.addon.addon_name,
            id: element.id,
            addon_size_id: element.addon_size_id,
            addon_size_name: element.addon_size.addon_size_name,
            addon_size_price: element.addon_size_price, // Return as addon_size_price
          });
        }
      }
      //result.cafe_menu_item_sizes.unshift({
      //id: 0,
      //item_size_price: result.item_price,
      //size_id: 0,
      //size: {
      //id: 0,
      //size_name: 'Regular'
      //}
      //});
      //result.cafe_menu_item_sizes.sort((a, b) => (a.size.id > b.size.id) ? 1 : ((b.size.id > a.size.id) ? -1 : 0));
      delete result.addon_size_cafe_items;
      result.addon_size_cafe_items = addon_size_cafe_items;
    }

    return result;
  } catch (error) {
    throw new Error(error);
  }
}

// cafe suggested item list
export async function cafeItemSuggestedList(data) {
  try {
    let result = await SuggestedItemDB.paginate({
      paginate: 10,
      page: parseInt(data.page),
      where: {
        item_id: {
          [Op.in]: data.item_id.split(","),
        },
      },
      include: [
        {
          model: CafeMenuItemDB,
          where: {
            status: 1,
            item_deleted_at: 0,
          },
          required: true,
          attributes: [
            "id",
            "item_name",
            "item_description",
            "item_image_id",
            "item_type",
            "item_price",
          ],
          include: [
            {
              model: PreDefinedImageDB,
              as: "image_data",
              attributes: ["item_name", "item_image"],
              required: true,
            },
            {
              model: AddonSizeCafeItemDB,
              include: [
                {
                  model: AddonSizeDB,
                  required: false,
                  attributes: ["addon_size_name", "addon_size_price"],
                  where: {
                    addon_size_deleted_at: 0,
                  },
                  include: [
                    {
                      model: AddonDB,
                      required: false,
                      attributes: ["id", "addon_name", "addon_size_price"],
                    },
                  ],
                },
              ],
              required: false,
              attributes: ["id", "addon_size_id", "addon_size_price"],
            },
            {
              model: CafeMenuItemSizeDB,
              required: false,
              attributes: ["id", "item_size_price", "size_id"],
              include: [
                {
                  model: SizeDB,
                  attributes: ["id", "size_name"],
                },
              ],
            },
          ],
        },
      ],
      attributes: ["id", "item_id"],
    });
    return result;
  } catch (error) {
    throw new Error(error);
  }
}

export async function cafeGoToOrders(userId) {
  try {
    let result = await CafeGoToOrders.findAll({
      where: {
        user_id: userId,
      },
      include: [
        {
          model: CafeDB,
          attributes: [
            "id",
            "cafe_name",
            "banner_image",
            "cafe_tax",
            "stripe_account_id",
          ],
          include: [
            {
              model: userFavoriteCafes,
              as: "user_favorite_cafes",
              required: false,
              where: {
                is_favorite: 1,
                user_id: parseInt(userId),
              },
              attributes: ["is_favorite"],
            },
          ],
        },
      ],
    });
    return result;
  } catch (error) {
    throw new Error(error.message);
  }
}

export async function cafeGoToOrder(userId, cafeId) {
  try {
    let result = await CafeGoToOrders.findOne({
      where: {
        user_id: userId,
        cafe_id: cafeId,
      },
      include: [
        {
          model: CafeDB,
          attributes: ["id", "cafe_name", "banner_image", "cafe_tax"],
          include: [
            {
              model: userFavoriteCafes,
              as: "user_favorite_cafes",
              required: false,
              where: {
                is_favorite: 1,
                user_id: parseInt(userId),
              },
              attributes: ["is_favorite"],
            },
          ],
        },
      ],
    });
    return result;
  } catch (error) {
    throw new Error(error.message);
  }
}

export async function createGoToOrder(data) {
  try {
    let result = await CafeGoToOrders.create({
      user_id: data.loggedInUser,
      cafe_id: data.cafe_id,
      order_items: data.order_items,
      created_at: moment().unix(),
      updated_at: moment().unix(),
    });
    return result;
  } catch (error) {
    throw new Error(error.message);
  }
}

export async function updateGoToOrder(data) {
  try {
    const orderItems = JSON.parse(data.order_items);
    if (orderItems.length == 0) {
      let result = await CafeGoToOrders.destroy({
        where: {
          id: data.id,
        },
      });
      return result;
    }
    let result = await CafeGoToOrders.update(
      {
        order_items: data.order_items,
        updated_at: moment().unix(),
      },
      {
        where: {
          id: data.id,
        },
      }
    );
    return result;
  } catch (error) {
    throw new Error(error.message);
  }
}

export async function removeGoToOrder(data) {
  try {
    const result = await CafeGoToOrders.destroy({
      where: {
        user_id: data.loggedInUser,
        cafe_id: data.cafe_id,
        id: data.id,
      },
    });
    return result;
  } catch (error) {
    throw new Error(error.message);
  }
}