Duffer Derek

Current Path : /var/www/api-mk-planner.bitkit.dk/httpdocs/Backend/src/services/api/
Upload File :
Current File : /var/www/api-mk-planner.bitkit.dk/httpdocs/Backend/src/services/api/tasks.js

import { Op, Sequelize } from "sequelize";
import tasks from "../../database/models/tasks.js";
import User from "../../database/models/users.js";
import { dateTimeFormat } from "../commonFunctions.js";
import subTasks from "../../database/models/subTasks.js";
import files from "../../database/models/files.js";
import EmployeeLeaves from "../../database/models/employee_leaves.js";
import SharedTasks from "../../database/models/sharedTasks.js";
import Log from "../../configs/logger.js";
import { appAuthentication } from "../podio/podio.js";
import Podio from "@phasesdk/api-client-for-podio";
import TaskColors from "../../database/models/taskColors.js";

export const getTasks = async (filters, type = 1) => {
  let whereCondition = {};
  whereCondition = {
    [Op.or]: [
      {
        start_date: {
          [Op.between]: [
            dateTimeFormat(filters.startDate) + "T00:00:00.000Z",
            dateTimeFormat(filters.endDate) + "T23:59:59.999Z",
          ],
        },
      },
      {
        end_date: {
          [Op.between]: [
            dateTimeFormat(filters.startDate) + "T00:00:00.000Z",
            dateTimeFormat(filters.endDate) + "T23:59:59.999Z",
          ],
        },
      },
    ],

    status: {
      [Op.notIn]: [5, 8],
    },
  };

  if (filters.type) {
    whereCondition.type = filters.type.id;
  }
  if (filters.service_managers) {
    whereCondition.service_manager_id = filters.service_managers.id;
  }
  if (filters.partner) {
    whereCondition.user_item_id = filters.partner.id;
  }
  if (filters.lansdel) {
    whereCondition.countryside = filters.lansdel.id;
  }

  let include = [];
  let sharedTaskInclude = [];

  include.push({
    model: tasks,
    attributes: [
      "id",
      "item_id",
      "user_item_id",
      "service_manager_id",
      "customer_first_name",
      "customer_last_name",
      "start_date",
      "end_date",
      "invoice_description",
      "not_included_price",
      "internal_notes",
      "extra_services",
      "free_text_for_additional_services",
      "price",
      "type",
      "countryside",
      "country_side_color",
      "internal_notes_to_admin",
      "customer_phone_number",
      "customer_address",
      "status",
    ],
    required: false,
    where: whereCondition,
    include: [
      {
        model: subTasks,
        attributes: [
          "id",
          "user_item_id",
          "notes",
          "date",
          "time",
          "is_holiday",
          "shared_sub_task_time",
          "shared_partner",
        ],
        where: {
          shared: 0,
        },
        required: false,
        include: [
          {
            model: User, // Include the User model
            attributes: [["item_id", "id"], "name", "email", "phone", "type"],
          },
        ],
      },
      {
        model: files,
        attributes: ["file_id", "keyword", "filename", "item_id"],
        where: {
          keyword: "files",
        },
        required: false,
      },

      {
        model: User, // Include the User model for service manager
        as: "serviceManager", // Alias for service manager
        attributes: [["item_id", "id"], "name", "email", "phone", "type"],
        required: false,
        where: {
          id: Sequelize.col("tasks.service_manager_id"),
        },
      },
    ],
  });

  include.push({
    model: EmployeeLeaves,
    attributes: [
      "id",
      "item_id",
      "user_item_id",
      "start_date",
      "end_date",
      "status",
    ],
    required: false,
    where: {
      status: 2,
    },
  });

  let sharedTaskWhereCondition = {};
  sharedTaskWhereCondition = {
    [Op.or]: [
      {
        start_date: {
          [Op.between]: [
            dateTimeFormat(filters.startDate) + "T00:00:00.000Z",
            dateTimeFormat(filters.endDate) + "T23:59:59.999Z",
          ],
        },
      },
      {
        end_date: {
          [Op.between]: [
            dateTimeFormat(filters.startDate) + "T00:00:00.000Z",
            dateTimeFormat(filters.endDate) + "T23:59:59.999Z",
          ],
        },
      },
    ],
    status: {
      [Op.notIn]: [5, 8],
    },
  };

  if (filters.type) {
    sharedTaskWhereCondition.type = filters.type.id;
  }
  if (filters.service_managers) {
    sharedTaskWhereCondition.service_manager_id = filters.service_managers.id;
  }

  if (filters.lansdel) {
    sharedTaskWhereCondition.countryside = filters.lansdel.id;
  }

  sharedTaskInclude.push({
    model: tasks,
    attributes: [
      "id",
      "item_id",
      "user_item_id",
      "service_manager_id",
      "customer_first_name",
      "customer_last_name",
      "start_date",
      "end_date",
      "invoice_description",
      "not_included_price",
      "internal_notes",
      "extra_services",
      "free_text_for_additional_services",
      "price",
      "type",
      "countryside",
      "country_side_color",
      "internal_notes_to_admin",
      "customer_phone_number",
      "customer_address",
      "status",
    ],
    where: sharedTaskWhereCondition,
    include: [
      {
        model: subTasks,
        attributes: [
          "id",
          "user_item_id",
          "notes",
          "date",
          "time",
          "is_holiday",
          "shared_sub_task_time",
          "shared_partner",
          "shared",
        ],
        require: false,
        where: {
          shared: 1,
        },
        include: [
          {
            model: User, // Include the User model
            attributes: [["item_id", "id"], "name", "email", "phone", "type"],
          },
        ],
      },
      {
        model: files,
        attributes: ["file_id", "keyword", "filename", "item_id"],
        where: {
          keyword: "files",
        },
        required: false,
      },
    ],
  });
  include.push({
    model: SharedTasks,
    attributes: ["id", "task_id", "user_item_id", "date"],
    include: sharedTaskInclude,
  });
  let userWhereCondition = {
    type: 0,
  };
  if (filters.partner) {
    userWhereCondition.item_id = filters.partner.id;
  }
  const users = await User.findAll({
    attributes: [
      "item_id",
      "firstname",
      "lastname",
      [
        Sequelize.literal(`
          CASE
            WHEN users.firstname IS NOT NULL AND users.lastname IS NOT NULL THEN CONCAT(users.firstname, ' ', users.lastname)
            WHEN users.firstname IS NOT NULL THEN users.firstname
            ELSE users.lastname
          END
        `),
        "name",
      ],
      "email",
      "phone",
      "type",
    ],
    where: userWhereCondition,
    include: include,
  });
  const assignedTasks = getFormattedItems(users);

  whereCondition.user_item_id = null;
  whereCondition = {
    ...whereCondition,
    countryside: {
      [Op.ne]: null,
    },
  };
  if (filters.lansdel) {
    whereCondition.countryside = filters.lansdel.id;
  }

  // for handling unassigned tasks  checking any task  has with user_ietm id is null the n consider as a unassigned task
  let unAssignedItem = await tasks.findAll({
    attributes: [
      "id",
      "item_id",
      "user_item_id",
      "service_manager_id",
      "customer_first_name",
      "customer_last_name",
      "start_date",
      "end_date",
      "invoice_description",
      "not_included_price",
      "internal_notes",
      "extra_services",
      "free_text_for_additional_services",
      "price",
      "type",
      "countryside",
      "country_side_color",
      "internal_notes_to_admin",
      "customer_phone_number",
      "customer_address",
      "status",
    ],
    where: whereCondition,
    include: [
      {
        model: files,
        attributes: ["file_id", "keyword", "filename", "item_id"],
        required: false,
        where: {
          keyword: "files",
        },
      },
      {
        model: User, // Include the User model for service manager
        as: "serviceManager", // Alias for service manager
        attributes: [["item_id", "id"], "name", "email", "phone", "type"],
        required: false,
        where: {
          id: Sequelize.col("tasks.service_manager_id"),
        },
      },
    ],
  });

  const unAssignedTasks = formatUnAssignedItem(unAssignedItem);

  return ((assignedTasks, unAssignedTasks) => ({
    assigned: assignedTasks,
    unassigned: unAssignedTasks,
  }))(assignedTasks, unAssignedTasks);
};

