diff --git a/backend/src/main/java/ddangkong/controller/balance/content/dto/BalanceContentResponse.java b/backend/src/main/java/ddangkong/controller/balance/content/dto/BalanceContentResponse.java index 66543da91..9f56359b7 100644 --- a/backend/src/main/java/ddangkong/controller/balance/content/dto/BalanceContentResponse.java +++ b/backend/src/main/java/ddangkong/controller/balance/content/dto/BalanceContentResponse.java @@ -1,26 +1,30 @@ package ddangkong.controller.balance.content.dto; import ddangkong.controller.balance.option.dto.BalanceOptionResponse; -import ddangkong.domain.balance.content.BalanceContent; import ddangkong.domain.balance.content.Category; +import ddangkong.domain.balance.content.RoomContent; import ddangkong.domain.balance.option.BalanceOption; import lombok.Builder; public record BalanceContentResponse( Long contentId, Category category, + int totalRound, + int currentRound, String question, BalanceOptionResponse firstOption, BalanceOptionResponse secondOption ) { @Builder - private BalanceContentResponse(BalanceContent balanceContent, + private BalanceContentResponse(RoomContent roomContent, BalanceOption firstOption, BalanceOption secondOption) { - this(balanceContent.getId(), - balanceContent.getCategory(), - balanceContent.getName(), + this(roomContent.getContentId(), + roomContent.getContentCategory(), + roomContent.getTotalRound(), + roomContent.getRound(), + roomContent.getContentName(), BalanceOptionResponse.from(firstOption), BalanceOptionResponse.from(secondOption)); } diff --git a/backend/src/main/java/ddangkong/controller/exception/GlobalExceptionHandler.java b/backend/src/main/java/ddangkong/controller/exception/GlobalExceptionHandler.java index 1814c07e4..382fd267e 100644 --- a/backend/src/main/java/ddangkong/controller/exception/GlobalExceptionHandler.java +++ b/backend/src/main/java/ddangkong/controller/exception/GlobalExceptionHandler.java @@ -1,7 +1,7 @@ package ddangkong.controller.exception; -import ddangkong.service.excpetion.BusinessLogicException; -import ddangkong.service.excpetion.ViolateDataException; +import ddangkong.exception.BadRequestException; +import ddangkong.exception.InternalServerException; import jakarta.validation.ConstraintViolationException; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -34,7 +34,7 @@ public ErrorResponse handleConstraintViolationException(ConstraintViolationExcep @ExceptionHandler @ResponseStatus(HttpStatus.BAD_REQUEST) - public ErrorResponse handleBusinessLogicException(BusinessLogicException e) { + public ErrorResponse handleBadRequestException(BadRequestException e) { log.warn(e.getMessage()); return new ErrorResponse(e.getMessage()); @@ -42,7 +42,7 @@ public ErrorResponse handleBusinessLogicException(BusinessLogicException e) { @ExceptionHandler @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - public ErrorResponse handleViolateDataException(ViolateDataException e) { + public ErrorResponse handleInternalServerErrorException(InternalServerException e) { log.error(e.getMessage(), e); return new ErrorResponse(SERVER_ERROR_MESSAGE); diff --git a/backend/src/main/java/ddangkong/domain/balance/content/Room.java b/backend/src/main/java/ddangkong/domain/balance/content/Room.java index 7dd029e80..f6d221539 100644 --- a/backend/src/main/java/ddangkong/domain/balance/content/Room.java +++ b/backend/src/main/java/ddangkong/domain/balance/content/Room.java @@ -1,5 +1,6 @@ package ddangkong.domain.balance.content; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -13,7 +14,16 @@ @Getter public class Room { + private static final int DEFAULT_TOTAL_ROUND = 5; + private static final int DEFAULT_CURRENT_ROUND = 1; + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + + @Column(nullable = false) + private int totalRound = DEFAULT_TOTAL_ROUND; + + @Column(nullable = false) + private int currentRound = DEFAULT_CURRENT_ROUND; } diff --git a/backend/src/main/java/ddangkong/domain/balance/content/RoomContent.java b/backend/src/main/java/ddangkong/domain/balance/content/RoomContent.java index 3f99b1f84..dc04a7606 100644 --- a/backend/src/main/java/ddangkong/domain/balance/content/RoomContent.java +++ b/backend/src/main/java/ddangkong/domain/balance/content/RoomContent.java @@ -1,6 +1,7 @@ package ddangkong.domain.balance.content; import ddangkong.domain.BaseEntity; +import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; @@ -28,4 +29,23 @@ public class RoomContent extends BaseEntity { @ManyToOne(optional = false, fetch = FetchType.LAZY) @JoinColumn(name = "balance_content_id") private BalanceContent balanceContent; + + @Column(nullable = false) + private int round; + + public Long getContentId() { + return balanceContent.getId(); + } + + public Category getContentCategory() { + return balanceContent.getCategory(); + } + + public String getContentName() { + return balanceContent.getName(); + } + + public int getTotalRound() { + return room.getTotalRound(); + } } diff --git a/backend/src/main/java/ddangkong/domain/balance/content/RoomContentRepository.java b/backend/src/main/java/ddangkong/domain/balance/content/RoomContentRepository.java index ea9f4ce27..d27a04dda 100644 --- a/backend/src/main/java/ddangkong/domain/balance/content/RoomContentRepository.java +++ b/backend/src/main/java/ddangkong/domain/balance/content/RoomContentRepository.java @@ -5,5 +5,5 @@ public interface RoomContentRepository extends JpaRepository { - Optional findTopByRoomIdOrderByCreatedAtDesc(Long roomId); + Optional findByRoomAndRound(Room room, int round); } diff --git a/backend/src/main/java/ddangkong/domain/balance/content/RoomRepository.java b/backend/src/main/java/ddangkong/domain/balance/content/RoomRepository.java new file mode 100644 index 000000000..e9b0759ec --- /dev/null +++ b/backend/src/main/java/ddangkong/domain/balance/content/RoomRepository.java @@ -0,0 +1,6 @@ +package ddangkong.domain.balance.content; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RoomRepository extends JpaRepository { +} diff --git a/backend/src/main/java/ddangkong/exception/BadRequestException.java b/backend/src/main/java/ddangkong/exception/BadRequestException.java new file mode 100644 index 000000000..39849d34f --- /dev/null +++ b/backend/src/main/java/ddangkong/exception/BadRequestException.java @@ -0,0 +1,8 @@ +package ddangkong.exception; + +public class BadRequestException extends RuntimeException { + + public BadRequestException(String message) { + super(message); + } +} diff --git a/backend/src/main/java/ddangkong/exception/InternalServerException.java b/backend/src/main/java/ddangkong/exception/InternalServerException.java new file mode 100644 index 000000000..43f60da4e --- /dev/null +++ b/backend/src/main/java/ddangkong/exception/InternalServerException.java @@ -0,0 +1,8 @@ +package ddangkong.exception; + +public class InternalServerException extends RuntimeException { + + public InternalServerException(String message) { + super(message); + } +} diff --git a/backend/src/main/java/ddangkong/service/balance/content/BalanceContentService.java b/backend/src/main/java/ddangkong/service/balance/content/BalanceContentService.java index a3a4b6114..775a2937e 100644 --- a/backend/src/main/java/ddangkong/service/balance/content/BalanceContentService.java +++ b/backend/src/main/java/ddangkong/service/balance/content/BalanceContentService.java @@ -2,11 +2,14 @@ import ddangkong.controller.balance.content.dto.BalanceContentResponse; import ddangkong.domain.balance.content.BalanceContent; +import ddangkong.domain.balance.content.Room; +import ddangkong.domain.balance.content.RoomContent; import ddangkong.domain.balance.content.RoomContentRepository; +import ddangkong.domain.balance.content.RoomRepository; import ddangkong.domain.balance.option.BalanceOption; import ddangkong.domain.balance.option.BalanceOptionRepository; -import ddangkong.service.excpetion.BusinessLogicException; -import ddangkong.service.excpetion.ViolateDataException; +import ddangkong.exception.BadRequestException; +import ddangkong.exception.InternalServerException; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -18,26 +21,29 @@ public class BalanceContentService { private static final int BALANCE_OPTION_SIZE = 2; + private final RoomRepository roomRepository; + private final RoomContentRepository roomContentRepository; private final BalanceOptionRepository balanceOptionRepository; @Transactional(readOnly = true) public BalanceContentResponse findRecentBalanceContent(Long roomId) { - BalanceContent balanceContent = findRecentContent(roomId); - List balanceOptions = findBalanceOptions(balanceContent); + RoomContent roomContent = findCurrentRoomContent(roomId); + List balanceOptions = findBalanceOptions(roomContent.getBalanceContent()); return BalanceContentResponse.builder() - .balanceContent(balanceContent) + .roomContent(roomContent) .firstOption(balanceOptions.get(0)) .secondOption(balanceOptions.get(1)) .build(); } - private BalanceContent findRecentContent(Long roomId) { - return roomContentRepository.findTopByRoomIdOrderByCreatedAtDesc(roomId) - .orElseThrow(() -> new BusinessLogicException("해당 방의 질문이 존재하지 않습니다.")) - .getBalanceContent(); + private RoomContent findCurrentRoomContent(Long roomId) { + Room room = roomRepository.findById(roomId) + .orElseThrow(() -> new BadRequestException("해당 방이 존재하지 않습니다.")); + return roomContentRepository.findByRoomAndRound(room, room.getCurrentRound()) + .orElseThrow(() -> new BadRequestException("해당 방의 현재 진행중인 질문이 존재하지 않습니다.")); } private List findBalanceOptions(BalanceContent balanceContent) { @@ -48,7 +54,7 @@ private List findBalanceOptions(BalanceContent balanceContent) { private void validateBalanceOptions(List balanceOptions) { if (balanceOptions.size() != BALANCE_OPTION_SIZE) { - throw new ViolateDataException("밸런스 게임의 선택지가 %d개입니다".formatted(balanceOptions.size())); + throw new InternalServerException("밸런스 게임의 선택지가 %d개입니다".formatted(balanceOptions.size())); } } } diff --git a/backend/src/main/java/ddangkong/service/excpetion/BusinessLogicException.java b/backend/src/main/java/ddangkong/service/excpetion/BusinessLogicException.java deleted file mode 100644 index d2b522cb4..000000000 --- a/backend/src/main/java/ddangkong/service/excpetion/BusinessLogicException.java +++ /dev/null @@ -1,8 +0,0 @@ -package ddangkong.service.excpetion; - -public class BusinessLogicException extends RuntimeException { - - public BusinessLogicException(String message) { - super(message); - } -} diff --git a/backend/src/main/java/ddangkong/service/excpetion/ViolateDataException.java b/backend/src/main/java/ddangkong/service/excpetion/ViolateDataException.java deleted file mode 100644 index 48192f9b1..000000000 --- a/backend/src/main/java/ddangkong/service/excpetion/ViolateDataException.java +++ /dev/null @@ -1,8 +0,0 @@ -package ddangkong.service.excpetion; - -public class ViolateDataException extends RuntimeException { - - public ViolateDataException(String message) { - super(message); - } -} diff --git a/backend/src/test/java/ddangkong/controller/balance/content/BalanceContentControllerTest.java b/backend/src/test/java/ddangkong/controller/balance/content/BalanceContentControllerTest.java index 67d24b7d6..722b8d86f 100644 --- a/backend/src/test/java/ddangkong/controller/balance/content/BalanceContentControllerTest.java +++ b/backend/src/test/java/ddangkong/controller/balance/content/BalanceContentControllerTest.java @@ -16,7 +16,7 @@ class BalanceContentControllerTest extends BaseControllerTest { class 현재_방의_내용_조회 { private static final BalanceContentResponse EXPECTED_RESPONSE = new BalanceContentResponse( - 1L, Category.EXAMPLE, "민초 vs 반민초", + 1L, Category.EXAMPLE, 5, 2, "민초 vs 반민초", new BalanceOptionResponse(1L, "민초"), new BalanceOptionResponse(2L, "반민초")); diff --git a/backend/src/test/java/ddangkong/domain/balance/content/RoomContentRepositoryTest.java b/backend/src/test/java/ddangkong/domain/balance/content/RoomContentRepositoryTest.java index 91d270ebf..067644f0d 100644 --- a/backend/src/test/java/ddangkong/domain/balance/content/RoomContentRepositoryTest.java +++ b/backend/src/test/java/ddangkong/domain/balance/content/RoomContentRepositoryTest.java @@ -12,16 +12,21 @@ class RoomContentRepositoryTest extends BaseRepositoryTest { @Autowired private RoomContentRepository roomContentRepository; + @Autowired + private RoomRepository roomRepository; + @Nested - class 방의_최신_질문_조회 { + class 방의_해당_라운드_질문_조회 { @Test - void 방의_가장_최신의_질문을_조회할_수_있다() { + void 방의_해당_라운드의_질문을_조회할_수_있다() { // given Long roomId = 1L; + Room room = roomRepository.findById(roomId).get(); + int round = 2; // when - RoomContent actual = roomContentRepository.findTopByRoomIdOrderByCreatedAtDesc(roomId).get(); + RoomContent actual = roomContentRepository.findByRoomAndRound(room, round).get(); // then assertThat(actual.getId()).isEqualTo(2L); diff --git a/backend/src/test/java/ddangkong/service/balance/content/BalanceContentServiceTest.java b/backend/src/test/java/ddangkong/service/balance/content/BalanceContentServiceTest.java index fc87fda26..1845abc9b 100644 --- a/backend/src/test/java/ddangkong/service/balance/content/BalanceContentServiceTest.java +++ b/backend/src/test/java/ddangkong/service/balance/content/BalanceContentServiceTest.java @@ -6,29 +6,29 @@ import ddangkong.controller.balance.content.dto.BalanceContentResponse; import ddangkong.controller.balance.option.dto.BalanceOptionResponse; import ddangkong.domain.balance.content.Category; +import ddangkong.exception.BadRequestException; import ddangkong.service.BaseServiceTest; -import ddangkong.service.excpetion.BusinessLogicException; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; class BalanceContentServiceTest extends BaseServiceTest { - private static final Long PROGRESS_ROOM_ID = 1L; - private static final Long NOT_EXIST_ROOM_ID = 2L; - private static final BalanceContentResponse BALANCE_CONTENT_RESPONSE = new BalanceContentResponse( - 1L, Category.EXAMPLE, "민초 vs 반민초", - new BalanceOptionResponse(1L, "민초"), - new BalanceOptionResponse(2L, "반민초")); - @Autowired private BalanceContentService balanceContentService; - @Nested class 현재_방의_밸런스_게임_내용_조회 { + private static final Long PROGRESS_ROOM_ID = 1L; + private static final Long NOT_EXIST_ROOM_ID = 3L; + private static final Long NOT_PROGRESSED_ROOM_ID = 2L; + private static final BalanceContentResponse BALANCE_CONTENT_RESPONSE = new BalanceContentResponse( + 1L, Category.EXAMPLE, 5, 2, "민초 vs 반민초", + new BalanceOptionResponse(1L, "민초"), + new BalanceOptionResponse(2L, "반민초")); + @Test - void 방의_최신_밸런스_게임_내용을_조회할_수_있다() { + void 방의_진행_중인_밸런스_게임_내용을_조회할_수_있다() { // when BalanceContentResponse actual = balanceContentService.findRecentBalanceContent(PROGRESS_ROOM_ID); @@ -40,8 +40,16 @@ class 현재_방의_밸런스_게임_내용_조회 { void 방이_없을_경우_예외를_던진다() { // when & then assertThatThrownBy(() -> balanceContentService.findRecentBalanceContent(NOT_EXIST_ROOM_ID)) - .isInstanceOf(BusinessLogicException.class) - .hasMessage("해당 방의 질문이 존재하지 않습니다."); + .isInstanceOf(BadRequestException.class) + .hasMessage("해당 방이 존재하지 않습니다."); + } + + @Test + void 방의_현재_라운드의_질문이_없을_경우_예외를_던진다() { + // when & then + assertThatThrownBy(() -> balanceContentService.findRecentBalanceContent(NOT_PROGRESSED_ROOM_ID)) + .isInstanceOf(BadRequestException.class) + .hasMessage("해당 방의 현재 진행중인 질문이 존재하지 않습니다."); } } } diff --git a/backend/src/test/resources/init-test.sql b/backend/src/test/resources/init-test.sql index a583b8f4b..4f1cdee0e 100644 --- a/backend/src/test/resources/init-test.sql +++ b/backend/src/test/resources/init-test.sql @@ -1,5 +1,5 @@ -INSERT INTO room () -VALUES (); +INSERT INTO room (total_round, current_round) +VALUES (5, 2), (5, 1); INSERT INTO member (nickname, room_id) VALUES ('mohamedeu al katan', 1), @@ -11,9 +11,9 @@ INSERT INTO balance_content (category, name) VALUES ('EXAMPLE', '민초 vs 반민초'), ('EXAMPLE', '월 200 백수 vs 월 500 직장인'); -INSERT INTO room_content (room_id, balance_content_id, created_at) -VALUES (1, 2, '2024-07-18 19:50:00.000'), - (1, 1, '2024-07-18 20:00:00.000'); +INSERT INTO room_content (room_id, balance_content_id, round, created_at) +VALUES (1, 2, 1, '2024-07-18 19:50:00.000'), + (1, 1, 2, '2024-07-18 20:00:00.000'); INSERT INTO balance_option (name, balance_content_id) VALUES ('민초', 1),