Duffer Derek
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