/
home
/
infinitibizsol
/
autocrm.infinitibizsol.com
/
controllers
/
File Upload :
llllll
Current File: /home/infinitibizsol/autocrm.infinitibizsol.com/controllers/auctioneerController.js
const jwt = require("jsonwebtoken"); const bcrypt = require("bcrypt"); const db = require("../models"); const { Op } = require("sequelize"); const { col } = require("sequelize"); const { generateResetPasswordPlainTextEmail, generateResetPasswordHtmlEmail, generatePlainTextEmail, generateHtmlEmail, } = require("../constants/emailTemplate"); const crypto = require("crypto"); const nodemailer = require("nodemailer"); const { deleteImageFromLocal, } = require("../controllers/imageUploadController"); 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; } } function getTokenExpiration(token) { try { const decodedToken = jwt.decode(token); if (decodedToken && decodedToken.exp) { const expirationDate = decodedToken.exp * 1000; return expirationDate; } else { throw new NotFoundError("No expiration time found in token."); } } catch (error) { throw new CustomAPIError(error.message); } } const auctioneerLogin = async (req, res) => { try { let { business_email, password } = req.body; // Convert email to lowercase business_email = business_email?.toLowerCase(); let result = await db.tblAuctioneer.findOne({ where: { business_email: business_email, }, }); if (!result) { return res .status(404) .json({ status: 404, message: "Invalid credentials" }); } const isMatched = await bcrypt.compare(password, result.password); if (!isMatched) { return res .status(403) .json({ status: 403, message: "Invalid credentials" }); } let token = await jwt.sign( { business_email: result.business_email, auctioneer_id: result.auctioneer_id, }, process.env.JWT_KEY, { expiresIn: "12h" } ); const expirationTime = getTokenExpiration(token); const { resetPasswordToken, password: newPassword, resetPasswordExpires, ...formattedData } = result.dataValues; return res.json({ status: 200, message: "Success", data: [ { expirationTime, token, ...formattedData, }, ], }); } catch (error) { return res.status(500).json({ status: 500, message: "Internal Server Error", error: error.message, }); } }; const signupController = async (req, res) => { try { let { business_email, password } = req.body; // Convert email to lowercase business_email = business_email.toLowerCase(); const salt = await bcrypt.genSalt(10); const hashedPassword = await bcrypt.hash(password, salt); // Check if email already exists in the database let result = await db.tblAuctioneer.findAll({ where: { business_email: business_email }, }); if (result.length > 0) { throw new BadRequestError("The email address is already in use!"); } // Create a new user with the hashed password and lowercase email result = await db.tblAuctioneer.create({ ...req.body, password: hashedPassword, business_email: business_email, // Make sure email is stored as lowercase }); let token = await jwt.sign( { business_email: result.business_email, user_id: result.user_id }, process.env.JWT_KEY, { expiresIn: "12h" } ); const expirationTime = getTokenExpiration(token); const { resetPasswordToken, password: newPassword, resetPasswordExpires, createdAt, updatedAt, ...formattedData } = result.dataValues; return sendJsonResponse(res, 200, "success", [ { expirationTime, token, ...formattedData }, ]); } catch (error) { return throwException(res, error.statusCode, error.message); } }; const validPassword = (password, storedHash) => { return bcrypt.compareSync(password, storedHash); }; function getTranperter() { const transporter = nodemailer.createTransport({ host: process.env.MAIL_SERVER_HOST, // Replace with your mail server host from cPanel port: 465, // Secure SMTP port number provided by your hosting (commonly 465 or 587) secure: true, // True for 465, false for other ports auth: { user: process.env.EMAIL_USERNAME, // The email account you created in cPanel pass: process.env.EMAIL_PASSWORD, // Email account password }, }); return transporter; } // Helper functions for password hashing const generateHash = (password) => { return bcrypt.hashSync(password, bcrypt.genSaltSync(8), null); }; const getAuctioneerProfile = async (req, res) => { const auctioneer_id = req.params.id; try { let result = await db.tblAuctioneer.findOne({ where: { auctioneer_id: auctioneer_id, }, }); if (!result) { return res.status(401).json({ status: 401, message: "No auctioneer 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 removeAuctioneer = async (req, res) => { const { business_email } = req.body; let transaction; try { transaction = await db.sequelize.transaction(); // Start a new transaction const auctioneer = await db.tblAuctioneer.findOne({ where: { business_email }, transaction, }); if (!auctioneer) { await transaction.rollback(); // Ensure transaction is rolled back if auctioneer does not exist return res .status(401) .json({ status: 401, 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, old_password, newPassword } = req.body; if (!auctioneer_id || !old_password || !newPassword) { return res.status(400).json({ status: 400, message: "Please enter all required fields.", }); } const auctioneer = await db.tblAuctioneer.findOne({ where: { auctioneer_id: auctioneer_id }, }); if (!auctioneer) { return res.json({ status: 401, message: "Auctioneer not found.", }); } const isMatched = await bcrypt.compare(old_password, auctioneer.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.tblAuctioneer.update( { password: hashedPassword }, { where: { auctioneer_id: auctioneer_id } } ); return res .status(200) .json({ status: 200, message: "Password updated successfully." }); } 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", "firstname", "lastname", "business_name", "business_logo"], }, { 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, firstname: item.tblUser.firstname, lastname: item.tblUser.lastname, business_name: item.tblUser.business_name, business_logo: item.tblUser.business_logo, 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_proceeds: vehicleRun.net_proceeds || 0, 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", "firstname", "lastname", [ 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) => { let { auctioneer_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.tblAuctioneer.update(data, { where: { auctioneer_id: req.body.auctioneer_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 updateAuctioneerBusinessLogo = async (req, res) => { try { const { auctioneer_id } = req.user; if (req.file) { req.body.business_logo = req.file?.filename; const { business_logo } = await db.tblAuctioneer.findOne({ attributes: ["business_logo"], where: { auctioneer_id: auctioneer_id, }, }); if(business_logo){ const isLogoDeleted = await deleteImageFromLocal(business_logo); if (isLogoDeleted) { console.log("Logo deleted from local server..."); } } } let [result] = await db.tblAuctioneer.update(req.body, { where: { auctioneer_id: auctioneer_id, }, }); let businessLogo; if (result > 0) { const user = await db.tblAuctioneer.findOne({ attributes: ["business_logo"], // Select only the business_logo attribute where: { auctioneer_id: auctioneer_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({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, }); } }; function getOrder(reqBody) { const { sortBy = "vehicle_id", orderDirection = "ASC" } = reqBody; const order = sortBy === "name" ? [ [db.tblVehicleRun, db.tblVehicle, "make", orderDirection], [db.tblVehicleRun, db.tblVehicle, "model", orderDirection], [db.tblVehicleRun, db.tblVehicle, "trim", orderDirection], ] : [[db.tblVehicleRun, db.tblVehicle, sortBy, orderDirection]]; return order; } const getAllAssignedVehiclesOnly = 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(); let order = getOrder(req.body); 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: order }); // 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_proceeds: run.net_proceeds || 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", "firstname", "lastname"], 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, firstname: user.firstname, lastname: user.lastname, 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 } = req.body; let order = getOrder(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: order }); 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_proceeds: vehicleRun?.net_proceeds || 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} = req.body; let order = getOrder(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: order }); // 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_proceeds: vehicleRun?.net_proceeds || 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 }, } ); let [unCatogrizedResult] = await db.sequelize.query( "CALL aAucUncatUnitCount(:auctioneer_id, :week_id)", { replacements: { auctioneer_id, week_id }, } ); if (!unCatogrizedResult) { unCatogrizedResult = { auction_id: 0, auction_name: "Not Provided", units: 0, }; } results.push(unCatogrizedResult); // 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", "firstname", "lastname"], }, { 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, firstname: item.tblUser.firstname, lastname: item.tblUser.lastname, 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", "firstname", "lastname"], }, { model: db.tblVehicleRun, include: [ { model: db.tblVehicle, }, { model: db.tblAuctionLane, attributes: ["lane_id", "name"], include: [ { model: db.tblAuction, attributes: ["auction_id", "name"], }, ], }, ], }, ], }); 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, firstname: tblUser.firstname, lastname: tblUser.lastname, 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, }); } }; const forgotPassword = async (req, res) => { let { business_email } = req.body; business_email = business_email?.toLowerCase(); let transporter; if (!transporter) { try { transporter = getTranperter(); } catch (error) { return res.status(500).json({ status: 500, message: "Failed to send email due to internal error", }); } } try { const user = await db.tblAuctioneer.findOne({ where: { business_email: business_email }, }); if (!user) { return res.status(400).json({ status: 400, error: "No account with that email address exists.", }); } // Generate token const token = crypto.randomBytes(20).toString("hex"); const tokenExpier = new Date(); tokenExpier.setMinutes(tokenExpier.getMinutes() + 15); //expires within 15 minutes user.resetPasswordToken = token; // user.resetPasswordExpires = Date.now() + 3600000; // 1 hour user.resetPasswordExpires = tokenExpier; // 15 mins await user.save(); const emailContentPlainText = generateResetPasswordPlainTextEmail( token, "password" ); const emailContentHtml = generateResetPasswordHtmlEmail(token, "password"); const mailOptions = { to: user.business_email, from: process.env.EMAIL_USERNAME, subject: "Password Reset Confirmation", text: emailContentPlainText, html: emailContentHtml, }; transporter.sendMail(mailOptions, (error, info) => { if (error) { return res.status(500).send(error); } transporter.close(); }); res.json({ status: 200, message: "success", data: { notification: `An e-mail has been sent to ${user.business_email} with further instructions.`, token: token, }, }); } catch (error) { return res.status(500).send(error.message); } }; const resetPasswordViaToken = async (req, res) => { const { token, newPassword } = req.body; try { const user = await db.tblAuctioneer.findOne({ where: { resetPasswordToken: token, resetPasswordExpires: { [Op.gt]: Date.now() }, }, }); if (!user) { return res.status(400).json({ status: 400, error: "Password reset token is invalid or has expired.", }); } user.password = generateHash(newPassword); user.resetPasswordToken = null; user.resetPasswordExpires = null; await user.save(); res.status(200).json({ status: 200, message: "Success! Your password has been changed.", }); } catch (error) { res.status(500).send(error.message); } }; const validateOTPOrToken = async (req, res) => { const { token } = req.body; try { const user = await db.tblAuctioneer.findOne({ where: { resetPasswordToken: token, resetPasswordExpires: { [Op.gt]: Date.now() }, }, }); if (!user) { return res.status(400).json({ status: 400, error: "OTP is invalid or has expired.", }); } return res.status(200).json({ status: 200, message: "Success! valid OTP.", }); } catch (error) { res.status(500).send(error.message); } }; // function transformByWholesaler(data) { // return data.map((item) => ({ // auctioneer_business_name: item.tblAuctioneer.business_name, // wholesaler_business_name: item.tblUser.business_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, // 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_proceeds: vehicleRun.net_proceeds || null, // sale_status: vehicleRun.sale_status, // run_no: vehicleRun.run_no, // lane_id: auctionLane.lane_id, // lane_name: auctionLane.name, // auction_name: auction.name, // }; // }), // })); // } function transformByWholesaler(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 exportByWholeSaler = async (req, res) => { try { let { timeRange = "currentweek", auctioneerId, weekId, sortBy, orderDirection, } = req.body; const result = await db.tblOpportunity.findAll({ attributes: ["opportunity_id"], where: { week_id: weekId, auctioneer_id: auctioneerId, }, 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 = transformByWholesaler(result); return res.status(200).json({ status: 200, message: "Success", filter_type: "whole_saler", 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, auctioneer_business_name: opportunity.tblAuctioneer.business_name, auction_name: auction.name, tblVehicles: [ { wholesaler_business_name: opportunity.tblUser.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 { const obj = { firstname: null, lastname: null, business_name: null, }; let { timeRange = "currentweek", auctioneerId, weekId, sortBy, orderDirection, } = req.body; let auctioneer_id = auctioneerId; let week_id = weekId; let combinedData; const result = await db.tblOpportunity.findAll({ attributes: ["opportunity_id"], where: { week_id: weekId, auctioneer_id: auctioneerId, }, 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: [], }); } const convertedData = transformByAuctions(result); // return res.json(convertedData); let notProvidedResult = await db.sequelize.query( "CALL aGetAucUncatUnits(:auctioneer_id,:week_id)", { replacements: { auctioneer_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",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, auctioneer_business_name: opportunity.tblAuctioneer.business_name, condition_light: vehicleRun.condition_light, tblVehicles: [ { wholesaler_business_name: opportunity.tblUser.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, 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", auctioneerId, weekId, sortBy, orderDirection, } = req.body; const result = await db.tblOpportunity.findAll({ attributes: ["opportunity_id"], where: { week_id: weekId, auctioneer_id: auctioneerId, }, 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(formattedData); const formattedData = transformByConditionLight(result); return res.status(200).json({ status: 200, message: "Success",data:formattedData }); } catch (error) { return res.status(500).json({ status: 500, error: "Internal Server Error", message: error.message, }); } }; // function transformBySaleStatus(originalArray) { // let result = []; // originalArray.forEach((opportunity) => { // let auctioneerBusinessName = opportunity.tblAuctioneer.business_name; // let userBusinessName = opportunity.tblUser.business_name; // // Grouping vehicles by sale_status within the same opportunity // let saleGroupedVehicles = opportunity.tblVehicleRuns.reduce( // (grouped, run) => { // const auctionLane = run.tblAuctionLane || { // lane_id: null, // name: null, // tblAuction: { // auction_id: null, // name: null, // }, // }; // const auction = auctionLane.tblAuction; // // Create a new group if one does not exist for this sale_status // if (!grouped[run.sale_status]) { // grouped[run.sale_status] = { // opportunity_id: opportunity.opportunity_id, // auctioneer_business_name: auctioneerBusinessName, // sale_status: run.sale_status, // tblVehicles: [ // { // wholesaler_business_name: userBusinessName, // vehicles: [], // }, // ], // }; // } // // Add vehicle data to the correct group // let 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, // }; // grouped[run.sale_status].tblVehicles[0].vehicles.push(vehicleData); // return grouped; // }, // {} // ); // // Push the values of the saleGroupedVehicles object into the result array // Object.values(saleGroupedVehicles).forEach((group) => result.push(group)); // }); // return result; // } 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, auctioneer_business_name: auctioneerBusinessName, sale_status: true, tblVehicles: [ { wholesaler_business_name: opportunity.tblUser.business_name, vehicles: [], }, ], }, false: { opportunity_id: opportunity.opportunity_id, auctioneer_business_name: auctioneerBusinessName, sale_status: false, tblVehicles: [ { wholesaler_business_name: opportunity.tblUser.business_name, 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", auctioneerId, weekId, sortBy, orderDirection, } = req.body; const result = await db.tblOpportunity.findAll({ attributes: ["opportunity_id"], where: { week_id: weekId, auctioneer_id: auctioneerId, }, 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", data: transformedData }); } catch (error) { return res.status(500).json({ status: 500, error: "Internal Server Error", message: error.message, }); } }; module.exports = { auctioneerLogin, signupController, getAuctioneerProfile, removeAuctioneer, updateAuctioneerPassword, GetAuctioneerUsers, updateVehicleStatus, updateAuctioneerProfile, updateAuctioneerBusinessLogo, getAllAssignedVehicles, sortAuctioneerVehicles, filterByConditionLight, filterBySaleStatus, GetVehicleCountBySaleStatus, GetVehicleCountByConditionLight, GetAuctioneerUsersOnly, getAllAssignedVehiclesOnly, filterByAuctioneerAuctions, auctioneerTotalSaleAndNetProceed, getConditionLightVehicles, getSaleStatusVehicles, GetVehicleCountByAuction, forgotPassword, resetPasswordViaToken, validateOTPOrToken, exportByWholeSaler, exportByAuctions, exportByConditionLight, exportBySaleStatus, };
Copyright ©2k19 -
Hexid
|
Tex7ure