Untitled

mail@pastecode.io avatar
unknown
javascript
7 months ago
14 kB
1
Indexable
Never
import asyncHandler from "express-async-handler";
import User from "../models/userModule.js";
import mongoose from "mongoose";
import Item from "../models/itemModule.js";
import Relation from "../models/BoToCcaRelation.js";
import callCenterAgent from "../models/callCenterAgentModule.js";
import {
  getServiceTypes,
  isValidServiceType,
  updateItemCcaSplit,
  validateItemServiceTypes,
} from "../services/util.js";
import Lead from "../models/leadModule.js";
import dailyRating from "../models/ccaRatingModule.js";

const getAgents = asyncHandler(async (req, res) => {
  if (req.user.type === "CCA") {
    res.status(400);
    throw new Error("invalid user type");
  }
  const agregation = [];
  const page = req.query.page || 0;
  const elementsPerPage = 18;

  const performance = req.query.performance;
  const date = req.query.date;
  const rating = req.query.rating;
  let sortObj = {
    $sort: {},
  };
  let matchOBJ = {
    $match: {
      type: "CCA",
      status: "Active",
    },
  };
  agregation.push({
    $lookup: {
      from: "callcenteragents",
      localField: "profile",
      foreignField: "_id",
      as: "ccaData",
    },
  });

  agregation.push({
    $unwind: "$ccaData",
  });

  if (typeof rating === "string") {
    let minVal = -1;
    let maxVal = -1;
    switch (rating) {
      case "1":
        minVal = 3;
        maxVal = 3.5;
        break;
      case "2":
        minVal = 3.5;
        maxVal = 4;
        break;
      case "3":
        minVal = 4;
        maxVal = 4.5;
        break;
      case "4":
        minVal = 4.5;
        maxVal = 5;
        break;
    }
    if (minVal !== -1 && maxVal !== -1) {
      matchOBJ.$match = {
        ...matchOBJ.$match,
        "ccaData.globalReview": { $gte: minVal, $lte: maxVal },
      };
    }
  }
  if (typeof performance === "string") {
    let minVal = 0;
    let maxVal = 0;
    switch (performance) {
      case "1":
        minVal = 40;
        maxVal = 60;
        break;
      case "2":
        minVal = 60;
        maxVal = 80;
        break;
      case "3":
        minVal = 80;
        maxVal = 100;
        break;
    }
    if (minVal !== 0 && maxVal !== 0) {
      matchOBJ.$match = {
        ...matchOBJ.$match,
        "ccaData.performance": { $gte: minVal, $lte: maxVal },
      };
    }
  }
  agregation.push(matchOBJ);

  const count = await User.countDocuments({ type: "CCA" });

  if (typeof date === "string" && (date === "OLD" || date === "NEW")) {
    sortObj.$sort = { ...sortObj.$sort, creationDate: date === "OLD" ? 1 : -1 };
    agregation.push(sortObj);
  }

  agregation.push({
    $skip: page * elementsPerPage,
  });

  agregation.push({
    $limit: elementsPerPage,
  });

  agregation.push({
    $project: {
      ccaData: 1,
      avatar: 1,
      firstName: 1,
      lastName: 1,
      boCapacity: "$ccaData.boCapacity",
    },
  });
  const agents = await User.aggregate(agregation);

  for (let i = 0; i < agents.length; i++) {
    const ratings = await dailyRating.aggregate([
      {
        $match: {
          ccaId: agents[i]._id,
        },
      },
      {
        $group: {
          _id: 1,
          performance: { $sum: "$performance" },
          confermationRate: { $sum: "$confermationRate" },
          goalAchivement: { $sum: "$goalAchivement" },
        },
      },
    ]);

    if (ratings[0]) {
      agents[i].ccaData.performance = ratings[0].performance.toFixed(2);
      agents[i].ccaData.confermationRate =
        ratings[0].confermationRate.toFixed(2);
      agents[i].ccaData.goalAchivement = ratings[0].goalAchivement.toFixed(2);
    }
  }

  res.status(200).json({
    count,
    agents: agents,
  });
});

const getAgentInfo = asyncHandler(async (req, res) => {
  if (req.user.type === "CCA") {
    res.status(400);
    throw new Error("invalid user type");
  }

  const agentID = req.params.id;
  if (!agentID || typeof agentID !== "string") {
    res.status(400);
    throw new Error("invalid agentID type");
  }

  const agent = await User.aggregate([
    {
      $match: {
        _id: new mongoose.Types.ObjectId(agentID),
      },
    },
    {
      $lookup: {
        from: "callcenteragents",
        localField: "profile",
        foreignField: "_id",
        as: "ccaData",
      },
    },
  ]);

  const ratings = await dailyRating.aggregate([
    {
      $match: {
        ccaId: agent[0]._id,
      },
    },
    {
      $group: {
        _id: 1,
        performance: { $sum: "$performance" },
        confermationRate: { $sum: "$confermationRate" },
        goalAchivement: { $sum: "$goalAchivement" },
      },
    },
  ]);
  if (agent.lenght === 0) {
    res.status(404);
    throw new Error("CCA agent not found");
  }

  if (ratings[0]) {
    agent[0].ccaData[0].performance = ratings[0].performance.toFixed(2);
    agent[0].ccaData[0].confermationRate =
      ratings[0].confermationRate.toFixed(2);
    agent[0].ccaData[0].goalAchivement = ratings[0].goalAchivement.toFixed(2);
  }

  res.status(200).json(agent);
});

