Skip to content
Closed
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions src/controllers/task.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
);

Expand Down
14 changes: 7 additions & 7 deletions src/repositories/task.repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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 },
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/routes/task.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
58 changes: 43 additions & 15 deletions src/services/task.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -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", "개인 과제는 '팀' 폴더에 생성할 수 없습니다.");
}
}

Expand Down Expand Up @@ -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;
});
}

// 우선순위 변경
Expand Down Expand Up @@ -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);
});
}

// 단일 세부 과제 생성 서비스
Expand Down
10 changes: 5 additions & 5 deletions src/swagger/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ paths:
resultType: "FAIL"
code: 400
errorCode: "BAD_REQUEST | TEAM_FOLDER_REQUIRED | INVALID_FOLDER"
reason: "과제명은 필수입니다. | 팀 과제는 '팀' 폴더에만 생성할 수 있습니다. | 개인 과제는 팀 과제 전용 폴더에 생성할 수 없습니다."
reason: "과제명은 필수입니다. | 팀 과제는 '팀' 폴더에만 생성할 수 있습니다. | 개인 과제는 '팀' 폴더에 생성할 수 없습니다. | 팀 과제는 '팀' 폴더에만 생성할 수 있습니다."
data: null
'401':
description: 인증 실패 (토큰 만료 또는 누락)
Expand Down Expand Up @@ -1729,7 +1729,7 @@ paths:
description: 서버 내부 오류

# 팀원 정보(역할) 수정
/api/v1/task/{taskId}/member/{memberId}:
/api/v1/task/{taskId}/member/{userId}:
patch:
tags:
- Task
Expand All @@ -1744,7 +1744,7 @@ paths:
schema:
type: integer
- in: path
name: memberId
name: userId
required: true
schema:
type: integer
Expand All @@ -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:
Expand Down