diff --git a/src/main/java/clap/server/HealthCheckController.java b/src/main/java/clap/server/HealthCheckController.java index 3d041386..64625979 100644 --- a/src/main/java/clap/server/HealthCheckController.java +++ b/src/main/java/clap/server/HealthCheckController.java @@ -9,7 +9,7 @@ @RequestMapping("/health") public class HealthCheckController { @GetMapping - public ResponseEntity healthcheck(){ + public ResponseEntity healthcheck(){ return ResponseEntity.ok("health check"); } } diff --git a/src/main/java/clap/server/adapter/inbound/web/dto/task/AttachmentResponse.java b/src/main/java/clap/server/adapter/inbound/web/dto/task/AttachmentResponse.java new file mode 100644 index 00000000..d2212586 --- /dev/null +++ b/src/main/java/clap/server/adapter/inbound/web/dto/task/AttachmentResponse.java @@ -0,0 +1,10 @@ +package clap.server.adapter.inbound.web.dto.task; + +import java.time.LocalDateTime; + +public record AttachmentResponse( + String fileName, + String fileSize, + String fileUrl, + LocalDateTime fileUploadedAt + ) {} \ No newline at end of file diff --git a/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskDetailsResponse.java b/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskDetailsResponse.java new file mode 100644 index 00000000..2e243487 --- /dev/null +++ b/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskDetailsResponse.java @@ -0,0 +1,25 @@ +package clap.server.adapter.inbound.web.dto.task; + +import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; + +import java.time.LocalDateTime; +import java.util.List; + +public record FindTaskDetailsResponse( + Long taskId, + String taskCode, + LocalDateTime requestedAt, + LocalDateTime finishedAt, + TaskStatus taskStatus, + String requesterNickName, + String requesterImageUrl, + String processorNickName, + String processorImageUrl, + String mainCategoryName, + String categoryName, + String title, + String description, + List attachmentResponses + + //TODO: taskhistory 및 comment 정보 추가 +) {} diff --git a/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListRequest.java b/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListRequest.java index 5b1112ba..13fe72cb 100644 --- a/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListRequest.java +++ b/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListRequest.java @@ -4,7 +4,7 @@ import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; public record FindTaskListRequest( - Integer term, //조회기간 + Integer term, //조회기간: 1주일, 1개월, 3개월 Long categoryId, Long mainCategoryId, String title, diff --git a/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListResponse.java b/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListResponse.java index 5e5c5af8..152624dd 100644 --- a/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListResponse.java +++ b/src/main/java/clap/server/adapter/inbound/web/dto/task/FindTaskListResponse.java @@ -7,12 +7,12 @@ public record FindTaskListResponse( Long taskId, String taskCode, - LocalDateTime createdAt, + LocalDateTime requestedAt, String mainCategoryName, String categoryName, String title, String processorName, TaskStatus taskStatus, - LocalDateTime completedAt + LocalDateTime finishedAt ) { } diff --git a/src/main/java/clap/server/adapter/inbound/web/task/CreateTaskController.java b/src/main/java/clap/server/adapter/inbound/web/task/CreateTaskController.java index 217327cd..260173f9 100644 --- a/src/main/java/clap/server/adapter/inbound/web/task/CreateTaskController.java +++ b/src/main/java/clap/server/adapter/inbound/web/task/CreateTaskController.java @@ -1,6 +1,7 @@ package clap.server.adapter.inbound.web.task; import clap.server.adapter.inbound.web.dto.task.CreateTaskRequest; +import clap.server.adapter.inbound.web.dto.task.CreateTaskResponse; import clap.server.application.port.inbound.task.CreateTaskUsecase; import clap.server.common.annotation.architecture.WebAdapter; import jakarta.validation.Valid; @@ -19,7 +20,7 @@ public class CreateTaskController { private static final Long memberId = 4L; @PostMapping - public ResponseEntity createTask( + public ResponseEntity createTask( @RequestBody @Valid CreateTaskRequest createTaskRequest){ return ResponseEntity.ok(taskCreateUsecase.createTask(memberId, createTaskRequest)); } diff --git a/src/main/java/clap/server/adapter/inbound/web/task/FindTaskDetailsController.java b/src/main/java/clap/server/adapter/inbound/web/task/FindTaskDetailsController.java new file mode 100644 index 00000000..9732a278 --- /dev/null +++ b/src/main/java/clap/server/adapter/inbound/web/task/FindTaskDetailsController.java @@ -0,0 +1,26 @@ +package clap.server.adapter.inbound.web.task; + +import clap.server.adapter.inbound.web.dto.task.FindTaskDetailsResponse; +import clap.server.application.port.inbound.task.FindTaskDetailsUsecase; +import clap.server.common.annotation.architecture.WebAdapter; +import lombok.RequiredArgsConstructor; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@WebAdapter +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/tasks") +public class FindTaskDetailsController { + private final FindTaskDetailsUsecase taskDetailsUsecase; + private static final Long taskId = 3L; + private static final Long memberId = 4L; + + @GetMapping("/requests/details") + public ResponseEntity> getRequestedTaskDetails(){ + return ResponseEntity.ok(taskDetailsUsecase.findRequestedTaskDetails(memberId, taskId)); + } +} \ No newline at end of file diff --git a/src/main/java/clap/server/adapter/inbound/web/task/FindTaskListController.java b/src/main/java/clap/server/adapter/inbound/web/task/FindTaskListController.java index c0a71e34..0f03e04d 100644 --- a/src/main/java/clap/server/adapter/inbound/web/task/FindTaskListController.java +++ b/src/main/java/clap/server/adapter/inbound/web/task/FindTaskListController.java @@ -1,9 +1,11 @@ package clap.server.adapter.inbound.web.task; import clap.server.adapter.inbound.web.dto.task.FindTaskListRequest; +import clap.server.adapter.inbound.web.dto.task.FindTaskListResponse; import clap.server.application.port.inbound.task.FindTaskListUsecase; import clap.server.common.annotation.architecture.WebAdapter; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.http.ResponseEntity; @@ -19,7 +21,7 @@ public class FindTaskListController { @GetMapping("/requests") - public ResponseEntity getRequestedTaskList( + public ResponseEntity> getRequestedTaskList( @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "20") int size, @RequestBody FindTaskListRequest findTaskListRequest){ diff --git a/src/main/java/clap/server/adapter/outbound/persistense/AttachmentPersistenceAdapter.java b/src/main/java/clap/server/adapter/outbound/persistense/AttachmentPersistenceAdapter.java index 8ac0e01e..f0f8d901 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/AttachmentPersistenceAdapter.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/AttachmentPersistenceAdapter.java @@ -4,18 +4,20 @@ import clap.server.adapter.outbound.persistense.mapper.AttachmentPersistenceMapper; import clap.server.adapter.outbound.persistense.repository.task.AttachmentRepository; import clap.server.application.port.outbound.task.CommandAttachmentPort; +import clap.server.application.port.outbound.task.LoadAttachmentPort; import clap.server.common.annotation.architecture.PersistenceAdapter; import clap.server.domain.model.task.Attachment; import lombok.RequiredArgsConstructor; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; @PersistenceAdapter @RequiredArgsConstructor -public class AttachmentPersistenceAdapter implements CommandAttachmentPort { +public class AttachmentPersistenceAdapter implements CommandAttachmentPort, LoadAttachmentPort { private final AttachmentRepository attachmentRepository; private final AttachmentPersistenceMapper attachmentPersistenceMapper; @@ -34,4 +36,12 @@ public void saveAll(List attachments) { .collect(Collectors.toList()); attachmentRepository.saveAll(attachmentEntities); } + + @Override + public List findAllByTaskId(final Long taskId) { + List attachmentEntities = attachmentRepository.findAllByTask_TaskId(taskId); + return attachmentEntities.stream() + .map(attachmentPersistenceMapper::toDomain) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/AttachmentEntity.java b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/AttachmentEntity.java index f25e3564..f350a3db 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/AttachmentEntity.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/AttachmentEntity.java @@ -28,7 +28,7 @@ public class AttachmentEntity extends BaseTimeEntity { @JoinColumn(name = "task_id") private TaskEntity task; - @ManyToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "comment_id") private CommentEntity comment; diff --git a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskEntity.java b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskEntity.java index ad5df89e..21ffde35 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskEntity.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskEntity.java @@ -10,6 +10,8 @@ import lombok.experimental.SuperBuilder; import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; @Entity @Table(name = "task") @@ -62,5 +64,4 @@ public class TaskEntity extends BaseTimeEntity { @Column private LocalDateTime completedAt; - } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskHistoryEntity.java b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskHistoryEntity.java index cbb99cdc..709572c6 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskHistoryEntity.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskHistoryEntity.java @@ -26,7 +26,7 @@ public class TaskHistoryEntity extends BaseTimeEntity { @Embedded private TaskModificationInfo taskModificationInfo; - @ManyToOne(fetch = FetchType.LAZY) + @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "comment_id") private CommentEntity comment; } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskModificationInfo.java b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskModificationInfo.java index a953dc0e..5ee1dcf1 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskModificationInfo.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/entity/task/TaskModificationInfo.java @@ -14,12 +14,12 @@ public class TaskModificationInfo { private TaskEntity task; @Column(name = "modified_field") - private String modifiedField; + private String modifiedField; //처리자(requestor) / 요청상태(taskStatus) -> task 상태 변경 혹은 처리 변경시에 taskhistory 테이블도 변경해야함 @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "modified_member_id") + @JoinColumn(name = "modified_member_id") //처리자가 바뀌는 경우 private MemberEntity member; @Column(name = "new_value") - private String newValue; + private String newValue; //상태가 바뀌는 경우 } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/repository/task/AttachmentRepository.java b/src/main/java/clap/server/adapter/outbound/persistense/repository/task/AttachmentRepository.java index 73667422..027ae3e0 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/repository/task/AttachmentRepository.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/repository/task/AttachmentRepository.java @@ -3,6 +3,10 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; +import java.util.List; + @Repository public interface AttachmentRepository extends JpaRepository { + List findAllByTask_TaskId(Long taskId); + } \ No newline at end of file diff --git a/src/main/java/clap/server/application/CreateTaskService.java b/src/main/java/clap/server/application/Task/CreateTaskService.java similarity index 84% rename from src/main/java/clap/server/application/CreateTaskService.java rename to src/main/java/clap/server/application/Task/CreateTaskService.java index ce35926b..2ff71a34 100644 --- a/src/main/java/clap/server/application/CreateTaskService.java +++ b/src/main/java/clap/server/application/Task/CreateTaskService.java @@ -1,9 +1,10 @@ -package clap.server.application; +package clap.server.application.Task; import clap.server.adapter.inbound.web.dto.task.CreateTaskRequest; import clap.server.adapter.inbound.web.dto.task.CreateTaskResponse; 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.task.CreateTaskUsecase; @@ -21,8 +22,6 @@ import java.util.List; -import static clap.server.application.mapper.TaskMapper.toCreateTaskResponse; -import static clap.server.application.mapper.TaskMapper.toTask; @ApplicationService @RequiredArgsConstructor @@ -40,12 +39,12 @@ public CreateTaskResponse createTask(Long requesterId, CreateTaskRequest createT Member member = memberService.findActiveMember(requesterId); Category category = categoryService.findById(createTaskRequest.categoryId()); - Task task = toTask(member, category, createTaskRequest.title(), createTaskRequest.description()); + Task task = TaskMapper.toTask(member, category, createTaskRequest.title(), createTaskRequest.description()); Task savedTask = commandTaskPort.save(task); List attachments = AttachmentMapper.toAttachments(savedTask, createTaskRequest.fileUrls()); commandAttachmentPort.saveAll(attachments); - return toCreateTaskResponse(savedTask); + return TaskMapper.toCreateTaskResponse(savedTask); } } \ No newline at end of file diff --git a/src/main/java/clap/server/application/Task/FindTaskDetailsService.java b/src/main/java/clap/server/application/Task/FindTaskDetailsService.java new file mode 100644 index 00000000..6c1c5f94 --- /dev/null +++ b/src/main/java/clap/server/application/Task/FindTaskDetailsService.java @@ -0,0 +1,38 @@ +package clap.server.application.Task; + +import clap.server.adapter.inbound.web.dto.task.FindTaskDetailsResponse; +import clap.server.adapter.outbound.persistense.entity.task.TaskEntity; +import clap.server.application.mapper.TaskMapper; +import clap.server.application.port.inbound.domain.MemberService; +import clap.server.application.port.inbound.task.FindTaskDetailsUsecase; +import clap.server.application.port.outbound.task.LoadAttachmentPort; +import clap.server.application.port.outbound.task.LoadTaskPort; +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.Task; +import clap.server.exception.ApplicationException; +import clap.server.exception.code.TaskErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + + +@ApplicationService +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class FindTaskDetailsService implements FindTaskDetailsUsecase { + private final MemberService memberService; + private final LoadTaskPort loadTaskPort; + private final LoadAttachmentPort loadAttachmentPort; + + @Override + public List findRequestedTaskDetails(final Long requesterId, final Long taskId) { + memberService.findActiveMember(requesterId); + Task task = loadTaskPort.findById(taskId) + .orElseThrow(()-> new ApplicationException(TaskErrorCode.TASK_NOT_FOUND)); + List attachments = loadAttachmentPort.findAllByTaskId(taskId); + return TaskMapper.toFindTaskDetailResponses(task, attachments); + } +} diff --git a/src/main/java/clap/server/application/FindTasklistService.java b/src/main/java/clap/server/application/Task/FindTaskListService.java similarity index 92% rename from src/main/java/clap/server/application/FindTasklistService.java rename to src/main/java/clap/server/application/Task/FindTaskListService.java index ea37d907..52c1af1f 100644 --- a/src/main/java/clap/server/application/FindTasklistService.java +++ b/src/main/java/clap/server/application/Task/FindTaskListService.java @@ -1,4 +1,4 @@ -package clap.server.application; +package clap.server.application.Task; import clap.server.adapter.inbound.web.dto.task.FindTaskListRequest; import clap.server.adapter.inbound.web.dto.task.FindTaskListResponse; @@ -21,7 +21,7 @@ @ApplicationService @RequiredArgsConstructor @Transactional(readOnly = true) -public class FindTasklistService implements FindTaskListUsecase { +public class FindTaskListService implements FindTaskListUsecase { private final MemberService memberService; private final LoadTaskPort loadTaskPort; diff --git a/src/main/java/clap/server/application/mapper/AttachmentMapper.java b/src/main/java/clap/server/application/mapper/AttachmentMapper.java index 242732c4..a048136c 100644 --- a/src/main/java/clap/server/application/mapper/AttachmentMapper.java +++ b/src/main/java/clap/server/application/mapper/AttachmentMapper.java @@ -1,5 +1,7 @@ package clap.server.application.mapper; +import clap.server.adapter.inbound.web.dto.task.AttachmentResponse; +import clap.server.adapter.inbound.web.dto.task.FindTaskDetailsResponse; import clap.server.domain.model.task.Attachment; import clap.server.domain.model.task.Task; diff --git a/src/main/java/clap/server/application/mapper/TaskMapper.java b/src/main/java/clap/server/application/mapper/TaskMapper.java index 6742a58a..27b36709 100644 --- a/src/main/java/clap/server/application/mapper/TaskMapper.java +++ b/src/main/java/clap/server/application/mapper/TaskMapper.java @@ -1,13 +1,19 @@ package clap.server.application.mapper; +import clap.server.adapter.inbound.web.dto.task.AttachmentResponse; import clap.server.adapter.inbound.web.dto.task.CreateTaskResponse; +import clap.server.adapter.inbound.web.dto.task.FindTaskDetailsResponse; import clap.server.adapter.inbound.web.dto.task.FindTaskListResponse; import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; 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.Task; +import java.util.List; +import java.util.stream.Collectors; + public class TaskMapper { private TaskMapper() { throw new IllegalArgumentException(); @@ -41,4 +47,35 @@ public static FindTaskListResponse toFindTaskListResponse(Task task) { task.getCompletedAt() ); } + + public static List toFindTaskDetailResponses(Task task, List attachments){ + + List attachmentResponses = attachments.stream() + .map(attachment -> new AttachmentResponse( + attachment.getOriginalName(), + attachment.getFileSize(), + attachment.getFileUrl(), + attachment.getCreatedAt() + )) + .collect(Collectors.toList()); + + FindTaskDetailsResponse response = new FindTaskDetailsResponse( + task.getTaskId(), + task.getTaskCode(), + task.getCreatedAt(), + task.getCompletedAt(), + task.getTaskStatus(), + task.getRequester().getMemberInfo().getNickname(), + task.getRequester().getImageUrl(), + task.getProcessor() != null ? task.getProcessor().getMemberInfo().getNickname() : null, + task.getProcessor() != null ? task.getProcessor().getImageUrl() : null, + task.getCategory().getMainCategory().getName(), + task.getCategory().getName(), + task.getTitle(), + task.getDescription(), + attachmentResponses + ); + + return List.of(response); + } } diff --git a/src/main/java/clap/server/application/port/inbound/task/FindTaskDetailsUsecase.java b/src/main/java/clap/server/application/port/inbound/task/FindTaskDetailsUsecase.java new file mode 100644 index 00000000..0006c376 --- /dev/null +++ b/src/main/java/clap/server/application/port/inbound/task/FindTaskDetailsUsecase.java @@ -0,0 +1,9 @@ +package clap.server.application.port.inbound.task; + +import clap.server.adapter.inbound.web.dto.task.FindTaskDetailsResponse; + +import java.util.List; + +public interface FindTaskDetailsUsecase { + List findRequestedTaskDetails(Long memberId, Long taskId); +} diff --git a/src/main/java/clap/server/application/port/outbound/task/LoadAttachmentPort.java b/src/main/java/clap/server/application/port/outbound/task/LoadAttachmentPort.java new file mode 100644 index 00000000..bd8d8df3 --- /dev/null +++ b/src/main/java/clap/server/application/port/outbound/task/LoadAttachmentPort.java @@ -0,0 +1,10 @@ +package clap.server.application.port.outbound.task; + +import clap.server.domain.model.task.Attachment; + +import java.util.List; + + +public interface LoadAttachmentPort { + List findAllByTaskId(Long task); +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d89f2b6d..90830453 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -13,7 +13,8 @@ spring: elasticsearch: uris: ${ELASTIC_URI:127.0.0.1:9200} -web.resources.add-mappings: false + web.resources.add-mappings: false + server: port: ${APPLICATION_PORT:8080} diff --git a/src/test/java/clap/server/task/FindTaskDetailsUsecase.java b/src/test/java/clap/server/task/FindTaskDetailsUsecase.java new file mode 100644 index 00000000..6fc35e9d --- /dev/null +++ b/src/test/java/clap/server/task/FindTaskDetailsUsecase.java @@ -0,0 +1,4 @@ +package clap.server.task; + +public class FindTaskDetailsUsecase { +}