diff --git a/src/controllers/task.controller.js b/src/controllers/task.controller.js index 671c487..e1d2ffc 100644 --- a/src/controllers/task.controller.js +++ b/src/controllers/task.controller.js @@ -190,12 +190,12 @@ class TaskController { async updateTeamMember(req, res, next) { try { const taskId = req.body.taskId || req.params.taskId; - const memberId = req.body.memberId || req.params.memberId; + const userId = req.body.userId || req.params.userId; const { role } = req.body; const result = await taskService.modifyMemberRole( parseInt(taskId), - parseInt(memberId), + parseInt(userId), role ); diff --git a/src/repositories/task.repository.js b/src/repositories/task.repository.js index 68948d3..ed1b82e 100644 --- a/src/repositories/task.repository.js +++ b/src/repositories/task.repository.js @@ -178,21 +178,21 @@ class TaskRepository { } // 멤버 존재 여부 확인 - async findMemberInTask(taskId, memberId) { + async findMemberInTask(taskId, userId) { return await prisma.member.findFirst({ where: { - id: memberId, - taskId: taskId + taskId: parseInt(taskId), + userId: parseInt(userId) } }); } // 나머지 멤버 역할 리셋 - async resetOtherMembersRole(taskId, memberId, tx) { + async resetOtherMembersRole(taskId, userId, tx) { return await tx.member.updateMany({ where: { - taskId: taskId, - id: { not: memberId }, + taskId: parseInt(taskId), + userId: { not: parseInt(userId) }, }, data: { role: false, @@ -203,7 +203,7 @@ class TaskRepository { // 대상 멤버 역할 업데이트 async updateMemberRole(memberId, isAdmin, tx) { return await tx.member.update({ - where: { id: memberId }, + where: { id: memberId }, // userId는 중복될 수 있으므로(다른 과제 등) id(PK) 사용 data: { role: isAdmin }, }); } diff --git a/src/routes/task.route.js b/src/routes/task.route.js index ac87a9f..050d3c5 100644 --- a/src/routes/task.route.js +++ b/src/routes/task.route.js @@ -30,8 +30,8 @@ router.get("/:taskId", authenticate, taskController.getTaskDetail); // GET /api/v1/task?sort=우선순위 -- 과제 목록 조회 router.get("/", authenticate, taskController.getTasks); -// PATCH /api/v1/task/:taskId/member/:memberId -- 팀원 정보 수정 -router.patch("/:taskId/member/:memberId", authenticate, taskController.updateTeamMember); +// PATCH /api/v1/task/:taskId/member/:userId -- 팀원 정보 수정 +router.patch("/:taskId/member/:userId", authenticate, taskController.updateTeamMember); // POST /api/v1/task/:taskId/subTask -- 단일 세부 과제 추가 router.post("/:taskId/subTask", authenticate, taskController.addSubTask) diff --git a/src/services/task.service.js b/src/services/task.service.js index a6374b0..bfaaa85 100644 --- a/src/services/task.service.js +++ b/src/services/task.service.js @@ -67,8 +67,17 @@ class TaskService { if (folder.userId !== userId) { throw new ForbiddenError("권한이 없는 폴더입니다."); } - if (folder.folderTitle === "팀" || folder.folderTitle === "팀 과제") { - throw new BadRequestError("INVALID_FOLDER", "개인 과제는 팀 과제 전용 폴더에 생성할 수 없습니다."); + } + // CASE A: 팀 과제 ('TEAM') + if (taskData.type === 'TEAM') { + if (!folder || folder.folderTitle !== "팀") { + throw new BadRequestError("INVALID_FOLDER", "팀 과제는 '팀' 폴더에만 생성할 수 있습니다."); + } + } + // CASE B: 개인 과제 ('PERSONAL') + else { + if (folder && folder.folderTitle === "팀") { + throw new BadRequestError("INVALID_FOLDER", "개인 과제는 '팀' 폴더에 생성할 수 없습니다."); } } @@ -332,16 +341,34 @@ class TaskService { async getTaskList(userId, queryParams = {}) { const { type, folderId, sort, status } = queryParams; - // 레포지토리의 findAllTasks 호출 + 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, + folderId, sort, status }); - return tasks; + return tasks.map(task => { + if (task.type === 'TEAM' && myTeamFolder) { + return { + ...task, + folderId: myTeamFolder.id, + folderTitle: myTeamFolder.folderTitle, + foldercolor: myTeamFolder.color + }; + } + return task; + }); } // 우선순위 변경 @@ -745,19 +772,20 @@ class TaskService { } // 팀원 정보 수정 - async modifyMemberRole(taskId, memberId, role) { - const member = await taskRepository.findMemberInTask(taskId, memberId); - if (!member) throw new NotFoundError("멤버를 찾을 수 없음"); + async modifyMemberRole(taskId, userId, role) { + const member = await taskRepository.findMemberInTask(taskId, userId); + + 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, memberId, tx); - } + return await prisma.$transaction(async (tx) => { + if (isAdmin) { + await taskRepository.resetOtherMembersRole(taskId, userId, tx); + } - return await taskRepository.updateMemberRole(memberId, isAdmin, tx); - }); + return await taskRepository.updateMemberRole(member.id, isAdmin, tx); + }); } // 단일 세부 과제 생성 서비스 diff --git a/src/swagger/swagger.yml b/src/swagger/swagger.yml index e161884..6b58efe 100644 --- a/src/swagger/swagger.yml +++ b/src/swagger/swagger.yml @@ -1099,7 +1099,7 @@ paths: resultType: "FAIL" code: 400 errorCode: "BAD_REQUEST | TEAM_FOLDER_REQUIRED | INVALID_FOLDER" - reason: "과제명은 필수입니다. | 팀 과제는 '팀' 폴더에만 생성할 수 있습니다. | 개인 과제는 팀 과제 전용 폴더에 생성할 수 없습니다." + reason: "과제명은 필수입니다. | 팀 과제는 '팀' 폴더에만 생성할 수 있습니다. | 개인 과제는 '팀' 폴더에 생성할 수 없습니다. | 팀 과제는 '팀' 폴더에만 생성할 수 있습니다." data: null '401': description: 인증 실패 (토큰 만료 또는 누락) @@ -1729,7 +1729,7 @@ paths: description: 서버 내부 오류 # 팀원 정보(역할) 수정 - /api/v1/task/{taskId}/member/{memberId}: + /api/v1/task/{taskId}/member/{userId}: patch: tags: - Task @@ -1744,7 +1744,7 @@ paths: schema: type: integer - in: path - name: memberId + name: userId required: true schema: type: integer @@ -1754,12 +1754,12 @@ paths: application/json: schema: type: object - required: [taskId, memberId, role] + required: [taskId, userId, role] properties: taskId: type: integer example: 1 - memberId: + userId: type: integer example: 5 role: