diff --git a/src/main/java/clap/server/adapter/inbound/web/history/CommandCommentController.java b/src/main/java/clap/server/adapter/inbound/web/history/CommandCommentController.java index 074e468a..7c9b7af8 100644 --- a/src/main/java/clap/server/adapter/inbound/web/history/CommandCommentController.java +++ b/src/main/java/clap/server/adapter/inbound/web/history/CommandCommentController.java @@ -36,8 +36,8 @@ public void editComment( editCommentUsecase.editComment(userInfo.getUserId(), commentId, request); } - @Operation(summary = "댓글 삭제", description = "첨부파일 댓글일 경우 request body에 삭제할 파일 ID를 리스트로 전달") - @Parameter(name = "commentId", description = "수정할 댓글 고유 ID", required = true, in = ParameterIn.PATH) + @Operation(summary = "댓글 삭제") + @Parameter(name = "commentId", description = "삭제할 댓글 고유 ID", required = true, in = ParameterIn.PATH) @DeleteMapping("/{commentId}") @Secured({"ROLE_MANAGER", "ROLE_USER"}) public void deleteComment( diff --git a/src/main/java/clap/server/adapter/inbound/web/history/FindTaskHistoryController.java b/src/main/java/clap/server/adapter/inbound/web/history/FindTaskHistoryController.java index 975171bc..83c9105c 100644 --- a/src/main/java/clap/server/adapter/inbound/web/history/FindTaskHistoryController.java +++ b/src/main/java/clap/server/adapter/inbound/web/history/FindTaskHistoryController.java @@ -2,10 +2,8 @@ import clap.server.adapter.inbound.security.service.SecurityUserDetails; import clap.server.adapter.inbound.web.dto.history.response.FindTaskHistoryResponse; -import clap.server.adapter.outbound.persistense.entity.log.constant.LogStatus; import clap.server.application.port.inbound.history.FindTaskHistoriesUsecase; import clap.server.common.annotation.architecture.WebAdapter; -import clap.server.common.annotation.log.LogType; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -15,7 +13,6 @@ 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 = "03. Task History") 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 1ca60f95..97ac1acd 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 @@ -1,6 +1,7 @@ package clap.server.adapter.outbound.persistense.entity.task; import clap.server.adapter.outbound.persistense.entity.common.BaseTimeEntity; +import clap.server.adapter.outbound.persistense.entity.member.MemberEntity; import clap.server.adapter.outbound.persistense.entity.task.constant.TaskHistoryType; import jakarta.persistence.*; import lombok.AccessLevel; @@ -8,7 +9,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; -import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.SQLRestriction; @Entity @@ -30,6 +30,10 @@ public class TaskHistoryEntity extends BaseTimeEntity { @Embedded private TaskModificationInfo taskModificationInfo; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "modified_member_id") + private MemberEntity modifiedMember; + @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 e7679315..fda49bd6 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 @@ -1,7 +1,9 @@ package clap.server.adapter.outbound.persistense.entity.task; -import clap.server.adapter.outbound.persistense.entity.member.MemberEntity; -import jakarta.persistence.*; +import jakarta.persistence.Embeddable; +import jakarta.persistence.FetchType; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -17,10 +19,6 @@ public class TaskModificationInfo { @JoinColumn(name = "task_id") private TaskEntity task; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "modified_member_id") - private MemberEntity modifiedMember; - @JoinColumn(name = "modified_status") private String modifiedStatus; } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/mapper/CommentPersistenceMapper.java b/src/main/java/clap/server/adapter/outbound/persistense/mapper/CommentPersistenceMapper.java index 546bf750..31f18a2d 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/mapper/CommentPersistenceMapper.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/mapper/CommentPersistenceMapper.java @@ -1,24 +1,34 @@ package clap.server.adapter.outbound.persistense.mapper; import clap.server.adapter.outbound.persistense.entity.task.CommentEntity; - -import clap.server.adapter.outbound.persistense.mapper.common.PersistenceMapper; - +import clap.server.domain.model.member.Member; import clap.server.domain.model.task.Comment; - +import org.hibernate.Hibernate; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.springframework.beans.factory.annotation.Autowired; @Mapper(componentModel = "spring", uses = {MemberPersistenceMapper.class, TaskPersistenceMapper.class}) -public interface CommentPersistenceMapper extends PersistenceMapper { +public abstract class CommentPersistenceMapper { + + @Autowired + MemberPersistenceMapper memberPersistenceMapper; - @Override @Mapping(source = "modified", target = "isModified") @Mapping(source = "deleted", target = "isDeleted") - Comment toDomain(final CommentEntity entity); + @Mapping(target = "member", expression = "java(mapMember(entity))") + @Mapping(target = "task", ignore = true) + public abstract Comment toDomain(final CommentEntity entity); - @Override @Mapping(source = "modified", target = "isModified") @Mapping(source = "deleted", target = "isDeleted") - CommentEntity toEntity(final Comment domain); + public abstract CommentEntity toEntity(final Comment domain); + + protected Member mapMember(CommentEntity entity) { + if (entity == null || entity.getMember() == null || !Hibernate.isInitialized(entity.getMember())) { + return null; + } + return memberPersistenceMapper.toDomain(entity.getMember()); + } + } diff --git a/src/main/java/clap/server/adapter/outbound/persistense/repository/history/TaskHistoryCustomRepositoryImpl.java b/src/main/java/clap/server/adapter/outbound/persistense/repository/history/TaskHistoryCustomRepositoryImpl.java index 4de37a20..9ec01e87 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/repository/history/TaskHistoryCustomRepositoryImpl.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/repository/history/TaskHistoryCustomRepositoryImpl.java @@ -1,5 +1,6 @@ package clap.server.adapter.outbound.persistense.repository.history; +import clap.server.adapter.outbound.persistense.entity.member.QMemberEntity; 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; @@ -18,9 +19,11 @@ public class TaskHistoryCustomRepositoryImpl implements TaskHistoryCustomReposit public List findAllTaskHistoriesByTaskId(Long taskId) { QTaskHistoryEntity taskHistory = QTaskHistoryEntity.taskHistoryEntity; QCommentEntity comment = QCommentEntity.commentEntity; + QMemberEntity member = QMemberEntity.memberEntity; return queryFactory.selectFrom(taskHistory) - .leftJoin(taskHistory.comment, comment).fetchJoin() // TaskHistory와 Comment를 조인 + .leftJoin(taskHistory.comment, comment).fetchJoin() + .leftJoin(taskHistory.modifiedMember, member).fetchJoin() .where( // Comment가 없는 경우에는 TaskModificationInfo의 Task 기준 taskHistory.comment.isNull() diff --git a/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepository.java b/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepository.java index 3fb983fd..7d6341f8 100644 --- a/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepository.java +++ b/src/main/java/clap/server/adapter/outbound/persistense/repository/task/TaskCustomRepository.java @@ -1,9 +1,8 @@ package clap.server.adapter.outbound.persistense.repository.task; -import clap.server.adapter.inbound.web.dto.task.request.FilterTaskListRequest; import clap.server.adapter.inbound.web.dto.task.request.FilterTaskBoardRequest; +import clap.server.adapter.inbound.web.dto.task.request.FilterTaskListRequest; import clap.server.adapter.inbound.web.dto.task.request.FilterTeamStatusRequest; -import clap.server.adapter.inbound.web.dto.task.response.TeamTaskResponse; import clap.server.adapter.outbound.persistense.entity.task.TaskEntity; import clap.server.adapter.outbound.persistense.entity.task.constant.TaskStatus; import org.springframework.data.domain.Page; diff --git a/src/main/java/clap/server/application/mapper/response/TaskHistoryResponseMapper.java b/src/main/java/clap/server/application/mapper/response/TaskHistoryResponseMapper.java index e3ac847f..21d6f8fe 100644 --- a/src/main/java/clap/server/application/mapper/response/TaskHistoryResponseMapper.java +++ b/src/main/java/clap/server/application/mapper/response/TaskHistoryResponseMapper.java @@ -21,7 +21,7 @@ public static FindTaskHistoryResponse toFindTaskHistoryResponse(List new FindTaskHistoryResponse.Details( new FindTaskHistoryResponse.TaskDetails( - taskHistory.getTaskModificationInfo().getModifiedMember().getNickname() + taskHistory.getModifiedMember().getNickname() ), null, null @@ -37,8 +37,8 @@ public static FindTaskHistoryResponse toFindTaskHistoryResponse(List new DomainException(TaskErrorCode.TASK_NOT_FOUND)); + .orElseThrow(()-> new ApplicationException(TaskErrorCode.TASK_NOT_FOUND)); List taskHistories = loadTaskHistoryPort.findAllTaskHistoriesByTaskId(task.getTaskId()); return TaskHistoryResponseMapper.toFindTaskHistoryResponse(taskHistories); } diff --git a/src/main/java/clap/server/application/service/history/PostCommentService.java b/src/main/java/clap/server/application/service/history/PostCommentService.java index 24c6c9db..28f8974a 100644 --- a/src/main/java/clap/server/application/service/history/PostCommentService.java +++ b/src/main/java/clap/server/application/service/history/PostCommentService.java @@ -9,17 +9,15 @@ import clap.server.application.port.inbound.history.SaveCommentAttachmentUsecase; import clap.server.application.port.inbound.history.SaveCommentUsecase; import clap.server.application.port.outbound.s3.S3UploadPort; -import clap.server.application.port.outbound.task.CommandAttachmentPort; import clap.server.application.port.outbound.task.CommandCommentPort; import clap.server.application.port.outbound.taskhistory.CommandTaskHistoryPort; import clap.server.application.service.webhook.SendNotificationService; import clap.server.common.annotation.architecture.ApplicationService; +import clap.server.common.constants.FilePathConstants; import clap.server.domain.model.member.Member; -import clap.server.domain.model.task.Attachment; import clap.server.domain.model.task.Comment; import clap.server.domain.model.task.Task; import clap.server.domain.model.task.TaskHistory; -import clap.server.common.constants.FilePathConstants; import clap.server.domain.policy.task.TaskCommentPolicy; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -53,7 +51,7 @@ public void save(Long memberId, Long taskId, CreateCommentRequest request) { Comment comment = Comment.createComment(member, task, request.content(), null, null, null); Comment savedComment = commandCommentPort.saveComment(comment); - TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.COMMENT, task, null, member, savedComment); + TaskHistory taskHistory = TaskHistory.createCommentTaskHistory(TaskHistoryType.COMMENT, member, savedComment); commandTaskHistoryPort.save(taskHistory); Member processor = task.getProcessor(); @@ -76,10 +74,10 @@ public void saveCommentAttachment(Long memberId, Long taskId, MultipartFile file String fileUrl = s3UploadPort.uploadSingleFile(FilePathConstants.TASK_COMMENT, file); String fileName = file.getOriginalFilename(); - Comment comment = Comment.createComment(member, task, null, fileName, fileUrl, formatFileSize(file.getSize())); + Comment comment = Comment.createComment(member, task, null, fileName, fileUrl, formatFileSize(file.getSize())); Comment savedComment = commandCommentPort.saveComment(comment); - TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.COMMENT_FILE, null, null, null, savedComment); + TaskHistory taskHistory = TaskHistory.createCommentTaskHistory(TaskHistoryType.COMMENT_FILE, member, savedComment); commandTaskHistoryPort.save(taskHistory); Member processor = task.getProcessor(); @@ -93,14 +91,6 @@ public void saveCommentAttachment(Long memberId, Long taskId, MultipartFile file } - @Deprecated -// private String saveAttachment(MultipartFile file, Task task) { -// String fileUrl = s3UploadPort.uploadSingleFile(FilePathConstants.TASK_COMMENT, file); -// Attachment attachment = Attachment.createCommentAttachment(task, null, file.getOriginalFilename(), fileUrl, file.getSize()); -// commandAttachmentPort.save(attachment); -// return file.getOriginalFilename(); -// } - private void publishNotification(Member receiver, Task task, String message, String commenterName) { boolean isManager = receiver.getMemberInfo().getRole() == MemberRole.ROLE_MANAGER; sendNotificationService.sendPushNotification(receiver, NotificationType.COMMENT, task, message, null, commenterName, isManager); diff --git a/src/main/java/clap/server/application/service/task/ApprovalTaskService.java b/src/main/java/clap/server/application/service/task/ApprovalTaskService.java index 9bd42977..7d14436b 100644 --- a/src/main/java/clap/server/application/service/task/ApprovalTaskService.java +++ b/src/main/java/clap/server/application/service/task/ApprovalTaskService.java @@ -59,7 +59,7 @@ public ApprovalTaskResponse approvalTaskByReviewer(Long reviewerId, Long taskId, updateProcessorTaskCountService.handleTaskStatusChange(processor, TaskStatus.REQUESTED, TaskStatus.IN_PROGRESS); task.approveTask(reviewer, processor, approvalTaskRequest.dueDate(), category, label); - TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.PROCESSOR_ASSIGNED, task, null, processor, null); + TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.PROCESSOR_ASSIGNED, task, null, processor); commandTaskHistoryPort.save(taskHistory); String processorName = processor.getNickname(); diff --git a/src/main/java/clap/server/application/service/task/TerminateTaskService.java b/src/main/java/clap/server/application/service/task/TerminateTaskService.java index 571404b2..1b30db47 100644 --- a/src/main/java/clap/server/application/service/task/TerminateTaskService.java +++ b/src/main/java/clap/server/application/service/task/TerminateTaskService.java @@ -37,7 +37,7 @@ public void terminateTask(Long memberId, Long taskId, String reason) { task.terminateTask(); taskService.upsert(task); - TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.TASK_TERMINATED, task, reason, null, null); + TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.TASK_TERMINATED, task, reason, null); commandTaskHistoryPort.save(taskHistory); publishNotification(task.getRequester(), task, task.getTaskStatus().getDescription(), reason); diff --git a/src/main/java/clap/server/application/service/task/UpdateTaskOrderAndStstusService.java b/src/main/java/clap/server/application/service/task/UpdateTaskOrderAndStstusService.java index d29af3aa..b32d5d2e 100644 --- a/src/main/java/clap/server/application/service/task/UpdateTaskOrderAndStstusService.java +++ b/src/main/java/clap/server/application/service/task/UpdateTaskOrderAndStstusService.java @@ -82,7 +82,7 @@ public void updateTaskOrderAndStatus(Long processorId, UpdateTaskOrderRequest re updatedTask = updateNewTaskOrderAndStatus(targetStatus, targetTask, newOrder); } - TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.STATUS_SWITCHED, updatedTask, targetStatus.getDescription(), null,null); + TaskHistory taskHistory = TaskHistory.createTaskHistory(TaskHistoryType.STATUS_SWITCHED, updatedTask, targetStatus.getDescription(), null); commandTaskHistoryPort.save(taskHistory); publishNotification(targetTask); } diff --git a/src/main/java/clap/server/application/service/task/UpdateTaskService.java b/src/main/java/clap/server/application/service/task/UpdateTaskService.java index d9691871..2849bd3e 100644 --- a/src/main/java/clap/server/application/service/task/UpdateTaskService.java +++ b/src/main/java/clap/server/application/service/task/UpdateTaskService.java @@ -57,7 +57,7 @@ public void updateTaskStatus(Long memberId, Long taskId, TaskStatus targetTaskSt task.updateTaskStatus(targetTaskStatus); Task updatedTask = taskService.upsert(task); - saveTaskHistory(TaskHistory.createTaskHistory(TaskHistoryType.STATUS_SWITCHED, task, targetTaskStatus.getDescription(), null, null)); + saveTaskHistory(TaskHistory.createTaskHistory(TaskHistoryType.STATUS_SWITCHED, task, targetTaskStatus.getDescription(), null)); List receivers = List.of(task.getRequester()); publishNotification(receivers, updatedTask, NotificationType.STATUS_SWITCHED, targetTaskStatus.getDescription()); @@ -79,7 +79,7 @@ public void updateTaskProcessor(Long taskId, Long memberId, UpdateTaskProcessorR task.updateProcessor(processor); Task updatedTask = taskService.upsert(task); - saveTaskHistory(TaskHistory.createTaskHistory(TaskHistoryType.PROCESSOR_CHANGED, task, null, processor, null)); + saveTaskHistory(TaskHistory.createTaskHistory(TaskHistoryType.PROCESSOR_CHANGED, task, null, processor)); List receivers = List.of(updatedTask.getRequester()); publishNotification(receivers, updatedTask, NotificationType.PROCESSOR_CHANGED, processor.getNickname()); diff --git a/src/main/java/clap/server/domain/model/task/TaskHistory.java b/src/main/java/clap/server/domain/model/task/TaskHistory.java index 0e751998..a40292b6 100644 --- a/src/main/java/clap/server/domain/model/task/TaskHistory.java +++ b/src/main/java/clap/server/domain/model/task/TaskHistory.java @@ -1,10 +1,8 @@ package clap.server.domain.model.task; import clap.server.adapter.outbound.persistense.entity.task.constant.TaskHistoryType; - import clap.server.domain.model.common.BaseTime; import clap.server.domain.model.member.Member; - import lombok.*; import lombok.experimental.SuperBuilder; @@ -15,6 +13,7 @@ public class TaskHistory extends BaseTime { private Long taskHistoryId; private TaskHistoryType type; private TaskModificationInfo taskModificationInfo; + private Member modifiedMember; private Comment comment; @Getter @@ -23,20 +22,33 @@ public class TaskHistory extends BaseTime { @NoArgsConstructor(access = AccessLevel.PROTECTED) public static class TaskModificationInfo { private Task task; - private Member modifiedMember; private String modifiedStatus; } - public static TaskHistory createTaskHistory(TaskHistoryType type, Task task, String statusDescription, Member member, Comment comment) { + public static TaskHistory createTaskHistory(TaskHistoryType type, Task task, String statusDescription, Member member) { return TaskHistory.builder() .type(type) + .modifiedMember(member) .taskModificationInfo( TaskModificationInfo.builder() .task(task) - .modifiedMember(member) .modifiedStatus(statusDescription) .build() ) + .comment(null) + .build(); + } + + public static TaskHistory createCommentTaskHistory(TaskHistoryType type, Member member, Comment comment) { + return TaskHistory.builder() + .type(type) + .modifiedMember(member) + .taskModificationInfo( + TaskModificationInfo.builder() + .task(null) + .modifiedStatus(null) + .build() + ) .comment(comment) .build(); } diff --git a/src/main/resources/db/migration/dev/V20250219453__Update_Modified_Member_From_Task_History.sql b/src/main/resources/db/migration/dev/V20250219453__Update_Modified_Member_From_Task_History.sql new file mode 100644 index 00000000..1bb95cf1 --- /dev/null +++ b/src/main/resources/db/migration/dev/V20250219453__Update_Modified_Member_From_Task_History.sql @@ -0,0 +1,9 @@ +START TRANSACTION; + +UPDATE task_history th +SET modified_member_id = ( + SELECT member_id FROM comment c WHERE c.comment_id = th.comment_id +) +WHERE th.comment_id IS NOT NULL AND th.type='COMMENT_FILE'; + +COMMIT; \ No newline at end of file diff --git a/src/main/resources/db/migration/prod/V20250219453__Update_Modified_Member_From_Task_History.sql b/src/main/resources/db/migration/prod/V20250219453__Update_Modified_Member_From_Task_History.sql new file mode 100644 index 00000000..1bb95cf1 --- /dev/null +++ b/src/main/resources/db/migration/prod/V20250219453__Update_Modified_Member_From_Task_History.sql @@ -0,0 +1,9 @@ +START TRANSACTION; + +UPDATE task_history th +SET modified_member_id = ( + SELECT member_id FROM comment c WHERE c.comment_id = th.comment_id +) +WHERE th.comment_id IS NOT NULL AND th.type='COMMENT_FILE'; + +COMMIT; \ No newline at end of file