Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
โ€ฆCodiary into develop
  • Loading branch information
yumzen committed Nov 21, 2024
2 parents c2d6da7 + 78f8b09 commit 9c0f561
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 23 deletions.
Original file line number Diff line number Diff line change
@@ -1,33 +1,45 @@
package com.codiary.backend.domain.post.controller;

import com.codiary.backend.domain.member.entity.Member;
import com.codiary.backend.domain.member.security.CustomMemberDetails;
import com.codiary.backend.domain.member.service.MemberCommandService;
import com.codiary.backend.domain.post.converter.PostConverter;
import com.codiary.backend.domain.post.dto.response.PostResponseDTO;
import com.codiary.backend.domain.post.dto.request.PostRequestDTO;
import com.codiary.backend.domain.post.dto.response.PostResponseDTO;
import com.codiary.backend.domain.post.entity.Bookmark;
import com.codiary.backend.domain.post.entity.Post;
import com.codiary.backend.domain.member.entity.Member;
import com.codiary.backend.domain.post.service.BookmarkService;
import com.codiary.backend.domain.post.service.PostCommandService;
import com.codiary.backend.domain.post.service.PostQueryService;
import com.codiary.backend.domain.post.service.PostService;
import com.codiary.backend.global.apiPayload.ApiResponse;
import com.codiary.backend.global.apiPayload.code.status.SuccessStatus;
import com.codiary.backend.global.jwt.JwtTokenProvider;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import java.util.Optional;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.data.domain.Pageable;
import com.codiary.backend.global.jwt.JwtTokenProvider;

