diff --git a/src/docs/asciidoc/index.adoc b/src/docs/asciidoc/index.adoc index 26ed4af9..0f89da7d 100644 --- a/src/docs/asciidoc/index.adoc +++ b/src/docs/asciidoc/index.adoc @@ -45,11 +45,21 @@ operation::admin-seat-controller-test/create-seat-grades[snippets='http-response === request -operation::seat-controller-test/get-zones[snippets='http-request,path-parameters'] +operation::seat-controller-test/get-seats[snippets='http-request,path-parameters'] === response -operation::seat-controller-test/get-zones[snippets='http-response,response-fields'] +operation::seat-controller-test/get-seats[snippets='http-response,response-fields'] + +== 공연의 좌석 등급 목록 조회 + +=== request + +operation::seat-controller-test/get-seat-grades[snippets='http-request,path-parameters'] + +=== response + +operation::seat-controller-test/get-seat-grades[snippets='http-response,response-fields'] = 티켓(Ticket) diff --git a/src/main/java/com/thirdparty/ticketing/domain/ItemResult.java b/src/main/java/com/thirdparty/ticketing/domain/ItemResult.java index 430e4ec5..48ca518c 100644 --- a/src/main/java/com/thirdparty/ticketing/domain/ItemResult.java +++ b/src/main/java/com/thirdparty/ticketing/domain/ItemResult.java @@ -12,6 +12,6 @@ public class ItemResult { private List items; public static ItemResult of(List items) { - return new ItemResult(items); + return new ItemResult<>(items); } } diff --git a/src/main/java/com/thirdparty/ticketing/domain/seat/controller/SeatController.java b/src/main/java/com/thirdparty/ticketing/domain/seat/controller/SeatController.java index 4e0e9b73..30f58cba 100644 --- a/src/main/java/com/thirdparty/ticketing/domain/seat/controller/SeatController.java +++ b/src/main/java/com/thirdparty/ticketing/domain/seat/controller/SeatController.java @@ -8,6 +8,7 @@ import com.thirdparty.ticketing.domain.ItemResult; import com.thirdparty.ticketing.domain.seat.dto.response.SeatElement; +import com.thirdparty.ticketing.domain.seat.dto.response.SeatGradeElement; import com.thirdparty.ticketing.domain.seat.service.SeatService; import lombok.RequiredArgsConstructor; @@ -23,4 +24,11 @@ public ResponseEntity> getSeats(@PathVariable("zoneId") ItemResult seats = seatService.getSeats(zoneId); return ResponseEntity.ok().body(seats); } + + @GetMapping("/performances/{performanceId}/grades") + public ResponseEntity> getSeatGrades( + @PathVariable("performanceId") long performanceId) { + ItemResult seatGrades = seatService.getSeatGrades(performanceId); + return ResponseEntity.ok().body(seatGrades); + } } diff --git a/src/main/java/com/thirdparty/ticketing/domain/seat/dto/response/SeatGradeElement.java b/src/main/java/com/thirdparty/ticketing/domain/seat/dto/response/SeatGradeElement.java new file mode 100644 index 00000000..9ea07449 --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/seat/dto/response/SeatGradeElement.java @@ -0,0 +1,17 @@ +package com.thirdparty.ticketing.domain.seat.dto.response; + +import com.thirdparty.ticketing.domain.seat.SeatGrade; + +import lombok.Data; + +@Data +public class SeatGradeElement { + private final Long gradeId; + private final String gradeName; + private final Long price; + + public static SeatGradeElement of(SeatGrade seatGrade) { + return new SeatGradeElement( + seatGrade.getSeatGradeId(), seatGrade.getGradeName(), seatGrade.getPrice()); + } +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/seat/repository/SeatGradeRepository.java b/src/main/java/com/thirdparty/ticketing/domain/seat/repository/SeatGradeRepository.java index 4615ae3a..db4132bc 100644 --- a/src/main/java/com/thirdparty/ticketing/domain/seat/repository/SeatGradeRepository.java +++ b/src/main/java/com/thirdparty/ticketing/domain/seat/repository/SeatGradeRepository.java @@ -6,6 +6,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; +import com.thirdparty.ticketing.domain.performance.Performance; import com.thirdparty.ticketing.domain.seat.SeatGrade; public interface SeatGradeRepository extends JpaRepository { @@ -18,4 +19,6 @@ public interface SeatGradeRepository extends JpaRepository { """) List findByPerformanceIdAndGradeNames( @Param("performanceId") long performanceId, @Param("gradeIds") List gradeIds); + + List findAllByPerformance(Performance performance); } diff --git a/src/main/java/com/thirdparty/ticketing/domain/seat/service/SeatService.java b/src/main/java/com/thirdparty/ticketing/domain/seat/service/SeatService.java index 179cf52f..f9313523 100644 --- a/src/main/java/com/thirdparty/ticketing/domain/seat/service/SeatService.java +++ b/src/main/java/com/thirdparty/ticketing/domain/seat/service/SeatService.java @@ -7,7 +7,11 @@ import com.thirdparty.ticketing.domain.ItemResult; import com.thirdparty.ticketing.domain.common.TicketingException; +import com.thirdparty.ticketing.domain.performance.Performance; +import com.thirdparty.ticketing.domain.performance.repository.PerformanceRepository; import com.thirdparty.ticketing.domain.seat.dto.response.SeatElement; +import com.thirdparty.ticketing.domain.seat.dto.response.SeatGradeElement; +import com.thirdparty.ticketing.domain.seat.repository.SeatGradeRepository; import com.thirdparty.ticketing.domain.seat.repository.SeatRepository; import com.thirdparty.ticketing.domain.zone.Zone; import com.thirdparty.ticketing.domain.zone.repository.ZoneRepository; @@ -17,7 +21,9 @@ @Service @RequiredArgsConstructor public class SeatService { + private final PerformanceRepository performanceRepository; private final ZoneRepository zoneRepository; + private final SeatGradeRepository seatGradeRepository; private final SeatRepository seatRepository; @Transactional(readOnly = true) @@ -28,4 +34,18 @@ public ItemResult getSeats(Long zoneId) { return ItemResult.of(seats); } + + @Transactional(readOnly = true) + public ItemResult getSeatGrades(Long performanceId) { + Performance performance = + performanceRepository + .findById(performanceId) + .orElseThrow(() -> new TicketingException((""))); + List seatGrades = + seatGradeRepository.findAllByPerformance(performance).stream() + .map(SeatGradeElement::of) + .toList(); + + return ItemResult.of(seatGrades); + } } diff --git a/src/test/java/com/thirdparty/ticketing/domain/seat/controller/SeatControllerTest.java b/src/test/java/com/thirdparty/ticketing/domain/seat/controller/SeatControllerTest.java index eb5c10ae..5a7600a0 100644 --- a/src/test/java/com/thirdparty/ticketing/domain/seat/controller/SeatControllerTest.java +++ b/src/test/java/com/thirdparty/ticketing/domain/seat/controller/SeatControllerTest.java @@ -1,6 +1,6 @@ package com.thirdparty.ticketing.domain.seat.controller; -import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; @@ -9,7 +9,6 @@ import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import java.util.Collections; import java.util.List; import org.junit.jupiter.api.DisplayName; @@ -21,6 +20,7 @@ import com.thirdparty.ticketing.domain.ItemResult; import com.thirdparty.ticketing.domain.seat.dto.response.SeatElement; +import com.thirdparty.ticketing.domain.seat.dto.response.SeatGradeElement; import com.thirdparty.ticketing.domain.seat.service.SeatService; import com.thirdparty.ticketing.support.BaseControllerTest; @@ -30,15 +30,15 @@ public class SeatControllerTest extends BaseControllerTest { @Test @DisplayName("구역의 좌석 목록을 조회한다.") - void getZones() throws Exception { + void getSeats() throws Exception { // Given long performanceId = 1L; long zoneId = 2L; List seatElements = - Collections.singletonList(new SeatElement(1L, "A01", true)); + List.of(new SeatElement(1L, "A01", true), new SeatElement(2L, "B01", false)); - given(seatService.getSeats(any())).willReturn(ItemResult.of(seatElements)); + given(seatService.getSeats(anyLong())).willReturn(ItemResult.of(seatElements)); // When ResultActions result = @@ -70,4 +70,44 @@ void getZones() throws Exception { .type(JsonFieldType.BOOLEAN) .description("좌석 선택 가능 여부")))); } + + @Test + @DisplayName("공연의 좌석 등급 목록을 조회한다.") + void getSeatGrades() throws Exception { + // Given + long performanceId = 1L; + + List seatGradeElements = + List.of( + new SeatGradeElement(1L, "Grade1", 10000L), + new SeatGradeElement(2L, "Grade2", 20000L)); + + given(seatService.getSeatGrades(anyLong())).willReturn(ItemResult.of(seatGradeElements)); + + // When + ResultActions result = + mockMvc.perform( + get("/api/performances/{performanceId}/grades", performanceId) + .header(AUTHORIZATION_HEADER, adminBearerToken)); + + // Then + result.andExpect(status().isOk()) + .andDo( + restDocs.document( + pathParameters( + parameterWithName("performanceId").description("공연 ID")), + responseFields( + fieldWithPath("items") + .type(JsonFieldType.ARRAY) + .description("좌석 등급 목록"), + fieldWithPath("items[].gradeId") + .type(JsonFieldType.NUMBER) + .description("좌석 등급 ID"), + fieldWithPath("items[].gradeName") + .type(JsonFieldType.STRING) + .description("좌석 등급 이름"), + fieldWithPath("items[].price") + .type(JsonFieldType.NUMBER) + .description("좌석 등급 가격")))); + } } diff --git a/src/test/java/com/thirdparty/ticketing/domain/seat/service/SeatServiceTest.java b/src/test/java/com/thirdparty/ticketing/domain/seat/service/SeatServiceTest.java index 0085f796..a8e66abd 100644 --- a/src/test/java/com/thirdparty/ticketing/domain/seat/service/SeatServiceTest.java +++ b/src/test/java/com/thirdparty/ticketing/domain/seat/service/SeatServiceTest.java @@ -18,9 +18,12 @@ import com.thirdparty.ticketing.domain.member.Member; import com.thirdparty.ticketing.domain.member.MemberRole; import com.thirdparty.ticketing.domain.performance.Performance; +import com.thirdparty.ticketing.domain.performance.repository.PerformanceRepository; import com.thirdparty.ticketing.domain.seat.Seat; import com.thirdparty.ticketing.domain.seat.SeatGrade; import com.thirdparty.ticketing.domain.seat.dto.response.SeatElement; +import com.thirdparty.ticketing.domain.seat.dto.response.SeatGradeElement; +import com.thirdparty.ticketing.domain.seat.repository.SeatGradeRepository; import com.thirdparty.ticketing.domain.seat.repository.SeatRepository; import com.thirdparty.ticketing.domain.zone.Zone; import com.thirdparty.ticketing.domain.zone.repository.ZoneRepository; @@ -28,8 +31,10 @@ @DataJpaTest public class SeatServiceTest { @Autowired private TestEntityManager testEntityManager; - @Autowired private SeatRepository seatRepository; + @Autowired private PerformanceRepository performanceRepository; @Autowired private ZoneRepository zoneRepository; + @Autowired private SeatGradeRepository seatGradeRepository; + @Autowired private SeatRepository seatRepository; private SeatService seatService; @@ -41,7 +46,9 @@ public class SeatServiceTest { @BeforeEach void setUpBase() { - seatService = new SeatService(zoneRepository, seatRepository); + seatService = + new SeatService( + performanceRepository, zoneRepository, seatGradeRepository, seatRepository); setUpMember(); setUpPerformance(); setUpZone(); @@ -100,7 +107,7 @@ private void setUpSeatGrades() { } @Nested - @DisplayName("getZones 메서드를 호출할 때") + @DisplayName("getSeats 메소드를 호출할 때") class GetZonesTest { private Seat seat1; private Seat seat2; @@ -125,7 +132,7 @@ void setUp() { } @Test - @DisplayName("좌석 등급이 성공적으로 생성된다.") + @DisplayName("좌석 목록이 성공적으로 생성된다.") void getZones_success() { // Given testEntityManager.persistAndFlush(seat1); @@ -149,4 +156,36 @@ private void assertSeatElement(SeatElement seatElement, Seat expectedSeat) { assertThat(seatElement.getSeatCode()).isEqualTo(expectedSeat.getSeatCode()); } } + + @Nested + @DisplayName("getSeatGrades 메소드를 호출할 때") + class GetSeatGradesTest { + + @Test + @DisplayName("좌석 등급 목록이 성공적으로 반환된다.") + void getSeatGrades_success() { + // Given + Long performanceId = performance.getPerformanceId(); + + // When + ItemResult seatGradesResult = + seatService.getSeatGrades(performanceId); + + // Then + List seatGradeElements = seatGradesResult.getItems(); + SeatGradeElement seatGradeElement1 = seatGradeElements.get(0); + SeatGradeElement seatGradeElement2 = seatGradeElements.get(1); + + assertThat(seatGradeElements).hasSize(2); + assertSeatGradeElement(seatGradeElement1, seatGrade1); + assertSeatGradeElement(seatGradeElement2, seatGrade2); + } + + private void assertSeatGradeElement( + SeatGradeElement seatGradeElement, SeatGrade expectedSeatGrade) { + assertThat(seatGradeElement.getGradeId()).isEqualTo(expectedSeatGrade.getSeatGradeId()); + assertThat(seatGradeElement.getGradeName()).isEqualTo(expectedSeatGrade.getGradeName()); + assertThat(seatGradeElement.getPrice()).isEqualTo(expectedSeatGrade.getPrice()); + } + } }