const sendrequest = asyncHandler(async (req, res) => {
  if (req.user.type === "CCA") {
    res.status(400);
    throw new Error("invalid user type");
  }
  const { items, ccaId, serviceType } = req.body;
  if (!ccaId) {
    res.status(400);
    throw new Error("missing Call Center Agent id");
  }
  if (items instanceof Array === false) {
    res.status(400);
    throw new Error("invalid request items");
  }
  if (isValidServiceType(serviceType) === false) {
    res.status(400);
    throw new Error("invalid request serviceType");
  }

  const boUser = await User.findById(req.user._id);
  const maxCcas = boUser.maxCCAs;

  const currentCcaCount = await Relation.countDocuments({
    boId: req.user._id,
    status: "accepted",
  });

  if (currentCcaCount >= maxCcas) {
    return res
      .status(400)
      .json({ message: "CCA limit reached. Cannot add more CCAs." });
  }

  const ccaInfo = await User.aggregate([
    {
      $match: {
        _id: new mongoose.Types.ObjectId(ccaId),
      },
    },
    {
      $lookup: {
        from: "callcenteragents",
        localField: "profile",
        foreignField: "_id",
        as: "ccaData",
      },
    },
  ]);
  const cca = ccaInfo[0];

  if (!cca) {
    res.status(404);
    throw new Error("cca not found");
  }
  if (cca.ccaData[0].boCapacity === "Full") {
    res.status(400);
    throw new Error("cca cant accept any more work");
  }
  if (cca.ccaData[0].serviceType.length === 0) {
    res.status(400);
    throw new Error("cca has no service type yet");
  }

  getServiceTypes(serviceType).forEach((type) => {
    if (cca.ccaData[0].serviceType.indexOf(type) === -1) {
      res.status(400);
      throw new Error("service type miss match");
    }
  });

  if (
    (await validateItemServiceTypes(items, getServiceTypes(serviceType))) ===
    false
  ) {
    res.status(400);
    throw new Error("item serviceType dose not match the selected serviceType");
  }

  const request = await Relation.findOne({
    ccaId,
    boId: req.user._id,
  });
  if (request && request.status === "pending") {
    res.status(400);
    throw new Error("request sent already");
  } else if (request && request.status === "accepted") {
    res.status(400);
    throw new Error("request already accepted");
    // items.forEach((item) => {
    // 	if (request.items.indexOf(item) === -1) {
    // 		request.items.push(item);
    // 	}
    // })
    // getServiceTypes(serviceType).forEach((type) => {
    // 	if (cca.ccaData[0].serviceType.indexOf(type) === -1) {
    // 		cca.ccaData[0].serviceType.push(type);
    // 	}
    // })

    // await request.save();
    // const ccaupdate = await callCenterAgent.replaceOne({ _id: cca.ccaData[0]._id }, cca.ccaData[0]);
    // res.status(200).json({
    // 	message: 'relation updates',
    // });
    // return;
  } else if (request && request.status === "canceled") {
    await Relation.deleteOne(request._id);
  }
  const dbItems = await Item.find({ _id: { $in: items } });
  if (dbItems.length === 0) {
    res.status(404);
    throw new Error("No Items In The Database");
  }
  const cca_bo_relation = await Relation.create({
    boId: req.user._id,
    ccaId: cca._id,
    status: "pending",
    items,
    sentDate: new Date(),
    performance: 0,
    confermationRate: 0,
    goalAchivement: 0,
    serviceType: getServiceTypes(serviceType),
    review: 0,
  });
  if (!cca_bo_relation) {
    res.status(500);
    throw new Error("SERVER IN MAINTENANCE");
  }
  items.forEach(async (item) => {
    const leads = await Lead.find({
      boID: req.user._id,
      status: "Pending",
      itemID: item._id,
      serviceType: cca.ccaData.serviceType,
    });
    leads.forEach(async (lead) => {
      (lead.ccaID = ccaId),
        await Lead.updateOne({ _id: lead._id }, { $set: lead });
    });
  });

  res.status(200).json(cca_bo_relation);
});

const getRequests = asyncHandler(async (req, res) => {
  if (req.user.type === "CCA") {
    res.status(400);
    throw new Error("invalid user type");
  }

  const page = req.query.page || 0;
  const elementsPerPage = 7;

  const count = await Relation.countDocuments({ boId: req.user._id });
  if (count === 0) {
    res.status(200).json({
      message: "no agents",
    });
    return;
  }
  const requrstList = await Relation.aggregate([
    {
      $match: {
        boId: req.user._id,
      },
    },
    {
      $lookup: {
        from: "users",
        localField: "ccaId",
        foreignField: "_id",
        as: "user",
      },
    },
    {
      $lookup: {
        from: "callcenteragents",
        localField: "user.profile",
        foreignField: "_id",
        as: "ccaData",
      },
    },
    {
      $sort: {
        sentDate: -1, // 1 ascending order
      },
    },
    {
      $skip: page * elementsPerPage,
    },
    {
      $limit: elementsPerPage,
    },
  ]);
  const ccas = [];
  for (let i = 0; i < requrstList.length; i++) {
    ccas.push({
      user: requrstList[i].user,
      date: requrstList[i].sentDate.toString().split(" GMT")[0],
      performance: requrstList[i].performance.toFixed(2),
      confermationRate: requrstList[i].confermationRate.toFixed(2),
      goalAchivement: requrstList[i].goalAchivement.toFixed(2),
      review: requrstList[i].review,
      status: requrstList[i].status,
      avatar: requrstList[i].user[0].avatar
        ? requrstList[i].user[0].avatar
        : null,
    });
  }
  res.status(200).json({
    count,
    requrstList: ccas,
  });
});

const leaveReview = asyncHandler(async (req, res) => {
  if (req.user.type === "CCA") {
    res.status(400);
    throw new Error("invalid user type");
  }
  const { starCount, ccaId } = req.body;
  if (!ccaId) {
    res.status(400);
    throw new Error("missing call center agent id");
  }

  if (!starCount || typeof starCount !== "string") {
    res.status(400);
    throw new Error("missing star count");
  }

  const count = Number(starCount).toFixed(1);
  if (Number.isNaN(count) || count < 0 || count > 5) {
    res.status(400);
    throw new Error("invalid star count");
  }
  const relation = await Relation.findOne({
    ccaId: ccaId,
    boId: req.user._id,
  });
  // if (relation.review !== -1) {
  // 	res.status(400);
  // 	throw new Error("review already submited");
  // }
  if (relation.status !== "accepted") {
    res.status(400);
    throw new Error("cant leave review");
  }
  const users = await User.aggregate([
    {
      $match: {
        _id: relation.ccaId,
      },
    },
    {
      $lookup: {
        from: "callcenteragents",
        localField: "profile",
        foreignField: "_id",
        as: "ccaData",
      },
    },
  ]);
  if (users.length === 0) {
    res.status(404);
    throw new Error("cca not found");
  }
  const ccaData = users[0].ccaData[0];
  relation.review = count;
  await relation.save();
  ccaData.reviews.push(count);
  ccaData.totalReviews += count;
  ccaData.reviewCount++;
  ccaData.globalReview = Math.min(
    5,
    Math.max(0, ccaData.totalReviews / ccaData.reviewCount)
  );

  const ccaupdate = await callCenterAgent.replaceOne(
    { _id: ccaData._id },
    ccaData
  );
  if (ccaupdate.modifiedCount === 1) {
    res.status(200).json({
      message: "review submitted successfully",
    });
  } else {
    res.status(500);
    throw new Error("SERVER IN MAINTENANCE");
  }
});

const cancelRequest = asyncHandler(async (req, res) => {
  if (req.user.type === "CCA") {
    res.status(400);
    throw new Error("invalid user type");
  }
  const ccaId = req.params.id;
  if (!ccaId) {
    res.status(400);
    throw new Error("missing cca id");
  }
  const relation = await Relation.findOne({
    boId: req.user._id,
    ccaId,
  });
  for (let i = 0; i < relation.items.length; i++) {
    const item = await Item.findById(relation.items[i]);
    if (item?.ccaSplit && item.ccaSplit.length !== 0) {
      item.ccaSplit = updateItemCcaSplit(item.ccaSplit, ccaId);
      await item.save();
    }
  }

  const deleteRelation = await Relation.deleteOne(relation._id);
  const leads = await Lead.find({
    boID: req.user._id,
    ccaID: ccaId,
  });
  if (deleteRelation.deletedCount === 1) {
    for (let i = 0; i < leads.length; i++) {
      leads[i].ccaID = null;
      const leadUpdate = await Lead.replaceOne({ _id: leads[i]._id }, leads[i]);
    }
    res.status(200).json({
      message: "request deleted",
    });
  } else {
    res.status(500);
    throw new Error("SERVER IN MAINTENANCE");
  }
});

export {
  getAgents,
  getAgentInfo,
  sendrequest,
  getRequests,
  leaveReview,
  cancelRequest,
};
Leave a Comment