// export const getTasks = async (filters, type = 1) => {

// };

export const item = async (itemId) => {
  return await tasks.findOne({
    include: [
      {
        model: User,
        attributes: ["id", "item_id", "name", "email", "phone"],
      },
      {
        model: subTasks,
        attributes: [
          "id",
          "notes",
          "date",
          "time",
          "is_holiday",
          "shared_sub_task_time",
          "shared_partner",
        ],
      },
    ],
    where: { item_id: itemId },
  });
};

export const updateItem = async (data) => {
  return await tasks.update(data, { where: { item_id: data.item_id } });
};
export const deleteSharedTask = async (data) => {
  let whereCondition = { task_id: data.task_id };
  if (data.date !== undefined) {
    whereCondition.date = data.date;
  }

  return await SharedTasks.destroy({
    where: whereCondition,
  });
};

const formatUnAssignedItem = (items) => {
  // Initialize with three empty categories for Sjælland, Fyn, and Jylland
  const groupedItems = [
    { categoryId: 1, tasks: [] }, // Sjælland
    { categoryId: 2, tasks: [] }, // Fyn
    { categoryId: 3, tasks: [] }, // Jylland
  ];

  // Perform the reduce operation
  items.reduce((acc, singleItem) => {
    const categoryId = singleItem.countryside;
    const existingCategory = acc.find(
      (category) => category.categoryId === categoryId
    );

    //get service manager details with task if exist
    const serviceManager = singleItem.serviceManager
      ? singleItem.serviceManager.name
      : null;
    let taskType = singleItem.type === 2 ? "Maler Reklamation" : "Maleropgave";
    let countryside =
      singleItem.countryside === 2
        ? "Fyn"
        : singleItem.countryside === 3
          ? "Jylland"
          : singleItem.countryside === 1
            ? "Sjælland"
            : "";

    let statusText = singleItem.status === 1
      ? "Oprettet"
      : singleItem.status === 3
        ? "Fuldført"
        : singleItem.status === 4
          ? "Faktureret"
          : singleItem.status === 5
            ? "Annulleret"
            : singleItem.status === 5
              ? "Annulleret Maler"
              : singleItem.status === 6
                ? "Booket"
                : singleItem.status === 8
                  ? "Annulleret Kunden"
                  : "";
    if (existingCategory) {
      existingCategory.tasks.push({
        id: singleItem.id,
        item_id: singleItem.item_id,
        taskName: `${singleItem.customer_first_name} ${singleItem.customer_last_name}`,
        startDate: dateTimeFormat(singleItem.start_date, "day_month_year"),
        endDate: dateTimeFormat(singleItem.end_date, "day_month_year"),
        files: singleItem.files,
        customer_phone_number: singleItem.customer_phone_number,
        customer_address: singleItem.customer_address,
        status: singleItem.status,
        shared: false,
        unassigned: true,
        invoice_description: singleItem.invoice_description,
        not_included_price: singleItem.not_included_price,
        internal_notes: singleItem.internal_notes,
        internal_notes_to_admin: singleItem.internal_notes_to_admin,
        extra_services: singleItem.extra_services,
        free_text_for_additional_services: singleItem.free_text_for_additional_services,
        price: singleItem.price,
        type: taskType,
        countryside: countryside,
        status: statusText,
        country_side_color: singleItem.country_side_color,
        serviceManager: serviceManager,
      });
    } else {
      acc.push({
        categoryId: categoryId,
        tasks: [
          {
            id: singleItem.id,
            item_id: singleItem.item_id,
            taskName: `${singleItem.customer_first_name} ${singleItem.customer_last_name}`,
            startDate: dateTimeFormat(singleItem.start_date, "day_month_year"),
            endDate: dateTimeFormat(singleItem.end_date, "day_month_year"),
            files: singleItem.files,
            shared: false,
            customer_address: singleItem.customer_address,
            customer_phone_number: singleItem.customer_phone_number,
            invoice_description: singleItem.invoice_description,
            not_included_price: singleItem.not_included_price,
            internal_notes: singleItem.internal_notes,
            internal_notes_to_admin: singleItem.internal_notes_to_admin,
            extra_services: singleItem.extra_services,
            free_text_for_additional_services: singleItem.free_text_for_additional_services,
            price: singleItem.price,
            type: taskType,
            countryside: countryside,
            status: statusText,
            country_side_color: singleItem.country_side_color,
            serviceManager: serviceManager,
          },
        ],
      });
    }
    return acc;
  }, groupedItems);

  return groupedItems;
};

