Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] 아티클 북마크 등록 API를 구현한다. #38

Merged
merged 7 commits into from
Jul 13, 2023
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package indipage.org.indipage.api.user.controller;

import indipage.org.indipage.api.user.controller.dto.response.HasReceivedTicketResponseDto;
import indipage.org.indipage.api.user.controller.dto.response.IsBookmarkedResponseDto;
import indipage.org.indipage.api.user.controller.dto.response.UserDto;
import indipage.org.indipage.api.user.service.UserService;
import indipage.org.indipage.common.dto.ApiResponse;
Expand Down Expand Up @@ -47,4 +48,18 @@ public ApiResponse updateVisit(@PathVariable final Long spaceId) {
userService.visit(1L, spaceId);
return ApiResponse.success(Success.UPDATE_VISIT_SUCCESS);
}

@GetMapping("/bookmark/article/{articleId}")
@ResponseStatus(HttpStatus.OK)
public ApiResponse<IsBookmarkedResponseDto> readIsArticleBookMarked(@PathVariable Long articleId) {
return ApiResponse.success(Success.READ_IS_ARTICLE_BOOKMARKED_SUCCESS,
userService.readIsArticleBookMarked(1L, articleId));
}

@PostMapping("/bookmark/article/{articleId}")
@ResponseStatus(HttpStatus.CREATED)
public ApiResponse createArticleBookmark(@PathVariable Long articleId) {
userService.createArticleBookmark(1L, articleId);
return ApiResponse.success(Success.CREATE_ARTICLE_BOOKMARK_SUCCESS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package indipage.org.indipage.api.user.controller.dto.response;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class IsBookmarkedResponseDto {
private boolean isBookMarked;

public static IsBookmarkedResponseDto of(boolean isBookMarked) {
return new IsBookmarkedResponseDto(isBookMarked);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

import indipage.org.indipage.api.ticket.service.TicketService;
import indipage.org.indipage.api.user.controller.dto.response.HasReceivedTicketResponseDto;
import indipage.org.indipage.api.user.controller.dto.response.IsBookmarkedResponseDto;
import indipage.org.indipage.api.user.controller.dto.response.UserDto;
import indipage.org.indipage.domain.Article;
import indipage.org.indipage.domain.ArticleBookmarkRelationRepository;
import indipage.org.indipage.domain.ArticleRepository;
import indipage.org.indipage.domain.InviteSpaceRelationRepository;
import indipage.org.indipage.domain.Relation.ArticleBookmarkRelation;
import indipage.org.indipage.domain.Relation.ArticleBookmarkRelationId;
import indipage.org.indipage.domain.Relation.InviteSpaceRelation;
import indipage.org.indipage.domain.Relation.InviteSpaceRelationId;
import indipage.org.indipage.domain.Space;
Expand All @@ -14,6 +20,7 @@
import indipage.org.indipage.exception.Error;
import indipage.org.indipage.exception.model.ConflictException;
import indipage.org.indipage.exception.model.NotFoundException;
import java.util.Optional;
import javax.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -23,8 +30,10 @@
public class UserService {
private final UserRepository userRepository;
private final TicketService ticketService;
private final ArticleRepository articleRepository;
private final SpaceRepository spaceRepository;
private final InviteSpaceRelationRepository inviteSpaceRelationRepository;
private final ArticleBookmarkRelationRepository articleBookmarkRelationRepository;

public UserDto readUser(final Long userId) {
return UserDto.of(findUser(userId));
Expand Down Expand Up @@ -79,10 +88,56 @@ public void visit(final Long userId, final Long spaceId) {
inviteSpaceRelationRepository.save(relation);
}

public IsBookmarkedResponseDto readIsArticleBookMarked(final Long userId, final Long articleId) {

User user = findUser(userId);
Article article = findArticle(articleId);

Optional<ArticleBookmarkRelation> relation = articleBookmarkRelationRepository.findArticleBookmarkRelationByArticleBookmarkRelationId(
ArticleBookmarkRelationId.newInstance(article, user));

if (relation.isEmpty()) {
return IsBookmarkedResponseDto.of(false);
}
return IsBookmarkedResponseDto.of(true);
}

@Transactional(rollbackOn = Exception.class)
public void createArticleBookmark(final Long userId, final Long articleId) {
User user = findUser(userId);
Article article = findArticle(articleId);

// 북마크 검사
if (isBookMarked(user, article)) {
throw new ConflictException(Error.ALREADY_BOOKMARKED_ARTICLE_EXCEPTION,
Error.ALREADY_BOOKMARKED_ARTICLE_EXCEPTION.getMessage());
}
;

ArticleBookmarkRelation relation = ArticleBookmarkRelation.newInstance(article, user);
articleBookmarkRelationRepository.save(relation);
}

private Space findSpace(Long spaceId) {
return spaceRepository.findById(spaceId).orElseThrow(
() -> new NotFoundException(Error.NOT_FOUND_SPACE_EXCEPTION,
Error.NOT_FOUND_SPACE_EXCEPTION.getMessage()));
}

private Article findArticle(Long articleId) {
return articleRepository.findById(articleId).orElseThrow(
() -> new NotFoundException(Error.NOT_FOUND_ARTICLE_EXCEPTION,
Error.NOT_FOUND_ARTICLE_EXCEPTION.getMessage()));
}

private boolean isBookMarked(User user, Article article) {
Optional<ArticleBookmarkRelation> relation = articleBookmarkRelationRepository.findArticleBookmarkRelationByArticleBookmarkRelationId(
ArticleBookmarkRelationId.newInstance(article, user));

if (relation.isEmpty()) {
return false;
}

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package indipage.org.indipage.domain;

import indipage.org.indipage.domain.Relation.ArticleBookmarkRelation;
import indipage.org.indipage.domain.Relation.ArticleBookmarkRelationId;
import indipage.org.indipage.domain.Relation.FollowSpaceRelation;
import java.util.Optional;
import org.springframework.data.repository.Repository;

public interface ArticleBookmarkRelationRepository extends
Repository<ArticleBookmarkRelation, ArticleBookmarkRelationId> {
Optional<ArticleBookmarkRelation> findArticleBookmarkRelationByArticleBookmarkRelationId(
ArticleBookmarkRelationId articleBookmarkRelationId);

void save(ArticleBookmarkRelation relation);

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
import javax.persistence.ManyToOne;
import javax.persistence.MapsId;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class ArticleBookmarkRelation extends CreatedTimeBaseEntity {

Expand All @@ -29,4 +31,9 @@ public class ArticleBookmarkRelation extends CreatedTimeBaseEntity {
@ManyToOne
@JoinColumn(name = "user_id")
private User user;

public static ArticleBookmarkRelation newInstance(Article article, User user) {
return new ArticleBookmarkRelation(
ArticleBookmarkRelationId.newInstance(article, user), article, user);
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
package indipage.org.indipage.domain.Relation;

import indipage.org.indipage.domain.Article;
import indipage.org.indipage.domain.Space;
import indipage.org.indipage.domain.User;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

@Embeddable
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
public class ArticleBookmarkRelationId implements Serializable {

Expand All @@ -16,4 +21,8 @@ public class ArticleBookmarkRelationId implements Serializable {

@Column(name = "user_id", nullable = false)
private Long userId;

public static ArticleBookmarkRelationId newInstance(Article article, User user) {
return new ArticleBookmarkRelationId(article.getId(), user.getId());
}
}
1 change: 1 addition & 0 deletions src/main/java/indipage/org/indipage/exception/Error.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum Error {
* 409 CONFLICT
*/
ALREADY_INVITED_EXCEPTION(HttpStatus.CONFLICT, "이미 티켓을 수령한 상태입니다."),
ALREADY_BOOKMARKED_ARTICLE_EXCEPTION(HttpStatus.CONFLICT, "이미 북마크한 아티클입니다."),

/**
* 413 PAYLOAD_TOO_LARGE
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/indipage/org/indipage/exception/Success.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public enum Success {
UPDATE_VISIT_SUCCESS(HttpStatus.OK, "공간 방문에 성공했습니다."),
READ_IF_USER_HAS_RECEIVED_TICKET_SUCCESS(HttpStatus.OK, "티켓 수령 여부 조회를 성공했습니다."),
READ_ARTICLE_SUMMARY_LIST_SUCCESS(HttpStatus.OK, "아티클 전체 목록 조회에 성공했습니다."),
READ_IS_ARTICLE_BOOKMARKED_SUCCESS(HttpStatus.OK, "아티클 북마크 여부 조회 성공"),
/**
* 201 CREATED
*/
Expand All @@ -29,8 +30,8 @@ public enum Success {
CREATE_IMAGE_SUCCESS(HttpStatus.CREATED, "이미지 업로드를 완료했습니다."),

CREATE_FOLLOW_SPACE_SUCCESS(HttpStatus.CREATED, "조르기 등록에 성공했습니다."),

CREATE_RECEIVE_TICKET_SUCCESS(HttpStatus.CREATED, "티켓 수령에 성공했습니다.")
CREATE_RECEIVE_TICKET_SUCCESS(HttpStatus.CREATED, "티켓 수령에 성공했습니다."),
CREATE_ARTICLE_BOOKMARK_SUCCESS(HttpStatus.CREATED, "아티클 북마크 등록에 성공했습니다.")
;

private final HttpStatus httpStatus;
Expand Down