Sindbad~EG File Manager

Current Path : /home/infinitibizsol/.trash/controllers.3/
Upload File :
Current File : /home/infinitibizsol/.trash/controllers.3/auctioneerController.js

const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const db = require("../models");
const { Op } = require("sequelize");
const { col } = require("sequelize");
const bodyParser = require("body-parser");

function calculateDateRange(timeRange) {
  const currentDate = new Date();

  switch (timeRange) {
    case "currentweek":
      const currentWeekStartDate = new Date(currentDate);
      currentWeekStartDate.setDate(
        currentDate.getDate() - currentDate.getDay()
      );
      currentWeekStartDate.setHours(0, 0, 0, 0);

      const currentWeekEndDate = new Date(currentDate);
      currentWeekEndDate.setDate(
        currentWeekEndDate.getDate() + (6 - currentWeekEndDate.getDay())
      );
      currentWeekEndDate.setHours(23, 59, 59, 999);

      return { startDate: currentWeekStartDate, endDate: currentWeekEndDate };

    case "lastweek":
      const lastWeekStartDate = new Date(currentDate);
      lastWeekStartDate.setDate(
        lastWeekStartDate.getDate() - lastWeekStartDate.getDay() - 7
      );
      lastWeekStartDate.setHours(0, 0, 0, 0);

      const lastWeekEndDate = new Date(currentDate);
      lastWeekEndDate.setDate(
        lastWeekEndDate.getDate() - lastWeekEndDate.getDay() - 1
      );
      lastWeekEndDate.setHours(23, 59, 59, 999);

      return { startDate: lastWeekStartDate, endDate: lastWeekEndDate };

    case "last4weeks":
      const last4WeeksStartDate = new Date(currentDate);
      last4WeeksStartDate.setDate(last4WeeksStartDate.getDate() - 28);
      last4WeeksStartDate.setHours(0, 0, 0, 0);

      const last4WeeksEndDate = new Date(currentDate);
      last4WeeksEndDate.setDate(last4WeeksEndDate.getDate());
      last4WeeksEndDate.setHours(23, 59, 59, 999);

      return { startDate: last4WeeksStartDate, endDate: last4WeeksEndDate };
    case "last12weeks":
      const last12WeeksStartDate = new Date(currentDate);
      last12WeeksStartDate.setDate(last12WeeksStartDate.getDate() - 84);
      last12WeeksStartDate.setHours(0, 0, 0, 0);

      const last12WeeksEndDate = new Date(currentDate);
      last12WeeksEndDate.setDate(last12WeeksEndDate.getDate());
      last12WeeksEndDate.setHours(23, 59, 59, 999);

      return { startDate: last12WeeksStartDate, endDate: last12WeeksEndDate };

    default:
      // Handle other cases or return an error
      return null;
  }
}