const getFormattedItems = (users) => {
  const formattedTasks = users.map((user) => ({
    userId: user.item_id,
    email: user.email,
    phone: user.phone,
    type: user.type,
    username: user.name,
    firstname: user.firstname,
    lastname: user.lastname,
    leaves: formatLeaves(user.employee_leaves),
    tasks: mergeTask(user),
    // shared: user.shared_tasks.map((task) => taskFormating1(task)),
  }));
  return formattedTasks;
};
// for shared task updation or creation
export const updateOrCreateSharedTask = async (data) => {
  const [instance, isCreated] = await SharedTasks.findOrCreate({
    where: Sequelize.and({
      task_id: data.task_id,
      date: data.date,
    }),
    defaults: data,
  });
  if (!isCreated) {
    await SharedTasks.update(data, {
      where: Sequelize.and({
        task_id: data.task_id,
        date: data.date,
      }),
    });
  }
};

export const updateOrCreateSubTask = async (data) => {
  if (data.shared === 1) {
    let sharedData = {
      task_id: data.item_id,
      user_item_id: data.user_item_id,
      date: data.date,
    };

    await updateOrCreateSharedTask(sharedData);
  }
  // First, try to find an existing instance
  let instance = await subTasks.findOne({
    where: Sequelize.and(
      { item_id: data.item_id },
      { date: data.date },
      { shared: data.shared }
    ),
  });

  // If instance exists, delete it
  if (instance) {
    await subTasks.destroy({
      where: Sequelize.and(
        { item_id: data.item_id },
        { date: data.date },
        { shared: data.shared }
      ),
    });
  }

  // Create a new instance with the provided data
  instance = await subTasks.create(data);
};
export const getAndDeleteSubTask = async (data) => {
  await subTasks.destroy({
    where: {
      item_id: data.item_id,
    },
  });
  await SharedTasks.destroy({
    where: {
      task_id: data.item_id,
    },
  });
};
//delete shared task and shared subtask and update  sharedpartner and shared time in subtask
export const deleteSharedTaskandSubTask = async (data) => {
  await subTasks.destroy({
    where: {
      item_id: data.item_id,
      date: data.date,
      shared: 1,
    },
  });
  await SharedTasks.destroy({
    where: {
      task_id: data.item_id,
      date: data.date,
    },
  });

  let update = {
    shared_sub_task_time: null,
    shared_partner: null,
  };

  await subTasks.update(update, {
    where: {
      date: data.date,
      item_id: data.item_id,
      shared: 0,
    },
  });
};
export const checkAndDeleteSubTask = async (data) => {
  await subTasks.destroy({
    where: {
      item_id: data.item_id,
      date: data.date,
      shared: data.shared,
    },
  });
  //also delete shared task
  await SharedTasks.destroy({
    where: {
      task_id: data.item_id,
      date: data.date,
    },
  });
};

export const getAndDeleteSharedTask = async (task_data) => {
  const task_id = task_data.item_id;
  const sharedTasks = await SharedTasks.findAll({
    attributes: ["id", "task_id", "user_item_id", "date"],
    where: {
      task_id: task_id,
    },
    include: [
      {
        model: subTasks,
        attributes: [
          "id",
          "item_id",
          "user_item_id",
          "notes",
          "date",
          "time",
          "is_holiday",
          "shared_sub_task_time",
          "shared_partner",
        ],
        where: {
          shared: 1,
        },
      },
    ],
  });

  if (sharedTasks.length === 0) {
    let data = {
      task_id: task_id,
    };
    deleteSharedTask(data);
  } else {
    sharedTasks.map((sharedTask) => {
      sharedTask.sub_tasks.map((subTask) => {
        if (
          new Date(subTask.date).getTime() !==
          new Date(sharedTask.date).getTime()
        ) {
          let data = {
            task_id: task_id,
            date: sharedTask.date,
          };
          deleteSharedTask(data);
        }
      });
    });
  }
  // await checkAndDeleteSharedSubTask(task_data);
  // also delete shared_subtask of shared
};

const mergeTask = (user) => {
  const mainTask = user?.tasks.map((task) => taskFormating(task, user.item_id));
  const sharedTask = user?.shared_tasks.map((task) =>
    taskFormating(task?.task, user?.item_id, task.date, true)
  );
  return [...mainTask, ...sharedTask];
};

const formatLeaves = (leaves) => {
  const formattedLeaves = leaves.map((leave) => ({
    id: leave?.id,
    item_id: leave.item_id,
    start_date: dateTimeFormat(leave.start_date, "day_month_year"),
    end_date: dateTimeFormat(leave.end_date, "day_month_year"),
    status: leave.status,
    user_item_id: leave.user_item_id,
  }));
  return formattedLeaves;
};

