From c5acab37b73f4840a8e28958a5dd8546d30ce137 Mon Sep 17 00:00:00 2001 From: jungmin Date: Fri, 23 Jan 2026 00:32:09 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=B4=88=EB=8C=80=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A7=8C=EB=A3=8C=EC=8B=9C=EA=B0=84=201=EC=9D=BC=20=EB=92=A4?= =?UTF-8?q?=EB=A1=9C=20=EA=B3=A0=EC=A0=95=20+=20=EB=A7=8C=EB=A3=8C?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EC=A7=80=EB=82=98=EB=A9=B4=20=ED=98=B8?= =?UTF-8?q?=EC=B6=9C=EC=95=88=EB=90=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/repositories/task.repository.js | 17 ++++++++++++----- src/services/task.service.js | 17 ++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/repositories/task.repository.js b/src/repositories/task.repository.js index 3335e5d..d0b6ef0 100644 --- a/src/repositories/task.repository.js +++ b/src/repositories/task.repository.js @@ -1,4 +1,9 @@ import { prisma } from "../db.config.js"; +import dayjs from "dayjs"; +import timezone from "dayjs/plugin/timezone.js"; +import utc from "dayjs/plugin/utc.js"; +dayjs.extend(utc); +dayjs.extend(timezone); class TaskRepository { async getCompletedTasks(userId) { @@ -200,15 +205,17 @@ class TaskRepository { // 초대 코드 생성 및 업데이트 async updateTaskInviteCode(taskId, inviteCode, tx = prisma) { - // 1년 후 만료일로 설정 - const oneYearLater = new Date(); - oneYearLater.setFullYear(oneYearLater.getFullYear() + 1); + // 1일 후 만료일로 설정 + // 1일 후 만료일로 설정 (한국 시간 기준) + const oneDayLater = dayjs().add(9, "hour").add(1, "day").toDate(); // 9시간 차이 보정 UTC +9시간 + console.log("oneDayLater (KST):", oneDayLater); + return await tx.task.update({ - where: { id: taskId }, + where: { id: taskId }, //팀과제만 가능 (개인과제는 초대 코드로 참여 불가) data: { inviteCode, - inviteExpiredAt: oneYearLater + inviteExpiredAt: oneDayLater }, select: { inviteCode: true, diff --git a/src/services/task.service.js b/src/services/task.service.js index 258b8cf..2bb4198 100644 --- a/src/services/task.service.js +++ b/src/services/task.service.js @@ -459,7 +459,11 @@ class TaskService { // 과제 존재 여부 확인 const task = await taskRepository.findTaskById(taskId); if (!task) { - throw new NotFoundError("과제를 찾을 수 없습니다."); + throw new NotFoundError("TASK_NOT_FOUND", "과제를 찾을 수 없습니다."); + } + + if (task.type === 'PERSONAL') { + throw new ForbiddenError("PERSONAL_TASK", "개인 과제는 초대 코드 생성이 불가능합니다."); } // 사용자가 해당 과제의 멤버인지 확인 @@ -472,7 +476,7 @@ class TaskService { }); if (!isMember) { - throw new ForbiddenError("초대 링크를 생성할 권한이 없습니다."); + throw new ForbiddenError("NOT_MEMBER", "해당 과제에 참여한 멤버가 아닙니다."); } // 랜덤한 8자리 초대 코드 생성 (대문자 + 숫자) @@ -494,7 +498,6 @@ class TaskService { invite_expired: result.inviteExpiredAt }; } - // ... existing code ... // 초대 코드로 팀 참여 async joinTaskByInviteCode(userId, inviteCode) { @@ -502,7 +505,7 @@ class TaskService { const task = await prisma.task.findFirst({ where: { inviteCode: inviteCode, - type: 'TEAM', // 팀 과제만 가능 + type: 'TEAM', // 팀 과제만 가능 (개인 과제는 초대 코드로 참여 불가) }, }); @@ -511,8 +514,8 @@ class TaskService { } // 초대 코드 만료일 확인 - if (task.inviteExpiredAt && new Date() > new Date(task.inviteExpiredAt)) { - throw new BadRequestError("EXPIRED_INVITE_CODE", "만료된 초대 코드입니다."); + if (task.inviteExpiredAt && new Date(Date.now() + 9 * 60 * 60 * 1000) > new Date(task.inviteExpiredAt)) { + throw new ForbiddenError("EXPIRED_INVITE_CODE", "만료된 초대 코드입니다."); } // 이미 멤버인지 확인 @@ -524,7 +527,7 @@ class TaskService { }); if (existingMember) { - throw new BadRequestError("ALREADY_MEMBER", "이미 팀 멤버입니다."); + throw new ForbiddenError("ALREADY_MEMBER", "이미 팀 멤버입니다."); } // 트랜잭션으로 멤버 추가 및 알림 생성