const auctioneerLogin = async (req, res) => {
  try {
    const { email, password } = req.body;
    let result = await db.tblAuctioneer.findAll({
      where: {
        email: email,
      },
    });
    if (result.length <= 0) {
      return res
        .status(404)
        .json({ status: 404, message: "Invalid credentials" });
    }
    const isMatched = await bcrypt.compare(password, result[0].password);
    if (!isMatched) {
      return res
        .status(403)
        .json({ status: 403, message: "Invalid credentials" });
    }
    let token = await jwt.sign(
      { email: result[0].email, auctioneerId: result[0].auctioneer_id },
      process.env.JWT_KEY
    );
    return res.json({
      status: 200,
      message: "Success",
      data: [{ token, ...result[0].dataValues }],
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};
const getAuctioneerProfile = async (req, res) => {
  const auctioneer_id = req.params.id;

  try {
    let [result] = await db.tblAuctioneer.findAll({
      where: {
        auctioneer_id: auctioneer_id,
      },
    });
    if (!result) {
      return res.json({ status: 402, message: "No user Found" });
    }

    return res.json({
      status: 200,
      message: "Success",
      data: [
        {
          user_id: result.auctioneer_id,
          first_name: result.first_name,
          last_name: result.last_name,
          email: result.email,
          contact: result.contact,
          address: result.address,
          business_address: result.business_address,
          business_name: result.business_name,
          username: result.username,
        },
      ],
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const removeAuctioneer = async (req, res) => {
  const { email } = req.body;

  let transaction;

  try {
    transaction = await db.sequelize.transaction(); // Start a new transaction

    const auctioneer = await db.tblAuctioneer.findOne({
      where: { email },
      transaction,
    });

    if (!auctioneer) {
      await transaction.rollback(); // Ensure transaction is rolled back if auctioneer does not exist
      return res
        .status(404)
        .json({ status: 404, message: "Auctioneer not found." });
    }

    const opportunities = await db.tblOpportunity.findAll({
      where: { auctioneer_id: auctioneer.auctioneer_id },
      transaction,
    });

    const opportunity_ids = opportunities.map(
      (opportunity) => opportunity.opportunity_id
    );

    vehicle_run = await db.tblVehicleRun.findAll({
      where: {
        opportunity_id: {
          [Op.in]: opportunity_ids, // Use the `Op.in` operator to look for any opportunity_id in the provided array
        },
      },
      transaction,
    });
    const vehicle_run_ids = vehicle_run.map((item) => item.vehicle_run_id);

    const vehicle_run_fee_deleted_count = await db.tblVehicleRunFee.destroy({
      where: { vehicle_run_id: vehicle_run_ids },
      transaction,
    });

    const auctioneer_feeses_deleted_count = await db.tblAuctioneerFee.destroy({
      where: { auctioneer_id: auctioneer.auctioneer_id },
      transaction,
    });

    const vehicle_run_deleted_count = await db.tblVehicleRun.destroy({
      where: { opportunity_id: opportunity_ids },
      transaction,
    });

    const opportunity_deleted_count = await db.tblOpportunity.destroy({
      where: { opportunity_id: opportunity_ids },
      transaction,
    });

    const subscription_deleted_count = await db.tblUserSubAuctioneer.destroy({
      where: { auctioneer_id: auctioneer.auctioneer_id },
      transaction,
    });

    const auctioneer_deleted_count = await db.tblAuctioneer.destroy({
      where: { auctioneer_id: auctioneer.auctioneer_id },
      transaction,
    });

    await transaction.commit(); // Commit all changes

    return res.status(200).json({
      message: "Auctioneer and related data successfully deleted.",
      details: {
        vehicle_runs: vehicle_run_deleted_count,
        vehicle_runs_fee: vehicle_run_fee_deleted_count,
        opportunities: opportunity_deleted_count,
        subscriptions: subscription_deleted_count,
        auctioneer_fee: auctioneer_feeses_deleted_count,
        auctioneer: auctioneer_deleted_count,
      },
    });
  } catch (error) {
    if (transaction) {
      try {
        // Additional safeguard to ensure that we do not call rollback on an already finished transaction.
        if (!transaction.finished) {
          await transaction.rollback();
        }
      } catch (rollbackError) {
        console.error("Rollback error:", rollbackError);
      }
    }

    return res.status(500).json({
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const updateAuctioneerPassword = async (req, res) => {
  try {
    let { auctioneer_id, newPassword } = req.body;

    if (newPassword) {
      const salt = await bcrypt.genSalt(10);
      const hashedPassword = await bcrypt.hash(newPassword, salt);
      let result = await db.tblAuctioneer.update(
        { password: hashedPassword },
        { where: { auctioneer_id: auctioneer_id } }
      );

      return res.status(200).json({ status: 200, message: "Success" });
    } else {
      return res.json({ status: 400, message: "Please enter new password." });
    }
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

//Hamza Ali
const GetAuctioneerUsers = async (req, res) => {
  try {
    let { auctioneerId, weekId, sortBy, orderDirection } = req.body;
    if (sortBy === "sold_price") {
      sortBy = "vehicle_id";
    }
    let timeRange;
    if (!req.body.timeRange) {
      timeRange = "currentweek";
    } else {
      timeRange = req.body.timeRange;
    }
    timeRange = timeRange.replace(/\s/g, "");
    timeRange = timeRange.toLowerCase();
    const currentDate = new Date();

    const weekRange = calculateDateRange(timeRange);
    const result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        week_id: weekId,
        auctioneer_id: auctioneerId,
      },
      include: [
        {
          model: db.tblUser,
          attributes: ["user_id", "first_name", "last_name"],
        },
        {
          model: db.tblVehicleRun,
          include: [
            {
              model: db.tblVehicle,
            },
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["auction_id", "name"],
                },
              ],
            },
          ],
        },
      ],
    });
    // return res.json(result);
    const formattedData = result.map((item) => ({
      user_id: item.tblUser.user_id,
      first_name: item.tblUser.first_name,
      last_name: item.tblUser.last_name,
      tblVehicles: item.tblVehicleRuns.map((vehicleRun) => {
        const vehicle = vehicleRun.tblVehicle || {};
        const auctionLane = vehicleRun.tblAuctionLane || {
          lane_id: null,
          name: null,
          tblAuction: {
            auction_id: null,
            name: null,
          },
        };
        const auction = auctionLane.tblAuction;
        return {
          vehicle_id: vehicle.vehicle_id,
          vin: vehicle.vin,
          year: vehicle.year,
          make: vehicle.make,
          model: vehicle.model,
          trim: vehicle.trim,
          mileage: vehicle.mileage,
          color: vehicle.color,
          color_name: vehicle.color_name || null,
          imageUrl: vehicle.imageUrl,
          details: vehicle.details || null,
          condition_light: vehicleRun.condition_light,
          announcements: vehicleRun.announcements,
          reserve: vehicleRun.reserve,
          sale_price: vehicleRun.sale_price,
          vehicle_total_fee: vehicleRun.vehicle_total_fee || null,
          net_proceed: vehicleRun.net_proceed || null,
          sale_status: vehicleRun.sale_status,
          run_no: vehicleRun.run_no,
          lane_id: auctionLane.lane_id,
          lane_name: auctionLane.name,
          auction_name: auction.name,
        };
      }),
    }));
    return res.json({
      status: 200,
      message: "Success",
      filter_type: "whole_saler",
      data: formattedData,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const GetAuctioneerUsersOnly = async (req, res) => {
  try {
    const { auctioneerId, weekId, orderDirection, sortBy } = req.body;

    const { sequelize, tblUser, tblOpportunity, tblVehicle } = db;

    const result = await tblUser.findAll({
      attributes: [
        "user_id",
        "first_name",
        "last_name",
        [
          sequelize.fn(
            "COUNT",
            sequelize.col("tblOpportunities.tblVehicleRuns.opportunity_id")
          ),
          "units",
        ],
      ],
      include: [
        {
          model: tblOpportunity,
          attributes: [],
          include: [
            {
              model: db.tblVehicleRun,
              attributes: [],
              raw: true,
            },
          ],
          where: {
            auctioneer_id: auctioneerId,
            week_id: parseInt(weekId),
          },
        },
      ],

      group: ["tblUser.user_id", "tblOpportunities.opportunity_id"],
    });

    return res.json({
      status: 200,
      message: "Success",
      filter_type: "user",
      data: result,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const updateVehicleStatus = async (req, res) => {
  try {
    let result;
    const vehicle_id = req.body.vehicle_id;
    [result] = await db.tblVehicleRun.findAll({
      where: {
        vehicle_id: vehicle_id,
      },
    });

    if (!result) {
      await db.tblVehicleRun.create(req.body);
    } else {
      await db.tblVehicleRun.update(req.body, {
        where: {
          vehicle_id: vehicle_id,
        },
      });
    }
    return res.json({ status: 200, message: "Success" });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const updateAuctioneerProfile = async (req, res) => {
  const { auctioneer_id, ...data } = req.body;
  if (req.body.password) {
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(req.body.password, salt);
    data.password = hashedPassword;
  }
  try {
    let result = await db.tblAuctioneer.update(data, {
      where: {
        auctioneer_id: req.body.auctioneer_id,
      },
    });

    return res.json({
      status: 200,
      message: "profile updated",
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

//Auctioneer Side
const getAllAssignedVehicles = async (req, res) => {
  try {
    const { auctioneer_id, user_id, weekId } = req.body;
    const week_Id = parseInt(weekId);
    let timeRange;
    if (!req.body.timeRange) {
      timeRange = "last4weeks";
    } else {
      timeRange = req.body.timeRange;
    }
    timeRange = timeRange.replace(/\s/g, "");
    timeRange = timeRange.toLowerCase();

    const currentDate = new Date();

    const weekRange = calculateDateRange(timeRange);

    let result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        user_id: user_id,
        week_id: week_Id,
        auctioneer_id: auctioneer_id,
      },
      include: [
        {
          model: db.tblVehicle,
          raw: true,
          where: {
            user_id: user_id,
            opportunity_id: col("tblOpportunity.opportunity_id"),
          },
          include: [
            {
              model: db.tblVehicleRun,
              raw: true,
              include: [
                {
                  model: db.tblAuctionLane,
                  attributes: ["lane_id", "name"],
                  raw: true,
                  include: [
                    {
                      model: db.tblAuction,
                      attributes: ["auction_id", "name"],
                      raw: true,
                    },
                  ],
                },
              ],
            },
          ],
        },
      ],

      // order: [["createdAt", "ASC"]]
    });

    const formattedData = result.flatMap((user) =>
      user.tblVehicles.flatMap((vehicle) => {
        const run = vehicle.tblVehicleRuns[0];
        return {
          vehicle_id: vehicle.vehicle_id,
          vin: vehicle.vin,
          year: vehicle.year,
          make: vehicle.make,
          model: vehicle.model,
          trim: vehicle.trim,
          mileage: vehicle.mileage,
          color: vehicle.color,
          color_name: vehicle.color_name,
          details: vehicle.details,
          imageUrl: vehicle.imageUrl,
          opportunity_id: vehicle.opportunity_id,
          user_id: vehicle.user_id,
          createdAt: vehicle.createdAt,
          updatedAt: vehicle.updatedAt,

          vehicle_run_id: run.vehicle_run_id,
          condition_light: run.condition_light,
          announcements: run.announcements || null,
          reserve: run.reserve || null,
          sale_price: run.sale_price || null,
          auction_fee: run.auction_fee || null,
          net_profit: run.net_profit || null,
          sale_status: run.sale_status || false,
          run_no: run.run_no || null,
          lane_id: run.lane_id || null,
          lane_name: run.tblAuctionLane
            ? run.tblAuctionLane.name || null
            : null,
          auction_id:
            run.tblAuctionLane && run.tblAuctionLane.tblAuction
              ? run.tblAuctionLane.tblAuction.auction_id || null
              : null,
          auction_name:
            run.tblAuctionLane && run.tblAuctionLane.tblAuction
              ? run.tblAuctionLane.tblAuction.name || null
              : null,
        };
      })
    );
    return res.json({ status: 200, message: "Success", data: formattedData });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const getAllAssignedVehiclesOnly = async (req, res) => {
  try {
    const {
      auctioneer_id,
      user_id,
      weekId,
      sortBy = "vehicle_id",
      orderDirection = "ASC",
    } = req.body;
    const week_Id = parseInt(weekId);
    let timeRange;
    if (!req.body.timeRange) {
      timeRange = "last4weeks";
    } else {
      timeRange = req.body.timeRange;
    }
    timeRange = timeRange.replace(/\s/g, "");
    timeRange = timeRange.toLowerCase();
    let result;
    result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        user_id: user_id,
        week_id: week_Id,
        auctioneer_id: auctioneer_id,
      },
      include: [
        {
          model: db.tblVehicleRun,
          raw: true,
          where: {
            opportunity_id: col("tblOpportunity.opportunity_id"),
          },
          include: [
            {
              model: db.tblVehicle,
              raw: true,
            },
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              raw: true,
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["auction_id", "name"],
                  raw: true,
                },
              ],
            },
          ],
        },
      ],
      order: [[db.tblVehicleRun, db.tblVehicle, sortBy, orderDirection]],
    });
    // return res.json(result);
    const transformedData = result.flatMap((opportunity) =>
      opportunity.tblVehicleRuns.map((run) => ({
        vehicle_id: run.vehicle_id,
        vin: run.tblVehicle.vin,
        year: run.tblVehicle.year,
        make: run.tblVehicle.make,
        model: run.tblVehicle.model,
        trim: run.tblVehicle.trim,
        mileage: run.tblVehicle.mileage,
        color: run.tblVehicle.color,
        color_name: run.tblVehicle.color_name,
        details: run.tblVehicle.details,
        imageUrl: run.tblVehicle.imageUrl,
        opportunity_id: run.opportunity_id,
        user_id: run.tblVehicle.user_id,
        vehicle_run_id: run.vehicle_run_id,
        condition_light: run.condition_light || 0,
        announcements: run.announcements,
        reserve: run.reserve || 0,
        sale_price: run.sale_price || 0,
        vehicle_total_fee: run.vehicle_total_fee || 0,
        net_proceed: run.net_proceed || 0,
        sale_status: run.sale_status || false,
        run_no: run.run_no || null,
        auction_fee: run.auction_fee || 300,
        lane_id: run.lane_id || null,

        // Additional fields from tblAuctionLane and nested tblAuction if present
        lane_name: run.tblAuctionLane ? run.tblAuctionLane.name : null,
        auction_id:
          run.tblAuctionLane && run.tblAuctionLane.tblAuction
            ? run.tblAuctionLane.tblAuction.auction_id
            : null,
        auction_name:
          run.tblAuctionLane && run.tblAuctionLane.tblAuction
            ? run.tblAuctionLane.tblAuction.name
            : null,
      }))
    );

    return res.json({ status: 200, message: "Success", data: transformedData });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};
//Hamza Ali
const sortAuctioneerVehicles = async (req, res) => {
  try {
    const { auctioneerId, weekId, orderDirection, sortBy } = req.body;

    // Find user_ids from tblOpportunity based on auctioneerId and weekId
    const userOpportunityIds = await db.tblOpportunity.findAll({
      attributes: ["user_id"],
      where: {
        auctioneer_id: auctioneerId,
        week_id: parseInt(weekId),
      },
      raw: true,
    });

    // Extract user_ids from the result
    const userIds = userOpportunityIds.map(
      (opportunity) => opportunity.user_id
    );

    // Find user data from tblUser and tblVehicle based on the obtained user_ids

    let whereClause = {};

    // Adjust the where clause based on sortBy
    if (sortBy == "sold_price") {
      sortBy = "vehicle_id";
    }

    const result = await db.tblUser.findAll({
      attributes: ["user_id", "first_name", "last_name"],
      include: [
        {
          model: db.tblVehicle,
          attributes: [
            "vin",
            "year",
            "make",
            "model",
            "trim",
            "mileage",
            "color",
            "color_name",
            "imageUrl",
            "details",
          ],
          include: [
            {
              model: db.tblOpportunity,
              attributes: [],
              where: {
                auctioneer_id: auctioneerId,
                week_id: parseInt(weekId),
              },
              raw: true,
            },
            {
              model: db.tblVehicleRun,
              attributes: [
                "reserve",
                "sale_status",
                "sale_price",
                "condition_light",
                "announcements",
                "auction_fee",
              ],
              raw: true,
              include: [
                {
                  model: db.tblAuctionLane,
                  attributes: ["lane_id", "name"],
                  raw: true,
                  include: [
                    {
                      model: db.tblAuction,
                      attributes: ["auction_id", "name"],
                      raw: true,
                    },
                  ],
                },
              ],
            },
          ],

          raw: true,
          where: whereClause,
        },
      ],

      order: [[db.tblVehicle, sortBy || "vehicle_id", orderDirection || "ASC"]],
    });
    // Format the result as needed
    const formattedData = result.map((user) => ({
      user_id: user.user_id,
      first_name: user.first_name,
      last_name: user.last_name,
      tblVehicles: user.tblVehicles.map((vehicle) => ({
        vin: vehicle.vin,
        year: vehicle.year,
        make: vehicle.make,
        model: vehicle.model,
        trim: vehicle.trim,
        mileage: vehicle.mileage,
        color: vehicle.color,
        color_name: vehicle.color_name,
        imageUrl: vehicle.imageUrl,
        details: vehicle.details,
        reserve: vehicle.tblVehicleRuns[0].reserve,
        sale_status: vehicle.tblVehicleRuns[0].sale_status,
        sale_price: vehicle.tblVehicleRuns[0].sale_price,
        condition_light: vehicle.tblVehicleRuns[0].condition_light,
        announcements: vehicle.tblVehicleRuns[0].announcements,
        auction_fee: vehicle.tblVehicleRuns[0].auction_fee,
        lane_id: vehicle.tblVehicleRuns[0].tblAuctionLane.lane_id,
        lane_name: vehicle.tblVehicleRuns[0].tblAuctionLane.name,
        auction_name: vehicle.tblVehicleRuns[0].tblAuctionLane.tblAuction.name,
      })),
    }));

    return res.json({ status: 200, message: "Success", data: formattedData });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const filterByConditionLight = async (req, res) => {
  try {
    const { auctioneerId, weekId } = req.body;
    const auctioneer_id = auctioneerId;
    const week_id = weekId;
    let result = await db.sequelize.query(
      "CALL aFilterByConditionLight(:auctioneer_id,:week_id)",
      {
        replacements: { auctioneer_id, week_id },
        type: db.Sequelize.QueryTypes.SELECT,
      }
    );
    let data = result[0];
    const formattedData = Object.values(data)
      .flat()
      .filter(
        (item) => typeof item === "object" && !item.hasOwnProperty("fieldCount")
      );
    // return res.json(formattedData);
    const conditionLightValues = [0, 1, 2, 3, 4];
    // Check for missing condition_light values
    const missingValues = conditionLightValues.filter((value) => {
      return !formattedData.some((item) => item.condition_light === value);
    });
    // Add missing values to the existing data
    const newData = formattedData.concat(
      missingValues.map((value) => ({
        condition_light: value,
        units: 0,
      }))
    );
    const filteredData = newData.filter((item) => item.condition_light != 0);
    // # Sorting the list in-place in ascending order of 'condition_light'
    filteredData.sort((a, b) => a.condition_light - b.condition_light);

    return res.json({
      status: 200,
      message: "Success",
      filter_type: "condition_light",
      data: filteredData,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const getConditionLightVehicles = async (req, res) => {
  try {
    const { condition_light, auctioneer_id, week_id, sortBy, orderDirection } =
      req.body;
    let result;
    result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: { auctioneer_id, week_id },
      include: [
        {
          model: db.tblVehicleRun,
          // required: true, // Use this instead of raw to ensure an INNER JOIN
          where: { condition_light: condition_light },
          include: [
            {
              model: db.tblVehicle,
              // required: true, // Use this instead of raw to ensure an INNER JOIN
            },
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              // required: true, // Use this instead of raw to ensure an INNER JOIN
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["auction_id", "name"],
                  // required: true, // Use this instead of raw to ensure an INNER JOIN
                },
              ],
            },
          ],
        },
      ],
      order: [
        // Include the nested order here instead
        [db.tblVehicleRun, db.tblVehicle, sortBy, orderDirection],
      ],
    });

    if (result.length <= 0) {
      return res.json({ status: 200, message: "Success", data: [] });
    }
    // // Format the result as per the required format
    const formattedResult = result.flatMap((item) =>
      item.tblVehicleRuns.map((vehicleRun) => {
        const vehicle = vehicleRun.tblVehicle || {};
        const auctionLane = vehicleRun.tblAuctionLane || {};
        const auction = auctionLane.tblAuction || {};

        return {
          vehicle_id: vehicle.vehicle_id,
          year: vehicle.year,
          make: vehicle.make,
          model: vehicle.model,
          vin: vehicle.vin,
          mileage: vehicle.mileage,
          imageUrl: vehicle.imageUrl,
          color: vehicle.color,
          color_name: vehicle.color_name,
          details: vehicle.details,
          condition_light: vehicleRun?.condition_light || 0,
          sale_price: vehicleRun?.sale_price || 0,
          run_no: vehicleRun?.run_no || null,
          sale_status: vehicleRun?.sale_status || false,
          lane_id: vehicleRun?.lane_id || null,
          auction_fee: vehicleRun?.auction_fee || 300,
          net_proceed: vehicleRun?.net_proceed || 0,
          vehicle_total_fee: vehicleRun?.vehicle_total_fee || 0,
          reserve: vehicleRun?.reserve || 0,
          lane_name: auctionLane?.name || null,
          auction_id: auction?.auction_id || null,
          auction_name: auction?.name || null,
        };
      })
    );
    return res.json({ status: 200, message: "Success", data: formattedResult });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const filterBySaleStatus = async (req, res) => {
  try {
    const { auctioneerId, weekId } = req.body;
    const auctioneer_id = auctioneerId;
    const week_id = weekId;
    let result = await db.sequelize.query(
      "CALL aFilterBySaleStatus(:auctioneer_id,:week_id)",
      {
        replacements: { auctioneer_id, week_id },
        type: db.Sequelize.QueryTypes.SELECT,
      }
    );
    let data = result[0];
    const formattedData = Object.values(data)
      .flat()
      .filter(
        (item) => typeof item === "object" && !item.hasOwnProperty("fieldCount")
      );
    const saleStatusValues = ["true", "false"];
    // Initialize newData with default objects if existingData is empty
    let newData = [];
    if (result.length === 0) {
      newData = saleStatusValues.map((value) => ({
        opportunity_id: 0,
        auctioneer_id: 0,
        sale_status: value,
        units: 0,
      }));
      return res.json({
        status: 200,
        message: "Success",
        data: newData,
      });
    }

    const missingValues = saleStatusValues.filter((value) => {
      return !formattedData.some((item) => item.sale_status === value);
    });

    // Add missing values to the existing data
    newData = formattedData.concat(
      missingValues.map((value) => ({
        sale_status: value,
        units: 0,
      }))
    );

    return res.json({
      status: 200,
      message: "Success",
      filter_type: "sale_status",
      data: newData,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const getSaleStatusVehicles = async (req, res) => {
  try {
    const { sale_status, auctioneer_id, week_id, sortBy, orderDirection } =
      req.body;

    let result;
    result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: { auctioneer_id, week_id },
      include: [
        {
          model: db.tblVehicleRun,
          // required: true, // Use this instead of raw to ensure an INNER JOIN
          where: { sale_status: sale_status },
          include: [
            {
              model: db.tblVehicle,
              // required: true, // Use this instead of raw to ensure an INNER JOIN
            },
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              required: false, // Use this instead of raw to ensure an INNER JOIN
              where: { auctioneer_id: auctioneer_id },
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["auction_id", "name"],
                  // required: true, // Use this instead of raw to ensure an INNER JOIN
                },
              ],
            },
          ],
        },
      ],
      order: [
        // Include the nested order here instead
        [db.tblVehicleRun, db.tblVehicle, sortBy, orderDirection],
      ],
    });

    // return res.json(result);
    if (result.length <= 0) {
      return res.json({ status: 200, message: "Success", data: [] });
    }
    // // Format the result as per the required format
    const formattedResult = result.flatMap((item) =>
      item.tblVehicleRuns.map((vehicleRun) => {
        const vehicle = vehicleRun.tblVehicle || {};
        const auctionLane = vehicleRun.tblAuctionLane || {};
        const auction = auctionLane.tblAuction || {};

        return {
          vehicle_id: vehicle.vehicle_id,
          year: vehicle.year,
          make: vehicle.make,
          model: vehicle.model,
          vin: vehicle.vin,
          mileage: vehicle.mileage,
          imageUrl: vehicle.imageUrl,
          color: vehicle.color,
          color_name: vehicle.color_name,
          details: vehicle.details,
          condition_light: vehicleRun?.condition_light || 0,
          sale_price: vehicleRun?.sale_price || 0,
          run_no: vehicleRun?.run_no || null,
          sale_status: vehicleRun?.sale_status || false,
          lane_id: vehicleRun?.lane_id || null,
          auction_fee: vehicleRun?.auction_fee || 300,
          net_proceed: vehicleRun?.net_proceed || 0,
          vehicle_total_fee: vehicleRun?.vehicle_total_fee || 0,
          reserve: vehicleRun?.reserve || 0,
          lane_name: auctionLane?.name || null,
          auction_id: auction?.auction_id || null,
          auction_name: auction?.name || null,
        };
      })
    );
    return res.json({ status: 200, message: "Success", data: formattedResult });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const filterByAuctioneerAuctions = async (req, res) => {
  try {
    const { auctioneerId, weekId } = req.body;
    const auctioneer_id = auctioneerId;
    const week_id = weekId;
    let results = await db.sequelize.query(
      "CALL aFilterByAuction(:auctioneer_id,:week_id)",
      {
        replacements: { auctioneer_id, week_id },
      }
    );

    // Returning the result as a response
    return res.json({
      status: 200,
      message: "Success",
      filter_type: "auction",
      data: results,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const GetVehicleCountBySaleStatus = async (req, res) => {
  try {
    const { auctioneerId, weekId } = req.body;

    // Find user_ids from tblOpportunity based on auctioneerId and weekId
    const userOpportunityIds = await db.tblOpportunity.findAll({
      attributes: ["user_id"],
      where: {
        auctioneer_id: auctioneerId,
        week_id: parseInt(weekId),
      },
      raw: true,
    });

    // Extract user_ids from the result
    const userIds = userOpportunityIds.map(
      (opportunity) => opportunity.user_id
    );

    // Find user data from tblUser and tblVehicle based on the obtained user_ids
    const result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        week_id: weekId,
        auctioneer_id: auctioneerId,
      },
      include: [
        {
          model: db.tblUser,
          attributes: ["user_id", "first_name", "last_name"],
        },
        {
          model: db.tblVehicleRun,
          include: [
            {
              model: db.tblVehicle,
            },
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["auction_id", "name"],
                },
              ],
            },
          ],
        },
      ],
    });
    // return res.json(result);

    const modifiedData = result.map((item) => {
      return {
        user_id: item.tblUser.user_id,
        first_name: item.tblUser.first_name,
        last_name: item.tblUser.last_name,
        sold_vehicles: item.tblVehicleRuns
          .filter((run) => run.sale_status === true)
          .map((run) => {
            const vehicle = run.tblVehicle;
            return {
              vehicle_id: vehicle.vehicle_id,
              vin: vehicle.vin,
              year: vehicle.year,
              make: vehicle.make,
              model: vehicle.model,
              imageUrl: vehicle.imageUrl,
              trim: vehicle.trim,
              mileage: vehicle.mileage,
              color: vehicle.color,
              color_name: vehicle.color_name,
              details: vehicle.details,
              reserve: run.reserve,
              sale_status: run.sale_status,
              sale_price: run.sale_price,
              condition_light: run.condition_light,
              announcements: run.announcements,
              auction_fee: run.vehicle_total_fee, // Assuming auction_fee refers to 'vehicle_total_fee' field.
              run_no: run.run_no,
              lane_id: run.tblAuctionLane.lane_id,
              lane_name: run.tblAuctionLane.name,
              auction_name: run.tblAuctionLane.tblAuction.name,
            };
          }),
        not_sold_vehicles: item.tblVehicleRuns
          .filter((run) => run.sale_status === false)
          .map((run) => {
            const vehicle = run.tblVehicle;
            return {
              vin: vehicle.vin,
              year: vehicle.year,
              make: vehicle.make,
              model: vehicle.model,
              imageUrl: vehicle.imageUrl,
              trim: vehicle.trim,
              mileage: vehicle.mileage,
              color: vehicle.color,
              color_name: vehicle.color_name,
              details: vehicle.details,
              reserve: run.reserve,
              sale_status: run.sale_status,
              sale_price: run.sale_price,
              condition_light: run.condition_light,
              announcements: run.announcements,
              auction_fee: run.vehicle_total_fee, // Assuming auction_fee refers to 'vehicle_total_fee' field.
              run_no: run.run_no,
              lane_id: run.tblAuctionLane ? run.tblAuctionLane.lane_id : null,
              lane_name: run.tblAuctionLane ? run.tblAuctionLane.name : null,
              auction_name: run.tblAuctionLane
                ? run.tblAuctionLane.tblAuction.name
                : null,
            };
          }),
      };
    });

    return res.json({
      status: 200,
      message: "Success",
      data: modifiedData,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};
const GetVehicleCountByAuction = async (req, res) => {
  try {
    const { auctioneerId, weekId } = req.body;

    // Find user_ids from tblOpportunity based on auctioneerId and weekId
    const userOpportunityIds = await db.tblOpportunity.findAll({
      attributes: ["user_id"],
      where: {
        auctioneer_id: auctioneerId,
        week_id: parseInt(weekId),
      },
      raw: true,
    });
    // Extract user_ids from the result
    const userIds = userOpportunityIds.map(
      (opportunity) => opportunity.user_id
    );

    // Find user data from tblUser and tblVehicle based on the obtained user_ids
    const [result] = await db.sequelize.query(`
SELECT 
o.opportunity_id,
auc.auction_id as auction_id,
auc.name as auction_name,
v.vin,
v.year,
v.make,
v.model, 
al.lane_id,
al.name as lane_name,
vr.announcements,
vr.condition_light,
vr.sale_price,
vr.sale_status
from  tblopportunities as o 
inner join tblauctioneers as a on a.auctioneer_id=o.auctioneer_id
inner join tblauctionlanes as al on al.auctioneer_id=a.auctioneer_id
inner join tblauctions as auc on auc.auction_id=al.auction_id
inner join tblvehicleruns as vr on vr.lane_id=al.lane_id
inner join tblvehicles as v on v.vehicle_id=vr.vehicle_id
where o.auctioneer_id=${auctioneerId} and o.week_id=${weekId};`);
    const groupByAuctionID = (data) => {
      return data.reduce((acc, currentValue) => {
        // Find an auction in the accumulator array.
        let auction = acc.find((a) => a.auction_id === currentValue.auction_id);

        // If the auction doesn't exist, create it and push it to the accumulator.
        if (!auction) {
          auction = {
            auction_id: currentValue.auction_id,
            auction_name: currentValue.auction_name,
            data: [],
          };
          acc.push(auction);
        }

        // Add the current value to the data array of the found/created auction.
        auction.data.push({
          opportunity_id: currentValue.opportunity_id,
          vin: currentValue.vin.trim(),
          year: currentValue.year,
          make: currentValue.make.trim(),
          model: currentValue.model.trim(),
          lane_id: currentValue.lane_id,
          lane_name: currentValue.lane_name,
          announcements: currentValue.announcements,
          condition_light: currentValue.condition_light,
          sale_price: currentValue.sale_price,
          sale_status: currentValue.sale_status,
        });

        return acc;
      }, []);
    };

    const transformedData = groupByAuctionID(result);

    return res.json({
      status: 200,
      message: "Success",
      data: transformedData,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const GetVehicleCountByConditionLight = async (req, res) => {
  try {
    const { auctioneerId, weekId } = req.body;

    // Find user_ids from tblOpportunity based on auctioneerId and weekId
    const userOpportunityIds = await db.tblOpportunity.findAll({
      attributes: ["user_id"],
      where: {
        auctioneer_id: auctioneerId,
        week_id: parseInt(weekId),
      },
      raw: true,
    });

    // Extract user_ids from the result
    const userIds = userOpportunityIds.map(
      (opportunity) => opportunity.user_id
    );

    // Find user data from tblUser and tblVehicle based on the obtained user_ids
    const result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        week_id: weekId,
        auctioneer_id: auctioneerId,
      },
      include: [
        {
          model: db.tblUser,
          attributes: ["user_id", "first_name", "last_name"],
        },
        {
          model: db.tblVehicleRun,
          include: [
            {
              model: db.tblVehicle,
            },
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["auction_id", "name"],
                },
              ],
            },
          ],
        },
      ],
    });

    // return res.json({ data: result });
    /*   const modifiedData = result.map((item) => {
      const redVehicles = item.tblVehicles
        .filter((vehicle) =>
          vehicle.tblVehicleRuns.some((run) => run.condition_light === 1)
        )
        .map((vehicle) => {
          const run = vehicle.tblVehicleRuns[0];
          const lane_details = run.tblAuctionLane || {};

          return {
            vin: vehicle.get("vin"),
            year: vehicle.get("year"),
            make: vehicle.get("make"),
            model: vehicle.get("model"),
            mileage: vehicle.get("mileage"),
            trim: vehicle.get("trim"),
            imageUrl: vehicle.get("imageUrl"),
            condition_light: run.condition_light,
            reserve: run.reserve,
            announcements: run.announcements,
            sale_price: run.sale_price,
            sale_status: run.sale_status,
            auction_fee: run.auction_fee,
            lane_id: run.tblAuctionLane ? run.tblAuctionLane.lane_id : null,
            lane_name: run.tblAuctionLane ? run.tblAuctionLane.name : null,
            auction_name: run.tblAuctionLane
              ? run.tblAuctionLane.tblAuction.name
              : null,
          };
        });

      const yellowVehicles = item.tblVehicles
        .filter((vehicle) =>
          vehicle.tblVehicleRuns.some((run) => run.condition_light === 2)
        )
        .map((vehicle) => {
          const run = vehicle.tblVehicleRuns[0];
          const lane_details = run.tblAuctionLane || {};

          return {
            vin: vehicle.get("vin"),
            year: vehicle.get("year"),
            make: vehicle.get("make"),
            model: vehicle.get("model"),
            mileage: vehicle.get("mileage"),
            trim: vehicle.get("trim"),
            imageUrl: vehicle.get("imageUrl"),
            condition_light: run.condition_light,
            reserve: run.reserve,
            announcements: run.announcements,
            sale_price: run.sale_price,
            sale_status: run.sale_status,
            auction_fee: run.auction_fee,
            lane_id: run.tblAuctionLane ? run.tblAuctionLane.lane_id : null,
            lane_name: run.tblAuctionLane ? run.tblAuctionLane.name : null,
            auction_name: run.tblAuctionLane
              ? run.tblAuctionLane.tblAuction.name
              : null,
          };
        });

      const greenVehicles = item.tblVehicles
        .filter((vehicle) =>
          vehicle.tblVehicleRuns.some((run) => run.condition_light === 3)
        )
        .map((vehicle) => {
          const run = vehicle.tblVehicleRuns[0];

          const lane_details = run.tblAuctionLane || {};

          return {
            vin: vehicle.get("vin"),
            year: vehicle.get("year"),
            make: vehicle.get("make"),
            model: vehicle.get("model"),
            mileage: vehicle.get("mileage"),
            trim: vehicle.get("trim"),
            imageUrl: vehicle.get("imageUrl"),
            condition_light: run.condition_light,
            reserve: run.reserve,
            announcements: run.announcements,
            sale_price: run.sale_price,
            sale_status: run.sale_status,
            auction_fee: run.auction_fee,
            lane_id: run.tblAuctionLane ? run.tblAuctionLane.lane_id : null,
            lane_name: run.tblAuctionLane ? run.tblAuctionLane.name : null,
            auction_name: run.tblAuctionLane
              ? run.tblAuctionLane.tblAuction.name
              : null,
          };
        });

      return {
        user_id: item.get("user_id"),
        first_name: item.get("first_name"),
        last_name: item.get("last_name"),
        red_vehicles: redVehicles,
        yellow_vehicles: yellowVehicles,
        green_vehicles: greenVehicles,
      };
    }); */

    const modifiedData = result.map((opportunity) => {
      const { tblUser, tblVehicleRuns } = opportunity;

      // Helper function to get vehicles based on condition light
      const getVehiclesByConditionLight = (conditionLightValue) =>
        tblVehicleRuns
          .filter((run) => run.condition_light === conditionLightValue)
          .map((run) => {
            const { tblVehicle, tblAuctionLane } = run;

            return {
              vin: tblVehicle.vin,
              year: tblVehicle.year,
              make: tblVehicle.make,
              model: tblVehicle.model,
              mileage: tblVehicle.mileage,
              trim: tblVehicle.trim,
              imageUrl: tblVehicle.imageUrl,
              condition_light: run.condition_light,
              reserve: run.reserve,
              announcements: run.announcements,
              sale_price: run.sale_price,
              sale_status: run.sale_status,
              auction_fee: run.vehicle_total_fee,
              lane_id: tblAuctionLane ? tblAuctionLane.lane_id : null,
              lane_name: tblAuctionLane ? tblAuctionLane.name : null,
              auction_name:
                tblAuctionLane && tblAuctionLane.tblAuction
                  ? tblAuctionLane.tblAuction.name
                  : null,
            };
          });

      // Use the helper function for different condition lights
      const redVehicles = getVehiclesByConditionLight(1); // Red condition light vehicles
      const yellowVehicles = getVehiclesByConditionLight(2); // Yellow condition light vehicles
      const greenVehicles = getVehiclesByConditionLight(3); // Green condition light vehicles

      return {
        user_id: tblUser.user_id,
        first_name: tblUser.first_name,
        last_name: tblUser.last_name,
        red_vehicles: redVehicles,
        yellow_vehicles: yellowVehicles,
        green_vehicles: greenVehicles,
      };
    });

    return res.json({
      status: 200,
      message: "Success",
      data: modifiedData,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const auctioneerTotalSaleAndNetProceed = async (req, res) => {
  try {
    let { auctioneer_id } = req.body;
    const in_auctioneer_id = auctioneer_id;
    let timeRange;
    if (!req.body.timeRange) {
      timeRange = "currentweek";
    } else {
      timeRange = req.body.timeRange;
    }
    timeRange = timeRange.replace(/\s/g, "");
    timeRange = timeRange.toLowerCase();

    const weekRange = calculateDateRange(timeRange);

    const start_date = weekRange.startDate;
    const end_date = weekRange.endDate;

    let [result] = await db.sequelize.query(
      "CALL AuctioneerStats(:auctioneer_id,:start_date,:end_date)",
      {
        replacements: { auctioneer_id, start_date, end_date },
      }
    );
    if (!result) {
      return res.json({
        status: 200,
        message: "success",
        data: {
          sold_units: 0,
          total_sales: 0,
          net_proceeds: 0,
        },
      });
    }
    return res.json({
      status: 200,
      message: "success",
      data: {
        sold_units: result.sold_units || 0,
        total_sales: result.total_sales || 0,
        net_proceeds: result.net_proceeds || 0,
      },
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

module.exports = {
  auctioneerLogin,
  getAuctioneerProfile,
  removeAuctioneer,
  updateAuctioneerPassword,
  GetAuctioneerUsers,
  updateVehicleStatus,
  updateAuctioneerProfile,
  getAllAssignedVehicles,
  sortAuctioneerVehicles,
  filterByConditionLight,
  filterBySaleStatus,
  GetVehicleCountBySaleStatus,
  GetVehicleCountByConditionLight,
  GetAuctioneerUsersOnly,
  getAllAssignedVehiclesOnly,
  filterByAuctioneerAuctions,
  auctioneerTotalSaleAndNetProceed,
  getConditionLightVehicles,
  getSaleStatusVehicles,
  GetVehicleCountByAuction,
};

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists