Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 72 additions & 84 deletions src/services/task.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,46 @@ class TaskService {
return await taskRepository.getCompletedTasks(userId);
}

// ๊ณผ์ œ ๋“ฑ๋ก
async getTaskList(userId, queryParams = {}) {
let { type, folderId, sort, status } = queryParams;

const myTeamFolder = await prisma.folder.findFirst({
where: { userId, folderTitle: "ํŒ€" }
});

if (folderId && myTeamFolder && parseInt(folderId) === myTeamFolder.id) {
folderId = undefined;
type = 'TEAM';
}

// 3. ์‹ค์ œ DB ์กฐํšŒ
const tasks = await taskRepository.findAllTasks({
userId,
type,
folderId,
sort,
status
});

return tasks.map(task => {
if (task.type === 'TEAM' && myTeamFolder) {
return {
...task,
folderId: myTeamFolder.id,
folderTitle: myTeamFolder.folderTitle,
foldercolor: myTeamFolder.color
};
}
return task;
});
}

async registerTask(userId, data) {
const { subTasks, references, folderId, ...taskData } = data;

console.log("์ƒ์„ฑ ์‹œ๋„ ์œ ์ € ID:", userId)
console.log("์ƒ์„ฑ ์‹œ๋„ ์œ ์ € ID:", userId);

// 1. ์œ ์ € ์กด์žฌ ํ™•์ธ
const user = await prisma.user.findUnique({
where: { id: userId }
});
Expand All @@ -32,57 +67,42 @@ class TaskService {

if (!taskData.title) throw new BadRequestError("๊ณผ์ œ๋ช…์€ ํ•„์ˆ˜์ž…๋‹ˆ๋‹ค.");

// folderId๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ํด๋” ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ
if (folderId) {
const folder = await taskRepository.findFolderById(folderId);
if (!folder) throw new NotFoundError("์กด์žฌํ•˜์ง€ ์•Š๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.");
}

let targetFolderId = folderId;

if (taskData.type === 'TEAM') {
// 1. ํŒ€ ๊ณผ์ œ๋ผ๋ฉด ๋ฌด์กฐ๊ฑด 'ํŒ€' ํด๋”๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.
const teamFolder = await prisma.folder.findFirst({
where: {
userId: userId,
folderTitle: "ํŒ€"
}
});

if (!teamFolder) {
throw new NotFoundError("ํŒ€ ๊ณผ์ œ ์ „์šฉ ํด๋”๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
}
let folder = null;

// 2. ๊ฐ•์ œ๋กœ 'ํŒ€' ํด๋” ID๋กœ
targetFolderId = teamFolder.id;

} else if (folderId) {
// 3. ๊ฐœ์ธ ๊ณผ์ œ์ธ๋ฐ ํด๋”๋ฅผ ์„ ํƒํ•œ ๊ฒฝ์šฐ -> ์œ ํšจ์„ฑ ๋ฐ ๊ถŒํ•œ ๊ฒ€์‚ฌ
const folder = await taskRepository.findFolderById(folderId);
if (folderId) {
folder = await taskRepository.findFolderById(folderId);

// ํด๋”๊ฐ€ ์—†์œผ๋ฉด ์—๋Ÿฌ
if (!folder) {
throw new NotFoundError("์กด์žฌํ•˜์ง€ ์•Š๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.");
}

// ๋‚ด ํด๋”๊ฐ€ ์•„๋‹ˆ๋ฉด ์—๋Ÿฌ (๋ณด์•ˆ)
if (folder.userId !== userId) {
throw new ForbiddenError("๊ถŒํ•œ์ด ์—†๋Š” ํด๋”์ž…๋‹ˆ๋‹ค.");
}
}
// CASE A: ํŒ€ ๊ณผ์ œ ('TEAM')


// CASE A: ํŒ€ ๊ณผ์ œ ('TEAM')
if (taskData.type === 'TEAM') {
// ๊ทœ์น™: "ํŒ€" ํด๋”๊ฐ€ ์•„๋‹ˆ๋ฉด ๋ฌด์กฐ๊ฑด ์—๋Ÿฌ! (์„ ํƒ ์•ˆ ํ•ด๋„ ์—๋Ÿฌ, ๋‹ค๋ฅธ ํด๋”์—ฌ๋„ ์—๋Ÿฌ)
// โš ๏ธ ์ฃผ์˜: DB ํด๋”๋ช…์ด "ํŒ€ ๊ณผ์ œ"๋ผ๋ฉด ์—ฌ๊ธฐ๋„ "ํŒ€ ๊ณผ์ œ"๋กœ ์ˆ˜์ •ํ•˜์„ธ์š”.
if (!folder || folder.folderTitle !== "ํŒ€") {
throw new BadRequestError("INVALID_FOLDER", "ํŒ€ ๊ณผ์ œ๋Š” 'ํŒ€' ํด๋”์—๋งŒ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.");
}
}
// CASE B: ๊ฐœ์ธ ๊ณผ์ œ ('PERSONAL')
else {
// ๊ทœ์น™: "ํŒ€" ํด๋”๋ฅผ ์„ ํƒํ–ˆ๋‹ค๋ฉด ์—๋Ÿฌ! (ํŒ€ ํด๋” ์นจ๋ฒ” ๋ถˆ๊ฐ€)
if (folder && folder.folderTitle === "ํŒ€") {
throw new BadRequestError("INVALID_FOLDER", "๊ฐœ์ธ ๊ณผ์ œ๋Š” 'ํŒ€' ํด๋”์— ์ƒ์„ฑํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
}
}

// ํŠธ๋žœ์žญ์…˜ ์‹œ์ž‘
return await prisma.$transaction(async (tx) => {
// ๊ณผ์ œ ์ƒ์„ฑ
// ๊ณผ์ œ ์ƒ์„ฑ (๊ฒ€์ฆ๋œ folderId ์‚ฌ์šฉ)
const newTask = await taskRepository.createTask({ ...taskData, folderId }, tx);

// ๊ณผ์ œ ์ƒ์„ฑ์ž๋ฅผ owner๋กœ ๋ฉค๋ฒ„์— ์ž๋™ ์ถ”๊ฐ€
Expand All @@ -92,18 +112,15 @@ class TaskService {
const maxRank = await taskRepository.findMaxRank(userId, tx);
await taskRepository.upsertTaskPriority(userId, newTask.id, maxRank + 1, tx);

// ๊ณผ์ œ ์•Œ๋ฆผ ์ƒ์„ฑ
// --- [์•Œ๋ฆผ ์ƒ์„ฑ ๋กœ์ง ์œ ์ง€] ---
if (newTask.isAlarm) {
// ํŒ€ ๊ณผ์ œ์ธ ๊ฒฝ์šฐ: ๋ฉค๋ฒ„ ๋ชจ๋‘์—๊ฒŒ ์•Œ๋ฆผ ์ƒ์„ฑ
if (newTask.type === 'TEAM') {
// ๋ฉค๋ฒ„ ์กฐํšŒ (์ƒ์„ฑ์ž ํฌํ•จ)
const members = await tx.member.findMany({
where: { taskId: newTask.id },
include: { user: true },
});

if (members.length > 0) {
// ๋ชจ๋“  ๋ฉค๋ฒ„์—๊ฒŒ ์•Œ๋ฆผ ์ƒ์„ฑ
const alarmPromises = members.map(async (member) => {
const user = member.user;
const alarmHours = user.deadlineAlarm || 24;
Expand All @@ -120,7 +137,6 @@ class TaskService {
await Promise.all(alarmPromises);
}
} else {
// ๊ฐœ์ธ ๊ณผ์ œ์ธ ๊ฒฝ์šฐ: ์ƒ์„ฑ์ž์—๊ฒŒ๋งŒ ์•Œ๋ฆผ ์ƒ์„ฑ
const creator = await tx.user.findUnique({
where: { id: userId },
select: { deadlineAlarm: true },
Expand All @@ -141,18 +157,16 @@ class TaskService {
}
}

// ํ•˜์œ„ ๋ฐ์ดํ„ฐ ์ €์žฅ
// --- [ํ•˜์œ„ ๋ฐ์ดํ„ฐ ์ €์žฅ ๋กœ์ง ์œ ์ง€] ---
if (subTasks && subTasks.length > 0) {
await taskRepository.addSubTasks(newTask.id, subTasks, tx);

// ์„ธ๋ถ€๊ณผ์ œ ์ƒ์„ฑ ํ›„ ์•Œ๋ฆผ ์ƒ์„ฑ
const createdSubTasksList = await tx.subTask.findMany({
where: { taskId: newTask.id },
include: { assignee: true },
});

for (const subTask of createdSubTasksList) {
// ์„ธ๋ถ€๊ณผ์ œ ๋‹ด๋‹น์ž์—๊ฒŒ ์•Œ๋ฆผ ์ƒ์„ฑ
if (subTask.isAlarm && subTask.assigneeId) {
const assignee = subTask.assignee;
if (assignee) {
Expand Down Expand Up @@ -193,10 +207,18 @@ class TaskService {
taskData.deadline = new Date(taskData.deadline);
}

// ํด๋”
// ํด๋” ๋ณ€๊ฒฝ ์‹œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ (์ถ”๊ฐ€๋œ ๋ถ€๋ถ„)
if (folderId) {
const folder = await taskRepository.findFolderById(folderId);
if (!folder) throw new NotFoundError("๋ณ€๊ฒฝํ•˜๋ ค๋Š” ํด๋”๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");

// [๋ณดํ˜ธ ๋กœ์ง] ์ˆ˜์ • ์‹œ์—๋„ ํŒ€/๊ฐœ์ธ ํด๋” ๊ทœ์น™ ์ ์šฉ
if (currentTask.type === 'TEAM' && folder.folderTitle !== 'ํŒ€') {
throw new BadRequestError("INVALID_FOLDER", "ํŒ€ ๊ณผ์ œ๋Š” 'ํŒ€' ํด๋”๋กœ๋งŒ ์ด๋™ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.");
}
if (currentTask.type === 'PERSONAL' && folder.folderTitle === 'ํŒ€') {
throw new BadRequestError("INVALID_FOLDER", "๊ฐœ์ธ ๊ณผ์ œ๋Š” 'ํŒ€' ํด๋”๋กœ ์ด๋™ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
}
}

// ํŠธ๋žœ์žญ์…˜
Expand Down Expand Up @@ -259,6 +281,7 @@ class TaskService {
return { taskId: updatedTask.id };
});
}

// Task ๋งˆ๊ฐ์ผ ๋ณ€๊ฒฝ ์„œ๋น„์Šค
async updateTaskDeadline(userId, taskId, deadline) {
// 1. Task ์กด์žฌ ์—ฌ๋ถ€ ํ™•์ธ
Expand Down Expand Up @@ -337,40 +360,6 @@ class TaskService {
return task;
}

// ๊ณผ์ œ ๋ชฉ๋ก ์กฐํšŒ
async getTaskList(userId, queryParams = {}) {
const { type, folderId, sort, status } = queryParams;

const myTeamFolder = await prisma.folder.findFirst({
where: { userId, folderTitle: "ํŒ€" }
});

if (folderId && myTeamFolder && parseInt(folderId) === myTeamFolder.id) {
folderId = undefined;
type = 'TEAM';
}

const tasks = await taskRepository.findAllTasks({
userId,
type,
folderId,
sort,
status
});

return tasks.map(task => {
if (task.type === 'TEAM' && myTeamFolder) {
return {
...task,
folderId: myTeamFolder.id,
folderTitle: myTeamFolder.folderTitle,
foldercolor: myTeamFolder.color
};
}
return task;
});
}

// ์šฐ์„ ์ˆœ์œ„ ๋ณ€๊ฒฝ
async updatePriorities(userId, orderedTasks) {
// ์ผ๊ด„ ๋ณ€๊ฒฝ ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ
Expand Down Expand Up @@ -772,20 +761,19 @@ class TaskService {
}

// ํŒ€์› ์ •๋ณด ์ˆ˜์ •
async modifyMemberRole(taskId, userId, role) {
const member = await taskRepository.findMemberInTask(taskId, userId);

if (!member) throw new NotFoundError("ํ•ด๋‹น ๊ณผ์ œ์—์„œ ํ•ด๋‹น ์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ");
async modifyMemberRole(taskId, memberId, role) {
const member = await taskRepository.findMemberInTask(taskId, memberId);
if (!member) throw new NotFoundError("๋ฉค๋ฒ„๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ");

const isAdmin = role === 1;
const isAdmin = role === 1;

return await prisma.$transaction(async (tx) => {
if (isAdmin) {
await taskRepository.resetOtherMembersRole(taskId, userId, tx);
}
return await prisma.$transaction(async (tx) => {
if (isAdmin) {
await taskRepository.resetOtherMembersRole(taskId, memberId, tx);
}

return await taskRepository.updateMemberRole(member.id, isAdmin, tx);
});
return await taskRepository.updateMemberRole(memberId, isAdmin, tx);
});
}

// ๋‹จ์ผ ์„ธ๋ถ€ ๊ณผ์ œ ์ƒ์„ฑ ์„œ๋น„์Šค
Expand Down