const taskFormating = (task, userId, date = "", shared = false) => {
  let subtasks = [];
  let startDate = dateTimeFormat(task.start_date, "day_month_year");
  let endDate = dateTimeFormat(task.end_date, "day_month_year");
  if (shared == false) {
    shared = shared;
    subtasks = task?.sub_tasks.map((subTask) => ({
      id: subTask?.id,
      notes: subTask.notes,
      date: dateTimeFormat(subTask.date, "day_month_year"),
      time: subTask.time,
      is_holiday: subTask.is_holiday,
      user: subTask.shared_partner,
      user_id: subTask.user.id,
      shared_time: subTask.shared_sub_task_time,
    }));
  } else {
    startDate = dateTimeFormat(date, "day_month_year");
    endDate = dateTimeFormat(date, "day_month_year");
    subtasks = task?.sub_tasks.map((subTask) => {
      if (
        userId == subTask.user.id &&
        new Date(date).getTime() === new Date(subTask.date).getTime()
      ) {
        return {
          id: subTask?.id,
          notes: subTask.notes,
          date: dateTimeFormat(subTask.date, "day_month_year"),
          time: subTask.time,
          is_holiday: subTask.is_holiday,
          user: subTask.shared_partner,
          user_id: subTask.user.id,
          shared_time: subTask.shared_sub_task_time,
        };
      }
    });
  }

  return {
    id: task.id,
    unassigned: false,
    item_id: task.item_id,
    taskName: `${task.customer_first_name} ${task.customer_last_name}`,
    startDate: startDate,
    endDate: endDate,
    invoice_description: task.invoice_description,
    not_included_price: task.not_included_price,
    internal_notes: task.internal_notes,
    internal_notes_to_admin: task.internal_notes_to_admin,
    extra_services: task.extra_services,
    free_text_for_additional_services: task.free_text_for_additional_services,
    customer_phone_number: task.customer_phone_number,
    customer_address: task.customer_address,
    price: task.price,
    type: task.type === 2 ? "Maler Reklamation" : "Maleropgave",
    countryside:
      task.countryside === 2
        ? "Fyn"
        : task.countryside === 3
          ? "Jylland"
          : task.countryside === 1
            ? "Sjælland"
            : "",
    status:
      task.status === 1
        ? "Oprettet"
        : task.status === 3
          ? "Fuldført"
          : task.status === 4
            ? "Faktureret"
            : task.status === 5
              ? "Annulleret"
              : task.status === 5
                ? "Annulleret Maler"
                : task.status === 6
                  ? "Booket"
                  : task.status === 8
                    ? "Annulleret Kunden"
                    : "",

    country_side_color: task.country_side_color,
    files: task.files,
    subtasks: subtasks.filter(Boolean),
    files: task.files,
    serviceManager: task.serviceManager ? task.serviceManager.name : null,
    shared: shared,
  };
};

export const updateTask = async (task) => {
  try {
    const item_id = task.item_id;
    const start_date = task.start_date;
    const end_date = task.end_date;
    const user_id = task.user_id;
    const country_side_color = task.country_side_color;
    let attributes = {
      fields: {
        "dato-for-hvornar-opgaven-skal-pabegyndes": {
          start_date: start_date,
          end_date: start_date,
        },
        "deadline-date": { start_date: end_date, end_date: end_date },
        "partner-2": [user_id],
      },
    };
    const auth = await appAuthentication(
      process.env.TASK_APP_ID,
      process.env.TASK_APP_TOKEN
    );
    let update = await Podio.api.item(auth).update(item_id, attributes);
    if (update.status == 200 || update.status == 204) {
      let update = {
        item_id: item_id,
        start_date: start_date,
        end_date: end_date,
        user_item_id: user_id,
        country_side_color: country_side_color,
      };
      await updateItem(update);
      // if that item user and shared task  user are sam ethen delete shared task
      // await deleteSharedTask(update);
    }
    return true;
  } catch (error) {
    Log.error(error);
    return error;
  }
};

export const getLandsdelColor = async (landsdel) => {
  try {
    let colors = await TaskColors.findAll({
      attributes: ["id", "name", "color"],
      where: {
        status: 1,
      },
    });
    return colors;
    // let ids = [];
    // landsdel.forEach((item) => {
    //   ids.push(item.id);
    // });

    // let colors = await tasks.findAll({
    //   attributes: [
    //     "countryside",
    //     [
    //       Sequelize.fn("MAX", Sequelize.col("country_side_color")),
    //       "country_side_color",
    //     ],
    //   ],
    //   where: {
    //     countryside: ids,
    //     type: 1,
    //     user_item_id: { [Op.not]: null },
    //   },
    //   group: ["countryside"],
    // });
    // landsdel.forEach((item) => {
    //   const matchingColor = colors.find(
    //     (color) => item.id === color.countryside
    //   );
    //   if (matchingColor) {
    //     item.color = matchingColor.country_side_color;
    //   }
    // });
    // return landsdel;
  } catch (error) {
    Log.error(error);
  }
};

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