diff --git a/src/main/java/com/swmarastro/mykkumiserver/global/exception/ErrorCode.java b/src/main/java/com/swmarastro/mykkumiserver/global/exception/ErrorCode.java index f43f087..e0858d5 100644 --- a/src/main/java/com/swmarastro/mykkumiserver/global/exception/ErrorCode.java +++ b/src/main/java/com/swmarastro/mykkumiserver/global/exception/ErrorCode.java @@ -29,6 +29,7 @@ public enum ErrorCode { //409 CONFLICT DUPLICATE_VALUE(HttpStatus.CONFLICT), DUPLICATE_REPORT(HttpStatus.CONFLICT), + ALREADY_EXISTS(HttpStatus.CONFLICT), //500 INTERNAL_SERVER_ERROR INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR), diff --git a/src/main/java/com/swmarastro/mykkumiserver/like/Likes.java b/src/main/java/com/swmarastro/mykkumiserver/like/Likes.java new file mode 100644 index 0000000..11d3200 --- /dev/null +++ b/src/main/java/com/swmarastro/mykkumiserver/like/Likes.java @@ -0,0 +1,48 @@ +package com.swmarastro.mykkumiserver.like; + +import com.swmarastro.mykkumiserver.global.BaseEntity; +import com.swmarastro.mykkumiserver.post.domain.Post; +import com.swmarastro.mykkumiserver.user.User; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Builder +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PROTECTED) +public class Likes extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "likes_id") + private Long id; + + private Boolean isDeleted; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @JoinColumn(name = "user_id") + @ManyToOne(fetch = FetchType.LAZY) + private User user; + + public static Likes of(Post post, User user) { + return Likes.builder() + .post(post) + .user(user) + .isDeleted(false) + .build(); + } + + public Boolean like() { + isDeleted = false; + return true; + } + + public Boolean unlike() { + isDeleted = true; + return true; + } +} diff --git a/src/main/java/com/swmarastro/mykkumiserver/like/LikesController.java b/src/main/java/com/swmarastro/mykkumiserver/like/LikesController.java new file mode 100644 index 0000000..90d386d --- /dev/null +++ b/src/main/java/com/swmarastro/mykkumiserver/like/LikesController.java @@ -0,0 +1,28 @@ +package com.swmarastro.mykkumiserver.like; + +import com.swmarastro.mykkumiserver.auth.annotation.Login; +import com.swmarastro.mykkumiserver.auth.annotation.RequiresLogin; +import com.swmarastro.mykkumiserver.like.dto.LikesRequest; +import com.swmarastro.mykkumiserver.like.dto.LikesResponse; +import com.swmarastro.mykkumiserver.user.User; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1") +@RequiredArgsConstructor +public class LikesController { + + private final LikesService likeService; + + @RequiresLogin + @PostMapping("/likes") + public ResponseEntity like(@Login User user, @RequestBody LikesRequest request) { + LikesResponse response = LikesResponse.of(likeService.like(user, request.getPostId())); + return ResponseEntity.ok(response); + } +} diff --git a/src/main/java/com/swmarastro/mykkumiserver/like/LikesRepository.java b/src/main/java/com/swmarastro/mykkumiserver/like/LikesRepository.java new file mode 100644 index 0000000..16a2fdb --- /dev/null +++ b/src/main/java/com/swmarastro/mykkumiserver/like/LikesRepository.java @@ -0,0 +1,14 @@ +package com.swmarastro.mykkumiserver.like; + +import com.swmarastro.mykkumiserver.post.domain.Post; +import com.swmarastro.mykkumiserver.user.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.Optional; + +public interface LikesRepository extends JpaRepository { + + @Query("SELECT l from Likes l WHERE l.post = :post AND l.user = :user") + Optional findByPostAndUser(Post post, User user); //TODO postid, userid로 하는게 나을지??? +} diff --git a/src/main/java/com/swmarastro/mykkumiserver/like/LikesService.java b/src/main/java/com/swmarastro/mykkumiserver/like/LikesService.java new file mode 100644 index 0000000..95ed1bc --- /dev/null +++ b/src/main/java/com/swmarastro/mykkumiserver/like/LikesService.java @@ -0,0 +1,42 @@ +package com.swmarastro.mykkumiserver.like; + +import com.swmarastro.mykkumiserver.global.exception.CommonException; +import com.swmarastro.mykkumiserver.global.exception.ErrorCode; +import com.swmarastro.mykkumiserver.post.domain.Post; +import com.swmarastro.mykkumiserver.post.service.PostService; +import com.swmarastro.mykkumiserver.user.User; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +@RequiredArgsConstructor +@Transactional +public class LikesService { + + private final LikesRepository likeRepository; + private final PostService postService; + + public Boolean like(User user, Long postId) { + + Post post = postService.findById(postId); + + //like가 테이블에 있는지 확인 + Optional optionalLike = likeRepository.findByPostAndUser(post, user); + //없음 -> 생성하고 좋아요 눌림 + if (optionalLike.isEmpty()) { + Likes like = Likes.of(post, user); + likeRepository.save(like); + return true; + } + Likes like = optionalLike.get(); + //있는데 안눌린 상태 -> 좋아요 눌림 + if (like.getIsDeleted()) { + return like.like(); + } + //있는데 이미 눌린상태 -> 이미 좋아요 누른 포스트입니다. + throw new CommonException(ErrorCode.ALREADY_EXISTS, "이미 좋아요를 누른 포스트입니다.", "이미 좋아요를 누른 포스트입니다."); + } +} diff --git a/src/main/java/com/swmarastro/mykkumiserver/like/dto/LikesRequest.java b/src/main/java/com/swmarastro/mykkumiserver/like/dto/LikesRequest.java new file mode 100644 index 0000000..e20c40b --- /dev/null +++ b/src/main/java/com/swmarastro/mykkumiserver/like/dto/LikesRequest.java @@ -0,0 +1,9 @@ +package com.swmarastro.mykkumiserver.like.dto; + +import lombok.Getter; + +@Getter +public class LikesRequest { + + private Long postId; +} diff --git a/src/main/java/com/swmarastro/mykkumiserver/like/dto/LikesResponse.java b/src/main/java/com/swmarastro/mykkumiserver/like/dto/LikesResponse.java new file mode 100644 index 0000000..31099ea --- /dev/null +++ b/src/main/java/com/swmarastro/mykkumiserver/like/dto/LikesResponse.java @@ -0,0 +1,17 @@ +package com.swmarastro.mykkumiserver.like.dto; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class LikesResponse { + + private Boolean success; + + public static LikesResponse of(Boolean success) { + return LikesResponse.builder() + .success(success) + .build(); + } +} diff --git a/src/main/java/com/swmarastro/mykkumiserver/post/service/PostService.java b/src/main/java/com/swmarastro/mykkumiserver/post/service/PostService.java index 82e1a5a..c948842 100644 --- a/src/main/java/com/swmarastro/mykkumiserver/post/service/PostService.java +++ b/src/main/java/com/swmarastro/mykkumiserver/post/service/PostService.java @@ -180,4 +180,9 @@ private void saveHashtags(List contentTexts, Post savedPost) { }) .forEach(hashtagService::savePostHashtag); // PostHashtag 저장 } + + public Post findById(Long postId) { + return postRepository.findById(postId) + .orElseThrow(() -> new CommonException(ErrorCode.NOT_FOUND, "포스트가 존재하지 않습니다.", "포스트가 존재하지 않습니다.")); + } }