import java.util.Optional;
import java.util.Set;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RequiredArgsConstructor
Expand All @@ -43,6 +55,7 @@ public class PostController {
private final PostQueryService postQueryService;
private final MemberCommandService memberCommandService;
private final JwtTokenProvider jwtTokenProvider;
private final BookmarkService bookmarkService;

// ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑํ•˜๊ธฐ
@PostMapping(consumes = "multipart/form-data")
Expand Down Expand Up @@ -170,4 +183,30 @@ public ApiResponse<PostResponseDTO.UpdatePostResultDTO> setPostCategory(@PathVar
Post updatedPost = postCommandService.setPostCategories(postId, categoryNames);
return ApiResponse.onSuccess(SuccessStatus.POST_OK, PostConverter.toSetPostCategoriesResultDTO(updatedPost));
}

// ๋ถ๋งˆํฌ ์ถ”๊ฐ€
@PostMapping("/{post_id}/bookmark")
@Operation(summary = "๊ฒŒ์‹œ๊ธ€ ๋ถ๋งˆํฌ")
public ApiResponse<PostResponseDTO.BookmarkDTO> bookmarkPost(
@PathVariable("post_id") Long postId,
@AuthenticationPrincipal CustomMemberDetails memberDetails
) {
Long memberId = memberDetails.getId();
Bookmark bookmark = bookmarkService.bookmarkPost(memberId, postId);

return ApiResponse.onSuccess(SuccessStatus.BOOKMARK_OK, PostConverter.toBookmarkDTO(bookmark));
}

// ๋ถ๋งˆํฌ ์‚ญ์ œ
@DeleteMapping("/{post_id}/bookmark")
@Operation(summary = "๊ฒŒ์‹œ๊ธ€ ๋ถ๋งˆํฌ ์ทจ์†Œ")
public ApiResponse<String> cancelBookmark(
@PathVariable("post_id") Long postId,
@AuthenticationPrincipal CustomMemberDetails memberDetails
) {
Long memberId = memberDetails.getId();
String response = bookmarkService.cancelBookmark(memberId, postId);

return ApiResponse.onSuccess(SuccessStatus.BOOKMARK_OK, response);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package com.codiary.backend.domain.post.converter;

import com.codiary.backend.domain.category.entity.Category;
import com.codiary.backend.domain.post.dto.request.PostRequestDTO;
import com.codiary.backend.domain.post.dto.response.PostResponseDTO;
import com.codiary.backend.domain.post.entity.Bookmark;
import com.codiary.backend.domain.post.entity.Post;
import com.codiary.backend.domain.category.entity.Category;
import com.codiary.backend.domain.post.enumerate.PostAccess;
import com.codiary.backend.domain.project.entity.Project;
import com.codiary.backend.domain.team.entity.Team;
import org.springframework.data.domain.Page;
import com.codiary.backend.domain.project.repository.ProjectRepository;
import com.codiary.backend.domain.team.entity.Team;
import com.codiary.backend.domain.team.repository.TeamRepository;

import java.util.List;
import java.util.stream.Collectors;
import org.springframework.data.domain.Page;

public class PostConverter {

Expand Down Expand Up @@ -426,5 +426,12 @@ public static PostResponseDTO.UpdatePostResultDTO toSetPostCategoriesResultDTO(P
.build();
}

public static PostResponseDTO.BookmarkDTO toBookmarkDTO(Bookmark bookmark) {
return PostResponseDTO.BookmarkDTO.builder()
.bookmarkId(bookmark.getId())
.postId(bookmark.getPost().getPostId())
.memberId(bookmark.getMember().getMemberId())
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.*;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

public class PostResponseDTO {

Expand Down Expand Up @@ -312,8 +313,13 @@ public record PostAdjacentPreviewDTO(
}
}





@Builder
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record BookmarkDTO(
Long bookmarkId,
Long memberId,
Long postId
) {
}
}
20 changes: 18 additions & 2 deletions src/main/java/com/codiary/backend/domain/post/entity/Bookmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@

import com.codiary.backend.domain.member.entity.Member;
import com.codiary.backend.global.common.BaseEntity;
import jakarta.persistence.*;
import lombok.*;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
Expand Down Expand Up @@ -42,4 +52,10 @@ public void setPost(Post post) {
post.getBookmarkList().add(this);
}

@Builder
public Bookmark(Member member, Post post) {
this.member = member;
this.post = post;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.codiary.backend.domain.post.repository;

import com.codiary.backend.domain.member.entity.Member;
import com.codiary.backend.domain.post.entity.Bookmark;
import com.codiary.backend.domain.post.entity.Post;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {

Boolean existsByMemberAndPost(Member member, Post post);

Optional<Bookmark> findByMemberAndPost(Member member, Post post);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package com.codiary.backend.domain.post.service;

import com.codiary.backend.domain.member.entity.Member;
import com.codiary.backend.domain.member.repository.MemberRepository;
import com.codiary.backend.domain.post.entity.Bookmark;
import com.codiary.backend.domain.post.entity.Post;
import com.codiary.backend.domain.post.enumerate.PostAccess;
import com.codiary.backend.domain.post.repository.BookmarkRepository;
import com.codiary.backend.domain.post.repository.PostRepository;
import com.codiary.backend.domain.team.entity.Team;
import com.codiary.backend.domain.team.repository.TeamRepository;
import com.codiary.backend.global.apiPayload.code.status.ErrorStatus;
import com.codiary.backend.global.apiPayload.exception.GeneralException;
import com.codiary.backend.global.apiPayload.exception.handler.BookmarkHandler;
import com.codiary.backend.global.apiPayload.exception.handler.MemberHandler;
import com.codiary.backend.global.apiPayload.exception.handler.PostHandler;
import com.codiary.backend.global.apiPayload.exception.handler.TeamHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class BookmarkService {

private final MemberRepository memberRepository;
private final PostRepository postRepository;
private final BookmarkRepository bookmarkRepository;
private final TeamRepository teamRepository;

public Bookmark bookmarkPost(Long memberId, Long postId) {
// validation: member, post ์—ฌ๋ถ€
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));
Post post = postRepository.findById(postId).orElseThrow(() -> new PostHandler(ErrorStatus.POST_NOT_FOUND));

// validation: ์ด๋ฏธ ๋ถ๋งˆํฌํ•œ ์ƒํƒœ
if (bookmarkRepository.existsByMemberAndPost(member, post)) {
throw new BookmarkHandler(ErrorStatus.BOOKMARK_ALREADY_EXIST);
}

// validation: post ๊ถŒํ•œ ํ™•์ธ
if (post.getPostAccess().equals(PostAccess.MEMBER) && post.getMember() != member) {
throw new GeneralException(ErrorStatus.BOOKMARK_CREATE_UNAUTHORIZED);
} else if (post.getPostAccess().equals(PostAccess.TEAM)) {
Team teamOfPost = teamRepository.findByIdWithTeamMemberList(post.getTeam().getTeamId())
.orElseThrow(() -> new TeamHandler(ErrorStatus.TEAM_NOT_FOUND));
if (!teamRepository.isTeamMember(teamOfPost, member)) {
throw new GeneralException((ErrorStatus.BOOKMARK_CREATE_UNAUTHORIZED));
}
}

// business logic
Bookmark bookmark = Bookmark.builder()
.member(member)
.post(post)
.build();
Bookmark savedBookmark = bookmarkRepository.save(bookmark);

// response
return savedBookmark;
}

public String cancelBookmark(Long memberId, Long postId) {
// validation: member, post, bookmark ์—ฌ๋ถ€
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new MemberHandler(ErrorStatus.MEMBER_NOT_FOUND));
Post post = postRepository.findById(postId).orElseThrow(() -> new PostHandler(ErrorStatus.POST_NOT_FOUND));
Bookmark bookmark = bookmarkRepository.findByMemberAndPost(member, post)
.orElseThrow(() -> new BookmarkHandler(ErrorStatus.BOOKMARK_ALREADY_CANCELED));

// business logic
member.getBookmarkList().remove(bookmark);
post.getBookmarkList().remove(bookmark);
bookmarkRepository.deleteById(bookmark.getId());

// response
return "๋ถ๋งˆํฌ๊ฐ€ ์ทจ์†Œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ public enum ErrorStatus implements BaseErrorCode {


// ๋ถ๋งˆํฌ ๊ด€๋ จ ์—๋Ÿฌ 6000
// BOOKMARK_CREATE_UNAUTHORIZED(HttpStatus.BAD_REQUEST, "BOOKMARK_6001", "๋ถ๋งˆํฌ ์ถ”๊ฐ€ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."),
// BOOKMARK_VIEW_UNAUTHORIZED(HttpStatus.BAD_REQUEST, "BOOKMARK_6002", "๋ถ๋งˆํฌ ๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."),
BOOKMARK_CREATE_UNAUTHORIZED(HttpStatus.BAD_REQUEST, "BOOKMARK_6001", "๋ถ๋งˆํฌ ์ถ”๊ฐ€ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."),
BOOKMARK_VIEW_UNAUTHORIZED(HttpStatus.BAD_REQUEST, "BOOKMARK_6002", "๋ถ๋งˆํฌ ๊ฒŒ์‹œ๊ธ€ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."),
// BOOKMARK_COUNT_ERROR(HttpStatus.BAD_REQUEST, "BOOKMARK_6003", "๋ถ๋งˆํฌ ๊ฐœ์ˆ˜ ๊ณ„์‚ฐ์— ์—๋Ÿฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค."),
// BOOKMARK_DELETE_UNAUTHORIZED(HttpStatus.BAD_REQUEST, "BOOKMARK_6004", "๋ถ๋งˆํฌ ์‚ญ์ œ ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค."),
BOOKMARK_NOT_FOUND(HttpStatus.BAD_REQUEST, "BOOKMARK_6005", "๋ถ๋งˆํฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."),
BOOKMARK_ALREADY_EXIST(HttpStatus.BAD_REQUEST, "BOOKMARK_6006", "์ด๋ฏธ ๋ถ๋งˆํฌํ•œ ํฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค."),
BOOKMARK_ALREADY_CANCELED(HttpStatus.BAD_REQUEST, "BOOKMARK_6007", "์ด๋ฏธ ๋ถ๋งˆํฌ ์ƒํƒœ๊ฐ€ ์•„๋‹Œ ํฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค."),

// ์นดํ…Œ๊ณ ๋ฆฌ ๊ด€๋ จ ์—๋Ÿฌ 7000
CATEGORY_NOT_FOUND(HttpStatus.BAD_REQUEST, "CATEGORY_7001", "์นดํ…Œ๊ณ ๋ฆฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค."),
Expand Down

0 comments on commit 9c0f561

Please sign in to comment.