diff --git a/src/main/java/clap/server/adapter/inbound/web/dto/task/UpdateTaskLabelRequest.java b/src/main/java/clap/server/adapter/inbound/web/dto/task/UpdateTaskLabelRequest.java new file mode 100644 index 00000000..46e6bab5 --- /dev/null +++ b/src/main/java/clap/server/adapter/inbound/web/dto/task/UpdateTaskLabelRequest.java @@ -0,0 +1,6 @@ +package clap.server.adapter.inbound.web.dto.task; + +public record UpdateTaskLabelRequest( + Long labelId +) { +} diff --git a/src/main/java/clap/server/adapter/inbound/web/task/ManagementTaskController.java b/src/main/java/clap/server/adapter/inbound/web/task/ManagementTaskController.java index ab045008..f72aaf0d 100644 --- a/src/main/java/clap/server/adapter/inbound/web/task/ManagementTaskController.java +++ b/src/main/java/clap/server/adapter/inbound/web/task/ManagementTaskController.java @@ -31,6 +31,7 @@ public class ManagementTaskController { private final UpdateTaskUsecase updateTaskUsecase; private final UpdateTaskStatusUsecase updateTaskStatusUsecase; private final UpdateTaskProcessorUsecase updateTaskProcessorUsecase; + private final UpdateTaskLabelUsecase updateTaskLabelUsecase; private final ApprovalTaskUsecase approvalTaskUsecase; @Operation(summary = "작업 요청 생성") @@ -76,6 +77,16 @@ public ResponseEntity updateTaskProcessor( return ResponseEntity.ok(updateTaskProcessorUsecase.updateTaskProcessor(taskId, userInfo.getUserId(), updateTaskProcessorRequest)); } + @Operation(summary = "작업 구분 변경") + @Secured({"ROLE_MANAGER"}) + @PatchMapping("/label/{taskId}") + public ResponseEntity updateTaskLabel( + @PathVariable Long taskId, + @AuthenticationPrincipal SecurityUserDetails userInfo, + @RequestBody UpdateTaskLabelRequest updateTaskLabelRequest) { + return ResponseEntity.ok(updateTaskLabelUsecase.updateTaskLabel(taskId, userInfo.getUserId(), updateTaskLabelRequest)); + } + @Operation(summary = "작업 승인") @Secured({"ROLE_MANAGER"}) @PostMapping("/approval/{taskId}") diff --git a/src/main/java/clap/server/application/Task/UpdateTaskService.java b/src/main/java/clap/server/application/Task/UpdateTaskService.java index 372f2cba..d8163b6c 100644 --- a/src/main/java/clap/server/application/Task/UpdateTaskService.java +++ b/src/main/java/clap/server/application/Task/UpdateTaskService.java @@ -1,29 +1,26 @@ package clap.server.application.Task; -import clap.server.adapter.inbound.web.dto.task.UpdateTaskRequest; -import clap.server.adapter.inbound.web.dto.task.UpdateTaskResponse; -import clap.server.adapter.inbound.web.dto.task.UpdateTaskStatusRequest; -import clap.server.adapter.inbound.web.dto.task.UpdateTaskProcessorRequest; +import clap.server.adapter.inbound.web.dto.task.*; import clap.server.adapter.outbound.infrastructure.s3.S3UploadAdapter; import clap.server.application.mapper.AttachmentMapper; import clap.server.application.mapper.TaskMapper; import clap.server.application.port.inbound.domain.CategoryService; import clap.server.application.port.inbound.domain.MemberService; import clap.server.application.port.inbound.domain.TaskService; +import clap.server.application.port.inbound.task.UpdateTaskLabelUsecase; import clap.server.application.port.inbound.task.UpdateTaskProcessorUsecase; import clap.server.application.port.inbound.task.UpdateTaskStatusUsecase; import clap.server.application.port.inbound.task.UpdateTaskUsecase; import clap.server.application.port.outbound.task.CommandAttachmentPort; import clap.server.application.port.outbound.task.CommandTaskPort; import clap.server.application.port.outbound.task.LoadAttachmentPort; +import clap.server.application.port.outbound.task.LoadLabelPort; import clap.server.common.annotation.architecture.ApplicationService; import clap.server.domain.model.member.Member; -import clap.server.domain.model.task.Attachment; -import clap.server.domain.model.task.Category; -import clap.server.domain.model.task.FilePath; -import clap.server.domain.model.task.Task; +import clap.server.domain.model.task.*; import clap.server.exception.ApplicationException; +import clap.server.exception.code.LabelErrorCode; import clap.server.exception.code.MemberErrorCode; import clap.server.exception.code.TaskErrorCode; import lombok.RequiredArgsConstructor; @@ -34,17 +31,20 @@ import java.util.List; import java.util.Objects; +import static clap.server.exception.code.MemberErrorCode.ACTIVE_MEMBER_NOT_FOUND; + @ApplicationService @RequiredArgsConstructor @Slf4j -public class UpdateTaskService implements UpdateTaskUsecase, UpdateTaskStatusUsecase, UpdateTaskProcessorUsecase { +public class UpdateTaskService implements UpdateTaskUsecase, UpdateTaskStatusUsecase, UpdateTaskProcessorUsecase, UpdateTaskLabelUsecase { private final MemberService memberService; private final CategoryService categoryService; private final TaskService taskService; private final CommandTaskPort commandTaskPort; private final LoadAttachmentPort loadAttachmentPort; + private final LoadLabelPort loadLabelPort; private final CommandAttachmentPort commandAttachmentPort; private final S3UploadAdapter s3UploadAdapter; @@ -96,6 +96,21 @@ public UpdateTaskResponse updateTaskProcessor(Long taskId, Long userId, UpdateTa // TODO : 알림 생성 로직 및 푸시 알림 로직 추가 } + @Transactional + @Override + public UpdateTaskResponse updateTaskLabel(Long taskId, Long userId, UpdateTaskLabelRequest request) { + Member reviewer = memberService.findActiveMember(userId); + if (!reviewer.isReviewer()) { + throw new ApplicationException(MemberErrorCode.NOT_A_REVIEWER); + } + Task task = taskService.findById(taskId); + Label label = loadLabelPort.findById(request.labelId()).orElseThrow(() -> new ApplicationException(LabelErrorCode.LABEL_NOT_FOUND)); + + task.updateLabel(label); + Task updatetask = commandTaskPort.save(task); + return TaskMapper.toUpdateTaskResponse(updatetask); + } + private void updateAttachments(List attachmentIdsToDelete, List files, Task task) { List attachmentsToDelete = validateAndGetAttachments(attachmentIdsToDelete, task); attachmentsToDelete.forEach(Attachment::softDelete); diff --git a/src/main/java/clap/server/application/port/inbound/task/UpdateTaskLabelUsecase.java b/src/main/java/clap/server/application/port/inbound/task/UpdateTaskLabelUsecase.java new file mode 100644 index 00000000..be5c66dc --- /dev/null +++ b/src/main/java/clap/server/application/port/inbound/task/UpdateTaskLabelUsecase.java @@ -0,0 +1,8 @@ +package clap.server.application.port.inbound.task; + +import clap.server.adapter.inbound.web.dto.task.UpdateTaskLabelRequest; +import clap.server.adapter.inbound.web.dto.task.UpdateTaskResponse; + +public interface UpdateTaskLabelUsecase { + UpdateTaskResponse updateTaskLabel(Long taskId, Long userId, UpdateTaskLabelRequest request); +} diff --git a/src/main/java/clap/server/domain/model/task/Task.java b/src/main/java/clap/server/domain/model/task/Task.java index fb17bcd0..3b0b2814 100644 --- a/src/main/java/clap/server/domain/model/task/Task.java +++ b/src/main/java/clap/server/domain/model/task/Task.java @@ -67,6 +67,10 @@ public void updateProcessor(Member processor) { this.processor = processor; } + public void updateLabel(Label label) { + this.label = label; + } + public void approveTask(Member reviewer, Member processor, LocalDateTime dueDate, Category category, Label label) { this.reviewer = reviewer; this.processor = processor; diff --git a/src/main/java/clap/server/exception/code/LabelErrorCode.java b/src/main/java/clap/server/exception/code/LabelErrorCode.java new file mode 100644 index 00000000..1ba89e99 --- /dev/null +++ b/src/main/java/clap/server/exception/code/LabelErrorCode.java @@ -0,0 +1,16 @@ +package clap.server.exception.code; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum LabelErrorCode implements BaseErrorCode{ + LABEL_NOT_FOUND(HttpStatus.NOT_FOUND, "LABEL_001", "작업 구분을 찾을 수 없습니다."); + + + private final HttpStatus httpStatus; + private final String customCode; + private final String message; +}