Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Beakjiyeon committed Apr 6, 2024
2 parents abe78c4 + bbf118d commit f097972
Show file tree
Hide file tree
Showing 12 changed files with 222 additions and 4 deletions.
5 changes: 5 additions & 0 deletions src/main/java/com/unit/daybook/domain/board/entity/Board.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.unit.daybook.domain.board.dto.request.AddBoardRequestDto;
import com.unit.daybook.domain.common.model.BaseTimeEntity;
import com.unit.daybook.domain.member.domain.Member;
import com.unit.daybook.domain.reaction.entity.Reaction;

import jakarta.persistence.*;
import lombok.*;

Expand Down Expand Up @@ -43,6 +45,9 @@ public class Board extends BaseTimeEntity {
@OneToMany(mappedBy = "board", cascade = CascadeType.ALL)
private List<Hashtag> hashtags = new ArrayList<>();

@OneToMany(mappedBy = "board", cascade = CascadeType.REMOVE)
private List<Reaction> reactions = new ArrayList<>();

@Builder(access = AccessLevel.PRIVATE)
public Board(Long boardId, String content, Long respectBoardId, Member member, String category, Long hearts, String paperType) {
this.boardId = boardId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import com.unit.daybook.domain.board.entity.Board;
import com.unit.daybook.domain.common.model.BaseTimeEntity;
import com.unit.daybook.domain.reaction.entity.Reaction;

import jakarta.persistence.*;
import lombok.AccessLevel;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.unit.daybook.domain.reaction.controller;

import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
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;

import com.unit.daybook.domain.common.annotation.LoginUsers;
import com.unit.daybook.domain.reaction.dto.request.ReactionCreateRequest;
import com.unit.daybook.domain.reaction.dto.response.ReactionCreateResponse;
import com.unit.daybook.domain.reaction.service.ReactionService;
import com.unit.daybook.global.config.security.CustomUserDetails;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequestMapping("/reactions")
@RequiredArgsConstructor
public class ReactionController {

private final ReactionService reactionService;

@PostMapping
public ResponseEntity<ReactionCreateResponse> reactionCreate(
@Valid @RequestBody ReactionCreateRequest request,
@LoginUsers CustomUserDetails userDetails
) {
ReactionCreateResponse reaction = reactionService.createReaction(request, userDetails.getMemberId());
return ResponseEntity.status(HttpStatus.CREATED).body(reaction);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.unit.daybook.domain.reaction.dto.request;

import com.unit.daybook.domain.reaction.entity.ReactionType;

public record ReactionCreateRequest(
Long boardId,
ReactionType reactionType
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.unit.daybook.domain.reaction.dto.response;

import com.unit.daybook.domain.reaction.entity.Reaction;
import com.unit.daybook.domain.reaction.entity.ReactionType;

public record ReactionCreateResponse(
Long reactionId,
ReactionType reactionType,
Long memberId,
Long boardId
) {
public static ReactionCreateResponse from(Reaction reaction) {
return new ReactionCreateResponse(
reaction.getId(),
reaction.getReactionType(),
reaction.getMember().getId(),
reaction.getBoard().getBoardId()
);
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.unit.daybook.domain.reaction.entity;

import com.unit.daybook.domain.board.entity.Board;
import com.unit.daybook.domain.member.domain.Member;

import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand All @@ -15,9 +19,37 @@ public class Reaction {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "reaction_id")
private Long reactionId;
private Long id;

@Enumerated(EnumType.STRING)
private ReactionType reactionType;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "board_id")
private Board board;

@Builder(access = AccessLevel.PRIVATE)
private Reaction(ReactionType reactionType, Member member, Board board) {
this.reactionType = reactionType;
this.member = member;
this.board = board;
}

@Column
private String content;
public static Reaction createReaction(
ReactionType reactionType, Member member, Board board
) {
return Reaction.builder()
.reactionType(reactionType)
.member(member)
.board(board)
.build();
}

public void updateReaction(ReactionType reactionType) {
this.reactionType = reactionType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.unit.daybook.domain.reaction.entity;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum ReactionType {
MOVING,
ADMIRE,
GREAT,
;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.unit.daybook.domain.reaction.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.unit.daybook.domain.reaction.entity.Reaction;

public interface ReactionRepository extends JpaRepository<Reaction, Long>, ReactionRepositoryCustom {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.unit.daybook.domain.reaction.repository;

import com.unit.daybook.domain.board.entity.Board;
import com.unit.daybook.domain.member.domain.Member;
import com.unit.daybook.domain.reaction.entity.Reaction;

public interface ReactionRepositoryCustom {

Reaction findReactionByMemberAndBoard(Member member, Board board);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.unit.daybook.domain.reaction.repository;

import static com.unit.daybook.domain.reaction.entity.QReaction.*;

import org.springframework.stereotype.Repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import com.unit.daybook.domain.board.entity.Board;
import com.unit.daybook.domain.member.domain.Member;
import com.unit.daybook.domain.reaction.entity.Reaction;

import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor
public class ReactionRepositoryImpl implements ReactionRepositoryCustom {

private final JPAQueryFactory jpaQueryFactory;

@Override
public Reaction findReactionByMemberAndBoard(Member member, Board board) {
return jpaQueryFactory.selectFrom(reaction)
.where(
reaction.board.boardId.eq(board.getBoardId()),
reaction.member.id.eq(member.getId()))
.fetchOne();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.unit.daybook.domain.reaction.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.unit.daybook.domain.board.entity.Board;
import com.unit.daybook.domain.board.repository.BoardRepository;
import com.unit.daybook.domain.member.domain.Member;
import com.unit.daybook.domain.member.repository.MemberRepository;
import com.unit.daybook.domain.reaction.dto.request.ReactionCreateRequest;
import com.unit.daybook.domain.reaction.dto.response.ReactionCreateResponse;
import com.unit.daybook.domain.reaction.entity.Reaction;
import com.unit.daybook.domain.reaction.repository.ReactionRepository;
import com.unit.daybook.global.error.exception.CustomException;
import com.unit.daybook.global.error.exception.ErrorCode;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
@Transactional
public class ReactionService {

private final ReactionRepository reactionRepository;
private final MemberRepository memberRepository;
private final BoardRepository boardRepository;

public ReactionCreateResponse createReaction(ReactionCreateRequest request, Long memberId) {
final Member member = findMemberById(memberId);
Board board = boardRepository.findById(request.boardId())
.orElseThrow(() -> new CustomException(ErrorCode.BOARD_NOT_FOUND));

validateReactionMemberMatching(member, board);

Reaction reaction = Reaction.createReaction(request.reactionType(), member, board);
return ReactionCreateResponse.from(reactionRepository.save(reaction));
}

private void validateReactionMemberMatching(Member member, Board board) {
Reaction reaction = reactionRepository.findReactionByMemberAndBoard(member, board);
if (reaction != null) {
throw new CustomException(ErrorCode.REACTION_EXISTS);
}
}

private Member findMemberById(Long memberId) {
return memberRepository.findById(memberId)
.orElseThrow(() -> new CustomException(ErrorCode.MEMBER_NOT_FOUND));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,13 @@ public enum ErrorCode {
EXPIRED_REFRESH_TOKEN(HttpStatus.FORBIDDEN, "리프레시 토큰이 만료되었습니다."),

// Member
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 회원입니다.");
MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 회원입니다."),

// Board
BOARD_NOT_FOUND(HttpStatus.NOT_FOUND, "존재하지 않는 일지입니다."),

// Reaction
REACTION_EXISTS(HttpStatus.CONFLICT, "이미 리액션을 하였습니다.");
private final HttpStatus status;
private final String message;
}

0 comments on commit f097972

Please sign in to comment.