From f10ce4b8f6819897ab26e7bf3d17dcc27fb35d89 Mon Sep 17 00:00:00 2001 From: NohSungGyu Date: Fri, 28 Jun 2024 16:05:59 +0900 Subject: [PATCH 1/2] feature: add feature for updating comment SCRUM-25 --- build.gradle | 2 +- .../adapter/comment/CommentController.java | 8 +++++ .../adapter/comment/CommentMapper.java | 3 +- .../dto/request/UpdatingCommentDto.java | 19 +++++++++++ .../infrastructure/jpa/CommentEntity.java | 6 ++-- .../jpa/CommentRepositoryImpl.java | 26 +++++++++++++-- .../infrastructure/jpa/BaseTimeEntity.java | 9 +++-- .../jpa/PostRepositoryImpl.java | 1 + .../in/comment/CommentUseCase.java | 3 ++ .../out/persistence/CommentRepository.java | 4 +++ .../service/comment/CommentService.java | 7 ++++ .../domain/comment/CommentForUpdate.java | 33 +++++++++++++++++++ 12 files changed, 112 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/codecrafters/companity/adapter/comment/dto/request/UpdatingCommentDto.java create mode 100644 src/main/java/com/codecrafters/companity/domain/comment/CommentForUpdate.java diff --git a/build.gradle b/build.gradle index a754346..bb6412a 100644 --- a/build.gradle +++ b/build.gradle @@ -45,8 +45,8 @@ dependencies { implementation 'org.mapstruct:mapstruct:1.5.5.Final' - annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' annotationProcessor "org.projectlombok:lombok-mapstruct-binding:0.2.0" + annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' implementation("org.flywaydb:flyway-core") implementation("org.flywaydb:flyway-mysql") diff --git a/src/main/java/com/codecrafters/companity/adapter/comment/CommentController.java b/src/main/java/com/codecrafters/companity/adapter/comment/CommentController.java index 46dc5c4..678ef37 100644 --- a/src/main/java/com/codecrafters/companity/adapter/comment/CommentController.java +++ b/src/main/java/com/codecrafters/companity/adapter/comment/CommentController.java @@ -1,6 +1,7 @@ package com.codecrafters.companity.adapter.comment; import com.codecrafters.companity.adapter.comment.dto.request.AddCommentDto; +import com.codecrafters.companity.adapter.comment.dto.request.UpdatingCommentDto; import com.codecrafters.companity.adapter.comment.dto.response.ResponseComment; import com.codecrafters.companity.application.in.comment.CommentUseCase; import com.codecrafters.companity.application.in.post.PostUseCase; @@ -37,6 +38,13 @@ public ResponseEntity add(@RequestBody AddCommentDto request){ return new ResponseEntity<>(responsePost, HttpStatus.CREATED); } + @PutMapping + public ResponseEntity update(@RequestBody UpdatingCommentDto request){ + Comment result = commentUseCase.update(request.toCommentForUpdate(getUser())); + ResponseComment responsePost = COMMENT_MAPPER.toDto(result); + return new ResponseEntity<>(responsePost, HttpStatus.OK); + } + @GetMapping("/{id}") public ResponseEntity> getList(@PathVariable("id") Long postId, Pageable pageable){ Post post = postUseCase.get(postId); diff --git a/src/main/java/com/codecrafters/companity/adapter/comment/CommentMapper.java b/src/main/java/com/codecrafters/companity/adapter/comment/CommentMapper.java index b6d53bd..077f05f 100644 --- a/src/main/java/com/codecrafters/companity/adapter/comment/CommentMapper.java +++ b/src/main/java/com/codecrafters/companity/adapter/comment/CommentMapper.java @@ -5,12 +5,13 @@ import com.codecrafters.companity.domain.comment.Comment; import org.mapstruct.Mapper; import org.mapstruct.Mapping; +import org.mapstruct.MappingConstants; import org.mapstruct.control.DeepClone; import org.mapstruct.factory.Mappers; import java.util.List; -@Mapper(mappingControl = DeepClone.class) +@Mapper(mappingControl = DeepClone.class, componentModel = MappingConstants.ComponentModel.SPRING) public interface CommentMapper { CommentMapper COMMENT_MAPPER = Mappers.getMapper(CommentMapper.class); @Mapping(source = "owner", target = "user") diff --git a/src/main/java/com/codecrafters/companity/adapter/comment/dto/request/UpdatingCommentDto.java b/src/main/java/com/codecrafters/companity/adapter/comment/dto/request/UpdatingCommentDto.java new file mode 100644 index 0000000..bf6877a --- /dev/null +++ b/src/main/java/com/codecrafters/companity/adapter/comment/dto/request/UpdatingCommentDto.java @@ -0,0 +1,19 @@ +package com.codecrafters.companity.adapter.comment.dto.request; + +import com.codecrafters.companity.domain.comment.CommentForUpdate; +import com.codecrafters.companity.domain.user.User; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +@Getter +@Setter +@ToString +public class UpdatingCommentDto { + private Long id; + private String content; + + public CommentForUpdate toCommentForUpdate(User user){ + return CommentForUpdate.builder().id(id).user(user).content(content).build(); + } +} diff --git a/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentEntity.java b/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentEntity.java index a4e420a..68af3bc 100644 --- a/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentEntity.java +++ b/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentEntity.java @@ -5,12 +5,12 @@ import com.codecrafters.companity.adapter.user.infrastructure.jpa.UserEntity; import jakarta.persistence.*; import lombok.*; +import lombok.experimental.SuperBuilder; @Entity(name = "Comment") @Getter -@Builder -@NoArgsConstructor -@AllArgsConstructor +@SuperBuilder +@NoArgsConstructor(access = AccessLevel.PROTECTED) public class CommentEntity extends BaseTimeEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentRepositoryImpl.java b/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentRepositoryImpl.java index c8908c0..471253c 100644 --- a/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentRepositoryImpl.java +++ b/src/main/java/com/codecrafters/companity/adapter/comment/infrastructure/jpa/CommentRepositoryImpl.java @@ -21,8 +21,30 @@ public class CommentRepositoryImpl implements CommentRepository { private final String CREATED_AT = "createdAt"; @Override public Comment add(Comment comment) { - CommentEntity savedEntity = commentJPARepository.save(COMMENT_MAPPER.toEntity(comment)); - return COMMENT_MAPPER.toDomain(savedEntity); + CommentEntity savedEntity = commentJPARepository.save(toEntity(comment)); + return toDomain(savedEntity); + } + + @Override + public Comment getById(Long id) { + CommentEntity entity = commentJPARepository.findById(id).orElseThrow(() -> { + throw new IllegalArgumentException("존재하지 않는 댓글입니다."); + }); + return toDomain(entity); + } + + @Override + public Comment update(Comment comment) { + CommentEntity save = commentJPARepository.save(toEntity(comment)); + return toDomain(save); + } + + private Comment toDomain(CommentEntity entity){ + return COMMENT_MAPPER.toDomain(entity); + } + + private CommentEntity toEntity(Comment comment){ + return COMMENT_MAPPER.toEntity(comment); } @Override diff --git a/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java b/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java index c9043eb..d2f4bde 100644 --- a/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java +++ b/src/main/java/com/codecrafters/companity/adapter/common/infrastructure/jpa/BaseTimeEntity.java @@ -2,7 +2,10 @@ import jakarta.persistence.EntityListeners; import jakarta.persistence.MappedSuperclass; +import lombok.AccessLevel; import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -12,9 +15,11 @@ @Getter @MappedSuperclass @EntityListeners(AuditingEntityListener.class) +@SuperBuilder +@NoArgsConstructor(access = AccessLevel.PROTECTED) public abstract class BaseTimeEntity { @CreatedDate - private LocalDateTime createdAt; + protected LocalDateTime createdAt; @LastModifiedDate - private LocalDateTime modifiedAt; + protected LocalDateTime modifiedAt; } diff --git a/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java b/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java index 2237d8d..035c9e6 100644 --- a/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java +++ b/src/main/java/com/codecrafters/companity/adapter/post/infrastructure/jpa/PostRepositoryImpl.java @@ -54,6 +54,7 @@ public void delete(Long id) { @Override public Post update(Post post) { + //FIXME need to refactor this code PostEntity entity = postJPARepository.findById(post.getId()).orElseThrow(() -> { throw new IllegalArgumentException("존재하지 않는 게시물입니다."); }); diff --git a/src/main/java/com/codecrafters/companity/application/in/comment/CommentUseCase.java b/src/main/java/com/codecrafters/companity/application/in/comment/CommentUseCase.java index efe485a..0bcdc00 100644 --- a/src/main/java/com/codecrafters/companity/application/in/comment/CommentUseCase.java +++ b/src/main/java/com/codecrafters/companity/application/in/comment/CommentUseCase.java @@ -2,7 +2,10 @@ import com.codecrafters.companity.domain.comment.CommentForCreate; import com.codecrafters.companity.domain.comment.Comment; +import com.codecrafters.companity.domain.comment.CommentForUpdate; public interface CommentUseCase { Comment add(CommentForCreate commentForCreate); + + Comment update(CommentForUpdate commentForUpdate); } diff --git a/src/main/java/com/codecrafters/companity/application/out/persistence/CommentRepository.java b/src/main/java/com/codecrafters/companity/application/out/persistence/CommentRepository.java index 886a466..72318c3 100644 --- a/src/main/java/com/codecrafters/companity/application/out/persistence/CommentRepository.java +++ b/src/main/java/com/codecrafters/companity/application/out/persistence/CommentRepository.java @@ -8,4 +8,8 @@ public interface CommentRepository { Comment add(Comment comment); Page findAllByPost(Post post, Pageable pageable); + + Comment update(Comment comment); + + Comment getById(Long id); } diff --git a/src/main/java/com/codecrafters/companity/application/service/comment/CommentService.java b/src/main/java/com/codecrafters/companity/application/service/comment/CommentService.java index 2c75fbb..097d9c3 100644 --- a/src/main/java/com/codecrafters/companity/application/service/comment/CommentService.java +++ b/src/main/java/com/codecrafters/companity/application/service/comment/CommentService.java @@ -4,6 +4,7 @@ import com.codecrafters.companity.application.out.persistence.CommentRepository; import com.codecrafters.companity.domain.comment.CommentForCreate; import com.codecrafters.companity.domain.comment.Comment; +import com.codecrafters.companity.domain.comment.CommentForUpdate; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -18,4 +19,10 @@ public Comment add(CommentForCreate commentForCreate) { Comment comment = commentForCreate.toComment(); return commentRepository.add(comment); } + + @Override + public Comment update(CommentForUpdate commentForUpdate) { + Comment comment = commentRepository.getById(commentForUpdate.getId()); + return commentRepository.update(commentForUpdate.update(comment)); + } } diff --git a/src/main/java/com/codecrafters/companity/domain/comment/CommentForUpdate.java b/src/main/java/com/codecrafters/companity/domain/comment/CommentForUpdate.java new file mode 100644 index 0000000..8cf0682 --- /dev/null +++ b/src/main/java/com/codecrafters/companity/domain/comment/CommentForUpdate.java @@ -0,0 +1,33 @@ +package com.codecrafters.companity.domain.comment; + +import com.codecrafters.companity.domain.user.User; +import lombok.Builder; +import lombok.Getter; +import org.springframework.util.StringUtils; + +@Getter +@Builder +public class CommentForUpdate { + private Long id; + private String content; + private User user; + + public Comment update(Comment original){ + validate(original); + return Comment.builder() + .id(id) + .post(original.getPost().clone()) + .owner(user.clone()) + .content(content) + .createdAt(original.getCreatedAt()) + .modifiedAt(original.getModifiedAt()) + .build(); + } + + private void validate(Comment comment){ + if(!StringUtils.hasText(content)) throw new IllegalArgumentException("Content must not be null"); + if(id == null) throw new IllegalArgumentException("Id must not be null"); + if(user == null) throw new IllegalArgumentException("User must not be null"); + if(!user.getUserId().equals(comment.getOwner().getUserId())) throw new IllegalArgumentException("User must be the same as the writer of the comment"); + } +} From d718f05ae14cf3d3905bc0a76210b604010f69be Mon Sep 17 00:00:00 2001 From: NohSungGyu Date: Mon, 15 Jul 2024 11:08:44 +0900 Subject: [PATCH 2/2] docs: add comment SCRUM-25 --- .../companity/comment/application/port/CommentService.java | 1 + .../application/port/out/persistence/CommentRepository.java | 1 + .../java/com/codecrafters/companity/comment/domain/Comment.java | 2 -- .../codecrafters/companity/comment/domain/CommentForCreate.java | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java b/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java index 78109ad..3281b71 100644 --- a/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java +++ b/src/main/java/com/codecrafters/companity/comment/application/port/CommentService.java @@ -16,6 +16,7 @@ public class CommentService implements CommentUseCase { private final CommentRepository commentRepository; @Override public Comment add(CommentForCreate commentForCreate) { + //TODO : change to use commentForCreate directly and validate here Comment comment = commentForCreate.toComment(); return commentRepository.add(comment); } diff --git a/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java b/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java index 36e9976..bcdde5a 100644 --- a/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java +++ b/src/main/java/com/codecrafters/companity/comment/application/port/out/persistence/CommentRepository.java @@ -6,6 +6,7 @@ import org.springframework.data.domain.Pageable; public interface CommentRepository { + //TODO : change to use commentForCreate directly Comment add(Comment comment); Page findAllByPost(Post post, Pageable pageable); diff --git a/src/main/java/com/codecrafters/companity/comment/domain/Comment.java b/src/main/java/com/codecrafters/companity/comment/domain/Comment.java index 354bcb0..4664596 100644 --- a/src/main/java/com/codecrafters/companity/comment/domain/Comment.java +++ b/src/main/java/com/codecrafters/companity/comment/domain/Comment.java @@ -4,13 +4,11 @@ import com.codecrafters.companity.domain.user.User; import lombok.Builder; import lombok.Getter; -import lombok.ToString; import java.time.LocalDateTime; @Getter @Builder -@ToString public class Comment { private Long id; private User owner; diff --git a/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java b/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java index 6c8b207..35b022d 100644 --- a/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java +++ b/src/main/java/com/codecrafters/companity/comment/domain/CommentForCreate.java @@ -13,6 +13,7 @@ public class CommentForCreate { private Post post; private User user; + //FIXME: This method is not used. Remove it. public Comment toComment(){ validate(); return Comment.builder().post(post.clone()).owner(user.clone()).content(content).build();