Sindbad~EG File Manager

Current Path : /home/infinitibizsol/autocrm.infinitibizsol.com/controllers/
Upload File :
Current File : /home/infinitibizsol/autocrm.infinitibizsol.com/controllers/userController.js

const { Op, INTEGER, col } = require("sequelize");
const db = require("../models");
const bcrypt = require("bcrypt");

const {
  deleteImageFromLocal,
} = require("../controllers/imageUploadController");


const updateUserProfile = async (req, res) => {
  let { user_id, ...data } = req.body;
  data.business_email=data.business_email?.toLowerCase();
  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.tblUser.update(data, {
      where: {
        user_id: user_id,
      },
    });


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

const updateUserBusinessLogo = async (req, res) => {
  
  try {
      const { user_id } = req.user;
  
  if (req.file) {
    req.body.business_logo = req.file?.filename;
    const { business_logo } = await db.tblUser.findOne({
      attributes: ["business_logo"],
      where: {
        user_id: user_id,
      },
    });
    if(business_logo){
    const isLogoDeleted = await deleteImageFromLocal(business_logo);
    if (isLogoDeleted) {
      console.log("Logo deleted from local server...");
    }
    }
  }
    let [result] = await db.tblUser.update(req.body, {
      where: {
        user_id: user_id,
      },
    });
    
     let businessLogo;
    if (result > 0) {
      const user = await db.tblUser.findOne({
        attributes: ["business_logo"], // Select only the business_logo attribute
        where: {
          user_id: user_id,
        },
      });

      // Access the business_logo from the user instance
      businessLogo = user ? user.business_logo : null;
    }
  
    return res.json({
      status: 200,
      business_logo: businessLogo
    });
  } catch (error) {
      return res.status(500).json({
      status: 500,
      message: "Internal Server Error",
      error: error.message,
    });
  }
};

const updateUserPassword = async (req, res) => {
  try {
    let { user_id, old_password, newPassword } = req.body;

    if (!user_id || !old_password || !newPassword) {
      return res.json({
        status: 400,
        message: "Please enter all required fields.",
      });
    }

    const user = await db.tblUser.findOne({ where: { user_id: user_id } });
    if (!user) {
      return res.json({
        status: 401,
        message: "User not found.",
      });
    }
    const isMatched = await bcrypt.compare(old_password, user.password);
    if (!isMatched) {
      return res.status(409).json({
        status: 409,
        message: "Please enter correct old password",
      });
      
    }
    const salt = await bcrypt.genSalt(10);
    const hashedPassword = await bcrypt.hash(newPassword, salt);
    let result = await db.tblUser.update(
      { password: hashedPassword },
      { where: { user_id: user_id } }
    );

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

const getUserProfile = async (req, res) => {
  const user_id = req.params.id;

  try {
    let result = await db.tblUser.findOne({
      where: {
        user_id: user_id,
      },
    });
    if (!result) {
      return res.json({ status: 402, message: "No user Found" });
    }

    const {
      resetPasswordToken,
      password,
      resetPasswordExpires,
      ...formattedData
    } = result.dataValues;

    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 removeUser = async (req, res) => {
  const { email } = req.body;

  let transaction;

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

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

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

    const opportunities = await db.tblOpportunity.findAll({
      where: { user_id: user.user_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 vehicle_run_deleted_count = await db.tblVehicleRun.destroy({
      where: { opportunity_id: opportunity_ids },
      transaction,
    });

    const vehicle_deleted_count = await db.tblVehicle.destroy({
      where: { user_id: user.user_id },
      transaction,
    });

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

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

    const user_deleted_count = await db.tblUser.destroy({
      where: { user_id: user.user_id },
      transaction,
    });

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

    return res.status(200).json({
      message: "User and related data successfully deleted.",
      details: {
        vehicle_runs: vehicle_run_deleted_count,
        vehicle_runs_fee: vehicle_run_fee_deleted_count,
        vehicle: vehicle_deleted_count,
        opportunities: opportunity_deleted_count,
        subscriptions: subscription_deleted_count,
        user: user_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,
    });
  }
};

function getOrder(reqBody) {
  const { sortBy = "vehicle_id", orderDirection = "ASC" } = reqBody;

  const order =
    sortBy === "name"
      ? [
          ["make", orderDirection],
          ["model", orderDirection],
          ["trim", orderDirection],
        ]
      : [[sortBy, orderDirection]];

  return order;
}


const getAllAssignedVehicles = async (req, res) => {
  try {
    const { opportunity_id, user_id } = req.body;
    // Adjust the where clause based on sortBy
   let order = getOrder(req.body);
   
    const result = await db.tblVehicle.findAll({
      attributes: [
        "vehicle_id",
        "vin",
        "year",
        "make",
        "model",
        "mileage",
        "trim",
        "color",
        "color_name",
        "imageUrl",
      ],
      include: [
        {
          model: db.tblVehicleRun,
          where: {
            opportunity_id: opportunity_id,
          },
          attributes: ["condition_light", "run_no", "sale_status", "lane_id"],
          include: [
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              // as: "lane_details",
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["name"],
                  // as: "auction_details",
                },
              ],
            },
          ],
        },
      ],
      where: {
        user_id: user_id,
      },

      order: order,
    });
    // return res.json({ data: result });
    const formattedResult = result.map((item) => {
      const vehicleRun = item.tblVehicleRuns[0] || {};
      const lane = vehicleRun.tblAuctionLane || {};
      const auction = lane.tblAuction || {};
      return {
        vehicle_id: item.vehicle_id,
        year: item.year,
        make: item.make,
        model: item.model,
        vin: item.vin,
        color: item.color,
        color_name: item.color_name,
        mileage: item.mileage,
        trim: item.trim,
        imageUrl: item.imageUrl,
        condition_light: vehicleRun?.condition_light || 4,
        sale_status: vehicleRun?.sale_status || false,
        lane_id: vehicleRun?.lane_id || null,
        run_no: vehicleRun?.run_no || null,
        lane_name: lane?.name || 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 getAuctioneerName = async (opportunity_id) => {
  const opportunity = await db.tblOpportunity.findOne({
    attributes: [],
    include: [
      {
        model: db.tblAuctioneer,
        attributes: ["firstname"],
      },
    ],
    where: { opportunity_id },
  });

  if (opportunity && opportunity.tblAuctioneer) {
    return opportunity.tblAuctioneer.firstname;
  } else {
    return null;
  }
};

const getSelectedDate = async (opportunity_id) => {
  const opportunity = await db.tblOpportunity.findOne({
    attributes: ["date"],
    where: { opportunity_id },
  });

  if (opportunity) {
    return opportunity.date;
  } else {
    return null;
  }
};

const getWeekId = async (opportunity_id) => {
  const opportunity = await db.tblOpportunity.findOne({
    attributes: ["week_id"],
    where: { opportunity_id },
  });

  if (opportunity) {
    return opportunity.week_id;
  } else {
    return null;
  }
};

const getAllVehiclesWithStatus = async (req, res) => {
  try {
    const { user_id, sortBy = "vehicle_id", orderDirection = "ASC" } = req.body;
    const vehicles = await db.tblVehicle.findAll({
      attributes: [
        "vehicle_id",
        "year",
        "make",
        "model",
        "trim",
        "vin",
        "mileage",
        "color",
        "color_name",
        "details",
        "imageUrl",
        [db.sequelize.col("tblVehicleRuns.opportunity_id"), "opportunity_id"],
      ],
      where: { user_id },
      include: [
        {
          model: db.tblVehicleRun,
          // attributes: ["condition_light", "opportunity_id"], // Include opportunity_id here
          include: [
            {
              model: db.tblOpportunity,
              attributes: ["week_id", "date"],
              include: [
                {
                  model: db.tblAuctioneer,
                  attributes: ["firstname"],
                },
              ],
            },
          ],
        },
      ],
      order: [[sortBy, orderDirection]],
    });

    // return res.json(vehicles);
    let resultTableAdminUsers = await db.tblOpportunity.findAll({});
    const adminIdsInUsers = new Set(
      resultTableAdminUsers.map((item) => item.opportunity_id)
    );

    const formattedVehicles = vehicles.map((vehicle) => {
      const run = vehicle.tblVehicleRuns[0] || {};
      const opportunity = run.tblOpportunity || {};
      const auctioneer = opportunity.tblAuctioneer || {};
      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,
        /*  condition_light: run.condition_light || 0,
        announcements: run.announcements || null,
        reserve: run.reserve || 0,
        sale_price: run.sale_price || 0,
        vehicle_total_fee: run.vehicle_total_fee || 0,
        net_proceed: run.net_proceed || 0,
        run_no: run.run_no || 0,
        sale_status: run.sale_status || false,
        lane_id: run.lane_id || null, */
        status: adminIdsInUsers.has(vehicle.get().opportunity_id) || false,
        weekId: opportunity.week_id || null,
        auctioneer_name: auctioneer.firstname || null,
        selected_date: opportunity.date || null,
      };
    });

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

const userAddedAuctioneerListById = async (req, res) => {
  try {
    const { userId, weekId } = req.body;
    const result = await db.tblOpportunity.findAll({
      attributes: [
        "opportunity_id",
        [
          db.sequelize.fn(
            "COALESCE",
            db.sequelize.fn(
              "COUNT",
              db.sequelize.literal("tblVehicleRuns.opportunity_id")
            ),
            0
          ),
          "units",
        ],
      ],
      include: [
        {
          model: db.tblAuctioneer,
          attributes: ["firstname", "business_name", "auctioneer_id",  "business_logo"],
        },
        {
          model: db.tblVehicleRun,
          attributes: [],
          required: false, // Use LEFT JOIN to include opportunities without matching vehicles
        },
      ],
      where: {
        user_id: userId,
        week_id: parseInt(weekId),
      },
      group: ["tblOpportunity.opportunity_id", "tblAuctioneer.auctioneer_id"],
    });

    // Format the result as needed
    const formattedResult = result.map((item) => {
      return {
        opportunity_id: item.dataValues.opportunity_id,
        units: parseInt(item.dataValues.units) || 0, // Use COALESCE to return 0 if units is falsy
        auctioneer_id: item.tblAuctioneer.auctioneer_id,
        business_name: item.tblAuctioneer.business_name,
        business_logo: item.tblAuctioneer.business_logo||null,
      };
    });

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

const getAllAuctioneerList = async (req, res) => {
  try {
    const { weekId } = req.body;
    let resultTableAdmin = await db.tblAuctioneer.findAll();

    let resultTableAdminUsers = await db.tblOpportunity.findAll({
      where: {
        week_id: weekId,
      },
    });
    const adminIdsInUsers = new Set(
      resultTableAdminUsers.map((item) => item.auctioneer_id)
    );

    resultTableAdmin = resultTableAdmin.map((item) => item.get());

    const data = resultTableAdmin.map((item) => ({
      ...item,
      status: adminIdsInUsers.has(item.auctioneer_id),

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

const getAllSubscribedAuctioneerList = async (req, res) => {
  try {
    const { userId } = req.body;
    let resultTableAdmin = await db.tblAuctioneer.findAll();

    let resultTableAdminUsers = await db.tblUserSubAuctioneer.findAll({
      where: {
        user_id: userId,
      },
    });
    const adminIdsInUsers = new Set(
      resultTableAdminUsers.map((item) => item.auctioneer_id)
    );

    resultTableAdmin = resultTableAdmin.map((item) => item.get());

    const data = resultTableAdmin.map((item) => ({
      ...item,
      status: adminIdsInUsers.has(item.auctioneer_id),

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

const addUserAuctioneerToOpportunity = async (req, res) => {
  try {
    const { userId, auctioneer_ids, weekId, date } = req.body;
    let result;
    const promises = auctioneer_ids.map(async (item) => {
      try {
        result = await db.tblOpportunity.create({
          user_id: userId,
          auctioneer_id: item,
          week_id: weekId,
          date: date,
        });
      } catch (error) {
        console.error(error);
        return res
          .status(500)
          .json({ status: 500, message: "Internal Server Error" });
      }
    });

    await Promise.all(promises);

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

const removeUserAuctioneer = async (req, res) => {
  try {
    const { auctioneer_ids, weekId, user_id } = req.body;
    let result;
    const promises = auctioneer_ids.map(async (item) => {
      const opportunitiesToDelete = await db.tblOpportunity.findAll({
        attributes: ["opportunity_id"], // Select only the id column
        where: {
          [Op.and]: [
            {
              auctioneer_id: item,
            },
            {
              week_id: weekId,
            },
            // If needed, add more conditions
            // { user_id: user_id },
          ],
        },
      });

      opportunitiesToDelete.map(async (item) => {
        await db.tblVehicle.update(
          { lane_id: null },
          { opportunity_id: item.opportunity_id }
        );
      });

      result = await db.tblOpportunity.destroy({
        where: {
          [Op.and]: [
            {
              auctioneer_id: item,
            },
            {
              week_id: weekId,
            },
            // will be added later
            { user_id: user_id },
          ],
        },
      });
    });

    await Promise.all(promises);

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

const removeUserAuctioneerTesting = async (req, res) => {
  try {
    const { auctioneer_ids, weekId, user_id } = req.body;

    const deletePromises = auctioneer_ids.map(async (item) => {
      // Find opportunities to be deleted
      const opportunitiesToDelete = await db.tblOpportunity.findAll({
        attributes: ["opportunity_id"],
        where: {
          auctioneer_id: item,
          week_id: weekId,
          user_id: user_id,
          // If needed, add more conditions
        },
      });

      // Extract opportunity IDs
      const opportunityIds = opportunitiesToDelete.map(
        (opportunity) => opportunity.opportunity_id
      );
      const vehicleRunsResult = await db.tblVehicleRun.findAll({
          attributes:["vehicle_run_id"],
        where: { opportunity_id: opportunityIds },
      });
      const vehicleRunIds = vehicleRunsResult.map((item) => item.vehicle_run_id);
      
      await db.tblVehicleRunFee.destroy({
            where: {
              vehicle_run_id: vehicleRunIds,
            }
          });
          
      await db.tblVehicleRun.destroy({ where: { vehicle_run_id: vehicleRunIds } });

      const deleteResult = await db.tblOpportunity.destroy({
        where: {
          auctioneer_id: item,
          week_id: weekId,
          user_id: user_id,
        },
      });

      return {
        auctioneer_id: item,
        deletedOpportunities: opportunityIds,
        deleteResult,
      };
    });

    const results = await Promise.all(deletePromises);

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


function transformByAuctioneer(data) {
  return data.map((opportunity) => ({
    opportunity_id: opportunity.opportunity_id,
    auctioneer_business_name: opportunity.tblAuctioneer.business_name,
    wholesaler_business_name: opportunity.tblUser.business_name,
    tblVehicles: [
      {
        vehicles: opportunity.tblVehicleRuns.map((run) => {
          const auctionLane = run.tblAuctionLane || {
            lane_id: null,
            name: null,
            tblAuction: {
              auction_id: null,
              name: null,
            },
          };
          const auction = auctionLane.tblAuction;
          return {
            vehicle_run_id: run.vehicle_run_id,
            vehicle_id: run.vehicle_id,
            opportunity_id: run.opportunity_id,
            condition_light: run.condition_light,
            announcements: run.announcements,
            reserve: run.reserve,
            sale_price: run.sale_price,
            vehicle_total_fee: run.vehicle_total_fee,
            net_proceeds: run.net_proceeds,
            sale_status: run.sale_status,
            run_no: run.run_no,
            lane_id: run.lane_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,
            lane_name: auctionLane.name,
            auction_id: auction.auction_id,
            auction_name: auction.name,
          };
        }),
      },
    ],
  }));
}

const exportByAuctioneer = async (req, res) => {
  try {
    let {
      timeRange = "currentweek",
      userId,
      weekId,
      sortBy,
      orderDirection,
    } = req.body;

    const result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        week_id: weekId,
        user_id: userId,
      },
      include: [
        {
          model: db.tblAuctioneer,
          attributes: ["business_name"],
        },
        {
          model: db.tblUser,
          attributes: ["business_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 = transformByAuctioneer(result);

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


function mergeDataLists(convertedData, notProvidedResult) {
  let combinedData = [...convertedData];

  notProvidedResult.forEach((entry) => {
    let existingEntry = combinedData.find(
      (e) =>
        e.opportunity_id === entry.opportunity_id &&
        e.auctioneer_business_name === entry.auctioneer_business_name &&
        (!e.auction_name || e.auction_name === "Not Provided") // Assuming 'Not Provided' is to be matched specifically
    );

    if (!existingEntry) {
      combinedData.push({
        opportunity_id: entry.opportunity_id,
        auctioneer_business_name: entry.auctioneer_business_name,
        auction_name: entry.auction_name ? entry.auction_name : "Not Provided",
        tblVehicles: [
          {
            wholesaler_business_name: entry.wholesaler_business_name,
            vehicles: [entry], // The vehicle object from notProvidedResult can be used directly
          },
        ],
      });
    } else {
      let existingWholesaler = existingEntry.tblVehicles.find(
        (v) => v.wholesaler_business_name === entry.wholesaler_business_name
      );

      if (!existingWholesaler) {
        existingEntry.tblVehicles.push({
          wholesaler_business_name: entry.wholesaler_business_name,
          vehicles: [entry],
        });
      } else {
        existingWholesaler.vehicles.push(entry);
      }
    }
  });

  return combinedData;
}

function transformByAuctions(data) {
  const groupedByConditionLight = {};

  data.forEach((opportunity) => {
    opportunity.tblVehicleRuns.forEach((vehicleRun) => {
      const auctionLane = vehicleRun.tblAuctionLane || {
        lane_id: null,
        name: null,
        tblAuction: {
          auction_id: null,
          name: null,
        },
      };
      const auction = auctionLane.tblAuction;
      if (!groupedByConditionLight[auction.auction_id]) {
        groupedByConditionLight[auction.auction_id] = {
          opportunity_id: opportunity.opportunity_id,
          wholesaler_business_name: opportunity.tblUser.business_name,
          auction_name: auction.name,
          tblVehicles: [
            {
              auctioneer_business_name: opportunity.tblAuctioneer.business_name,
              vehicles: [],
            },
          ],
        };
      }

      groupedByConditionLight[auction.auction_id].tblVehicles[0].vehicles.push({
        vehicle_run_id: vehicleRun.vehicle_run_id,
        vehicle_id: vehicleRun.vehicle_id,
        opportunity_id: vehicleRun.opportunity_id,
        condition_light: vehicleRun.condition_light,
        announcements: vehicleRun.announcements,
        reserve: vehicleRun.reserve,
        sale_price: vehicleRun.sale_price,
        vehicle_total_fee: vehicleRun.vehicle_total_fee,
        net_proceeds: vehicleRun.net_proceeds,
        sale_status: vehicleRun.sale_status,
        run_no: vehicleRun.run_no,
        lane_id: vehicleRun.lane_id,
        vin: vehicleRun.tblVehicle.vin,
        year: vehicleRun.tblVehicle.year,
        make: vehicleRun.tblVehicle.make,
        model: vehicleRun.tblVehicle.model,
        trim: vehicleRun.tblVehicle.trim ? vehicleRun.tblVehicle.trim : null,
        mileage: vehicleRun.tblVehicle.mileage,
        color: vehicleRun.tblVehicle.color,
        color_name: vehicleRun.tblVehicle.color_name,
        details: vehicleRun.tblVehicle.details,
        lane_name: auctionLane.name,
        auction_id: auction.auction_id,
        auction_name: auction.name,
      });
    });
  });

  // Convert the grouped object into an array and sort by condition_light
  return Object.values(groupedByConditionLight).sort(
    (a, b) => a.auction_id - b.auction_id
  );
}

const exportByAuctions = async (req, res) => {
  try {
    let {
      timeRange = "currentweek",
      userId,
      weekId,
      sortBy,
      orderDirection,
    } = req.body;
    const user_id = userId;
    const week_id = weekId;
        let combinedData;
    const result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        week_id: weekId,
        user_id: userId,
      },
      include: [
        {
          model: db.tblAuctioneer,
          attributes: ["firstname", "lastname", "business_name"],
        },
        {
          model: db.tblUser,
          attributes: ["firstname", "lastname", "business_name"],
        },
        {
          model: db.tblVehicleRun,
          include: [
            {
              model: db.tblVehicle,
            },
            {
              model: db.tblAuctionLane,
              attributes: ["lane_id", "name"],
              include: [
                {
                  model: db.tblAuction,
                  attributes: ["auction_id", "name"],
                },
              ],
            },
          ],
          where: {
            lane_id: {
              [Op.not]: null,
            },
          },
        },
      ],
    });

if (result.length <= 0) {
      return res.status(200).json({
        status: 200,
        message: "Success",
        data: [],
      });
    }
    // return res.json(result);

    const convertedData = transformByAuctions(result);

    let notProvidedResult = await db.sequelize.query(
      "CALL uGetAucUncatUnits(:user_id,:week_id)",
      {
        replacements: { user_id, week_id },
      }
    );
    
    if (notProvidedResult.length <= 0) {
      notProvidedResult = {
        opportunity_id: 0,
        auctioneer_business_name: convertedData[0].wholesaler_business_name,
        auction_name: "Not Provided",
        tblVehicles: [
          {
            wholesaler_business_name: "None",
            vehicles: [],
          },
        ],
      };
      convertedData.push(notProvidedResult);
      combinedData = convertedData;
    } else {
      combinedData = mergeDataLists(convertedData, notProvidedResult);
    }
    
    return res.status(200).json({
      status: 200,
      message: "Success",
      filter_type: "auctions",
      data: combinedData,
    });
    
  } catch (error) {
    return res.status(500).json({
      status: 500,
      error: "Internal Server Error",
      message: error.message,
    });
  }
};


function transformByConditionLight(data) {
  const groupedByConditionLight = {};

  data.forEach((opportunity) => {
    opportunity.tblVehicleRuns.forEach((vehicleRun) => {
      const auctionLane = vehicleRun.tblAuctionLane || {
        lane_id: null,
        name: null,
        tblAuction: {
          auction_id: null,
          name: null,
        },
      };
      const auction = auctionLane.tblAuction;
      if (!groupedByConditionLight[vehicleRun.condition_light]) {
        groupedByConditionLight[vehicleRun.condition_light] = {
          opportunity_id: opportunity.opportunity_id,
          wholesaler_business_name: opportunity.tblUser.business_name,
          condition_light: vehicleRun.condition_light,
          tblVehicles: [
            {
              auctioneer_business_name: opportunity.tblAuctioneer.business_name,
              vehicles: [],
            },
          ],
        };
      }

      groupedByConditionLight[
        vehicleRun.condition_light
      ].tblVehicles[0].vehicles.push({
        vehicle_run_id: vehicleRun.vehicle_run_id,
        vehicle_id: vehicleRun.vehicle_id,
        opportunity_id: vehicleRun.opportunity_id,
        condition_light: vehicleRun.condition_light,
        announcements: vehicleRun.announcements,
        reserve: vehicleRun.reserve,
        sale_price: vehicleRun.sale_price,
        vehicle_total_fee: vehicleRun.vehicle_total_fee,
        net_proceeds: vehicleRun.net_proceeds,
        sale_status: vehicleRun.sale_status,
        run_no: vehicleRun.run_no,
        lane_id: vehicleRun.lane_id,
        vin: vehicleRun.tblVehicle.vin,
        year: vehicleRun.tblVehicle.year,
        make: vehicleRun.tblVehicle.make,
        model: vehicleRun.tblVehicle.model,
        trim: vehicleRun.tblVehicle.trim ? vehicleRun.tblVehicle.trim : null,
        mileage: vehicleRun.tblVehicle.mileage,
        color: vehicleRun.tblVehicle.color,
        color_name: vehicleRun.tblVehicle.color_name,
        details: vehicleRun.tblVehicle.details.trim(),
        lane_name: auctionLane.name,
        auction_id: auction.auction_id,
        auction_name: auction.name,
      });
    });
  });

  // Convert the grouped object into an array and sort by condition_light
  return Object.values(groupedByConditionLight).sort(
    (a, b) => a.condition_light - b.condition_light
  );
}

const exportByConditionLight = async (req, res) => {
  try {
    let {
      timeRange = "currentweek",
      userId,
      weekId,
      sortBy,
      orderDirection,
    } = req.body;

    const result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        week_id: weekId,
        user_id: userId,
      },
      include: [
        {
          model: db.tblAuctioneer,
          attributes: ["business_name"],
        },
        {
          model: db.tblUser,
          attributes: ["business_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 transformedData = transformByConditionLight(result);
    return res
      .status(200)
      .json({
        status: 200,
        message: "Success",
        filter_type: "condition_light",
        data: transformedData,
      });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      error: "Internal Server Error",
      message: error.message,
    });
  }
};

function transformBySaleStatus(originalArray) {
  let result = [];

  originalArray.forEach((opportunity) => {
    const auctioneerBusinessName = opportunity.tblAuctioneer.business_name;

    // Initialize empty groups for true and false sale statuses
    const saleGroupedVehicles = {
      true: {
        opportunity_id: opportunity.opportunity_id,
        wholesaler_business_name: opportunity.tblUser.business_name,

        sale_status: true,
        tblVehicles: [
          {
            auctioneer_business_name: auctioneerBusinessName,
            vehicles: [],
          },
        ],
      },
      false: {
        opportunity_id: opportunity.opportunity_id,
        wholesaler_business_name: opportunity.tblUser.business_name,
        sale_status: false,
        tblVehicles: [
          {
            auctioneer_business_name: auctioneerBusinessName,
            vehicles: [],
          },
        ],
      },
    };

    // Populate groups with vehicle data
    opportunity.tblVehicleRuns.forEach((run) => {
      const auctionLane = run.tblAuctionLane || {
        lane_id: null,
        name: null,
        tblAuction: {
          auction_id: null,
          name: null,
        },
      };
      const auction = auctionLane.tblAuction;
      const vehicleData = {
        vehicle_run_id: run.vehicle_run_id,
        vehicle_id: run.vehicle_id,
        opportunity_id: run.opportunity_id,
        condition_light: run.condition_light,
        announcements: run.announcements,
        reserve: run.reserve,
        sale_price: run.sale_price,
        vehicle_total_fee: run.vehicle_total_fee,
        net_proceeds: run.net_proceeds,
        sale_status: run.sale_status,
        run_no: run.run_no,
        lane_id: run.lane_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,
        lane_name: auctionLane.name,
        auction_id: auction.auction_id,
        auction_name: auction.name,
      };
      saleGroupedVehicles[run.sale_status].tblVehicles[0].vehicles.push(
        vehicleData
      );
    });

    // Push both true and false status groups regardless of whether they have data
    Object.values(saleGroupedVehicles).forEach((group) => result.push(group));
  });

  return result;
}

const exportBySaleStatus = async (req, res) => {
  try {
    let {
      timeRange = "currentweek",
      userId,
      weekId,
      sortBy,
      orderDirection,
    } = req.body;

    const result = await db.tblOpportunity.findAll({
      attributes: ["opportunity_id"],
      where: {
        week_id: weekId,
        user_id: userId,
      },
      include: [
        {
          model: db.tblAuctioneer,
          attributes: ["firstname", "lastname", "business_name"],
        },
        {
          model: db.tblUser,
          attributes: ["firstname", "lastname", "business_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 transformedData = transformBySaleStatus(result);
    return res.status(200).json({
      status: 200,
      message: "Success",
      filter_type: "sale_status",
      data: transformedData,
    });
  } catch (error) {
    return res.status(500).json({
      status: 500,
      error: "Internal Server Error",
      message: error.message,
    });
  }
};



module.exports = {
  getUserProfile,
  updateUserBusinessLogo,
  updateUserProfile,
  updateUserPassword,
  removeUser,
  userAddedAuctioneerListById,
  getAllAuctioneerList,
  addUserAuctioneerToOpportunity,
  getAllAssignedVehicles,
  getAllVehiclesWithStatus,
  getAllSubscribedAuctioneerList,
  removeUserAuctioneer,
  removeUserAuctioneerTesting,
  exportByAuctioneer,
  exportByAuctions,
  exportByConditionLight,
  exportBySaleStatus,

};

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