Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package clap.server.adapter.inbound.web.dto.task.response;

import clap.server.adapter.outbound.persistense.entity.task.constant.TaskHistoryType;

import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;

public record FindTaskHistoryResponse(
List<TaskHistoryResponse> histories
) {
public static record TaskHistoryResponse(
Long historyId,
LocalDate date,
LocalTime time,
TaskHistoryType taskHistoryType,
Details details
) {}

public static record Details(
TaskDetails taskDetails,
CommentDetails commentDetails,
CommentFileDetails commentFileDetails
) {}

public static record TaskDetails(
String newValue
) {}

public static record CommentDetails(
String nickName,
String profileImageUrl,
boolean isModified,
String comment
) {}

public static record CommentFileDetails(
String nickName,
String profileImageUrl,
boolean isModified,
String fileName,
String url,
String size
) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,25 @@
import clap.server.application.port.inbound.task.ApprovalTaskUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@Tag(name = "02. Task [조회]", description = "작업 조회 API")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks/form")
@RequestMapping("/api/tasks")
public class FindApprovalTaskFormController {

private final ApprovalTaskUsecase approvalTaskUsecase;

@Operation(summary = "요청 승인 폼 조회")
@Secured("ROLE_MANAGER")
@GetMapping("/{taskId}")
@GetMapping("/approval/{taskId}")
public ResponseEntity<FindApprovalFormResponse> findTaskForm(
@PathVariable Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

@Tag(name = "작업 조회")
@Tag(name = "02. Task [조회]", description = "작업 조회 API")
@WebAdapter
@RestController
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package clap.server.adapter.inbound.web.task;

import clap.server.adapter.inbound.security.SecurityUserDetails;
import clap.server.adapter.inbound.web.dto.task.FindTaskDetailsForManagerResponse;
import clap.server.adapter.inbound.web.dto.task.response.FindTaskHistoryResponse;
import clap.server.application.port.inbound.task.FindTaskHistoriesUsecase;
import clap.server.common.annotation.architecture.WebAdapter;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@Tag(name = "02. Task [조회]", description = "작업 조회 API")
@WebAdapter
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/tasks")
public class FindTaskHistoryController {

private final FindTaskHistoriesUsecase findTaskHistoriesUsecase;

@Operation(summary = "작업 히스토리 조회")
@Secured({"ROLE_MANAGER","ROLE_USER"})
@GetMapping("/histories/{taskId}")
public ResponseEntity<FindTaskHistoryResponse> findTaskHistories(
@PathVariable Long taskId,
@AuthenticationPrincipal SecurityUserDetails userInfo) {
return ResponseEntity.ok(findTaskHistoriesUsecase.findTaskHistories(userInfo.getUserId(), taskId));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,19 @@ public List<Attachment> findAllByTaskIdAndCommentIsNull(final Long taskId) {
.collect(Collectors.toList());
}

@Override
public List<Attachment> findAllByTaskIdAndCommentIsNullAndAttachmentId(final Long taskId, final List<Long> attachmentIds) {
List<AttachmentEntity> attachmentEntities = attachmentRepository.findAllByTask_TaskIdAndCommentIsNullAndIsDeletedIsFalseAndAttachmentIdIn(taskId, attachmentIds);
return attachmentEntities.stream()
.map(attachmentPersistenceMapper::toDomain)
.collect(Collectors.toList());
}

@Override
public List<Attachment> findAllByTaskIdAndCommentIsNotNull(final Long taskId) {
List<AttachmentEntity> attachmentEntities = attachmentRepository.findAllByTask_TaskIdAndCommentIsNotNullAndIsDeletedIsFalse(taskId);
return attachmentEntities.stream()
.map(attachmentPersistenceMapper::toDomain)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package clap.server.adapter.outbound.persistense;

import clap.server.application.port.outbound.task.LoadCommentPort;
import clap.server.domain.model.task.Comment;

import java.util.Optional;

public class CommentPersistenceAdapter implements LoadCommentPort {
@Override
public Optional<Comment> findById(Long id) {
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
package clap.server.adapter.outbound.persistense;


import clap.server.adapter.outbound.persistense.entity.task.TaskHistoryEntity;
import clap.server.adapter.outbound.persistense.mapper.TaskHistoryPersistenceMapper;
import clap.server.adapter.outbound.persistense.repository.task.TaskHistoryRepository;
import clap.server.application.port.outbound.task.LoadTaskHistoryPort;
import clap.server.common.annotation.architecture.PersistenceAdapter;

import clap.server.domain.model.task.TaskHistory;
import lombok.RequiredArgsConstructor;




import java.util.List;


@PersistenceAdapter
@RequiredArgsConstructor
public class TaskHistoryPersistenceAdapter implements LoadTaskHistoryPort {

private final TaskHistoryRepository taskHistoryRepository;
private final TaskHistoryPersistenceMapper taskHistoryPersistenceMapper;

@Override
public List<TaskHistory> findAllTaskHistoriesByTaskId(Long taskId) {
return taskHistoryRepository.findAllTaskHistoriesByTaskId(taskId)
.stream()
.map(taskHistoryPersistenceMapper::toDomain)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class CommentEntity extends BaseTimeEntity {
@JoinColumn(name = "task_id", nullable = false)
private TaskEntity task;

@Column(name = "content", nullable = false) //nullable false인 이유
@Column(name = "content")
private String content;

@Column(name = "is_modified", nullable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ public class TaskModificationInfo {
private TaskEntity task;

@Column(name = "modified_field")
private String modifiedField; //처리자(requestor) / 요청상태(taskStatus) -> task 상태 변경 혹은 처리 변경시에 taskhistory 테이블도 변경해야함
private String modifiedField; //TODO: 속성 필요성 검토

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "modified_member_id") //처리자가 바뀌는 경우
@JoinColumn(name = "modified_member_id")
private MemberEntity modifiedMember;

@Column(name = "new_value")
private String newValue; //상태가 바뀌는 경우
private String newValue; //TODO: 속성 필요성 검토
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
public interface AttachmentRepository extends JpaRepository<AttachmentEntity, Long> {
List<AttachmentEntity> findAllByTask_TaskIdAndCommentIsNullAndIsDeletedIsFalse(Long taskId);
List<AttachmentEntity> findAllByTask_TaskIdAndCommentIsNullAndIsDeletedIsFalseAndAttachmentIdIn(Long task_taskId, List<Long> attachmentId);

List<AttachmentEntity> findAllByTask_TaskIdAndCommentIsNotNullAndIsDeletedIsFalse(Long taskId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package clap.server.adapter.outbound.persistense.repository.task;

import clap.server.adapter.outbound.persistense.entity.task.TaskHistoryEntity;

import java.util.List;

public interface TaskHistoryCustomRepository {
List<TaskHistoryEntity> findAllTaskHistoriesByTaskId(Long taskId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package clap.server.adapter.outbound.persistense.repository.task;

import clap.server.adapter.outbound.persistense.entity.task.QCommentEntity;
import clap.server.adapter.outbound.persistense.entity.task.QTaskHistoryEntity;
import clap.server.adapter.outbound.persistense.entity.task.TaskHistoryEntity;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;



import java.util.List;

@RequiredArgsConstructor
public class TaskHistoryCustomRepositoryImpl implements TaskHistoryCustomRepository {

private final JPAQueryFactory queryFactory;

@Override
public List<TaskHistoryEntity> findAllTaskHistoriesByTaskId(Long taskId) {
QTaskHistoryEntity taskHistory = QTaskHistoryEntity.taskHistoryEntity;
QCommentEntity comment = QCommentEntity.commentEntity;

return queryFactory.selectFrom(taskHistory)
.leftJoin(taskHistory.comment, comment).fetchJoin() // TaskHistory와 Comment를 조인
.where(
// Comment가 없는 경우에는 TaskModificationInfo의 Task 기준
taskHistory.comment.isNull()
.and(taskHistory.taskModificationInfo.task.taskId.eq(taskId))
.or(
// Comment가 있는 경우에는 Comment의 Task 기준
taskHistory.comment.isNotNull()
.and(comment.task.taskId.eq(taskId))
)
)
.orderBy(taskHistory.taskHistoryId.asc()) // taskHistoryId로 정렬
.fetch();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface TaskHistoryRepository extends JpaRepository<TaskHistoryEntity, Long> {
public interface TaskHistoryRepository extends JpaRepository<TaskHistoryEntity, Long> , TaskHistoryCustomRepository{
List<TaskHistoryEntity> findAllByTaskModificationInfo_Task_TaskId(Long taskId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package clap.server.application.mapper;

import clap.server.adapter.inbound.web.dto.task.response.FindTaskHistoryResponse;

import clap.server.domain.model.task.Attachment;
import clap.server.domain.model.task.TaskHistory;

import java.util.List;


public class TaskHistoryMapper {

private TaskHistoryMapper() {
throw new IllegalArgumentException();
}

public static FindTaskHistoryResponse toFindTaskHistoryResponse(List<TaskHistory> taskHistories, List<Attachment> attachments) {
List<FindTaskHistoryResponse.TaskHistoryResponse> historyResponses = taskHistories.stream()
.map(taskHistory -> {
FindTaskHistoryResponse.Details details =
switch (taskHistory.getType()) {
case PROCESSOR_CHANGED, PROCESSOR_ASSIGNED -> new FindTaskHistoryResponse.Details(
new FindTaskHistoryResponse.TaskDetails(
taskHistory.getTaskModificationInfo().getModifiedMember().getNickname()
),
null,
null
);
case STATUS_SWITCHED -> new FindTaskHistoryResponse.Details(
new FindTaskHistoryResponse.TaskDetails(
taskHistory.getTaskModificationInfo().getTask().getTaskStatus().getDescription()
),
null,
null
);
case COMMENT -> new FindTaskHistoryResponse.Details(
null,
new FindTaskHistoryResponse.CommentDetails(
taskHistory.getComment().getMember().getNickname(),
taskHistory.getComment().getMember().getImageUrl(),
taskHistory.getComment().isModified(),
taskHistory.getComment().getContent()
),
null
);
case COMMENT_FILE -> new FindTaskHistoryResponse.Details(
null,
null,
attachments.stream()
.filter(attachment -> attachment.getComment().getCommentId().equals(taskHistory.getComment().getCommentId()))
.findFirst()
.map(attachment -> new FindTaskHistoryResponse.CommentFileDetails(
taskHistory.getComment().getMember().getNickname(),
taskHistory.getComment().getMember().getImageUrl(),
taskHistory.getComment().isModified(),
attachment.getOriginalName(),
attachment.getFileUrl(),
attachment.getFileSize()
))
.orElse(null)
);
};
return new FindTaskHistoryResponse.TaskHistoryResponse(
taskHistory.getTaskHistoryId(),
taskHistory.getUpdatedAt().toLocalDate(),
taskHistory.getUpdatedAt().toLocalTime(),
taskHistory.getType(),
details
);
})
.toList();
return new FindTaskHistoryResponse(historyResponses);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package clap.server.application.port.inbound.task;

import clap.server.adapter.inbound.web.dto.task.response.FindTaskHistoryResponse;

public interface FindTaskHistoriesUsecase {
FindTaskHistoryResponse findTaskHistories(Long userId, Long taskId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


public interface LoadAttachmentPort {
List<Attachment> findAllByTaskIdAndCommentIsNull(Long task);
List<Attachment> findAllByTaskIdAndCommentIsNull(Long taskId);
List<Attachment> findAllByTaskIdAndCommentIsNullAndAttachmentId(Long taskId, List<Long> attachmentIds);
List<Attachment> findAllByTaskIdAndCommentIsNotNull(Long taskId);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package clap.server.application.port.outbound.task;


import clap.server.domain.model.task.TaskHistory;

import java.util.List;

public interface LoadTaskHistoryPort {
List<TaskHistory> findAllTaskHistoriesByTaskId(Long taskId);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package clap.server.application.Task;
package clap.server.application.service.task;

import clap.server.adapter.inbound.web.dto.task.ApprovalTaskRequest;
import clap.server.adapter.inbound.web.dto.task.ApprovalTaskResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package clap.server.application.Task;
package clap.server.application.service.task;

import clap.server.adapter.inbound.web.dto.notification.SseRequest;
import clap.server.adapter.inbound.web.dto.task.CreateTaskRequest;
Expand Down
Loading