Skip to content

Commit

Permalink
[feat]: 조회 기간에 따른 예매 티켓 조회 API 추가 (#62)
Browse files Browse the repository at this point in the history
* [chore]: 페이징을 위한 의존성 추가

* [feat]: 예매 조회 controller 추가

* [test]: 예매 조회 인수테스트 추가

* [feat]: 예매 조회 application 추가

* [feat]: 예매 조회 repository, adaptor 추가

* [test]: 예매 조회 jpaRepository 쿼리 테스트 추가

* [refactor]: 예약 도메인 리팩토링 및 도메인 내장함수 추가

* [feat]: 예매 조회 응답 Response 추가

* [refactor]: 예매, 티켓 도메인 리팩토링 및 내장함수 추가

* [feat]: Response 매퍼 추가

* [refactor]: 리팩토링 적용

* [refactor]: 테스트 리팩토링

* [refactor]: 리팩토링
  • Loading branch information
ssssujini99 authored Jan 13, 2024
1 parent 0213b45 commit 173e415
Show file tree
Hide file tree
Showing 14 changed files with 387 additions and 6 deletions.
1 change: 1 addition & 0 deletions api/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework:spring-tx:6.1.1'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
//swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.1.0'

Expand Down
39 changes: 39 additions & 0 deletions api/src/main/java/dev/hooon/booking/BookingApiController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dev.hooon.booking;

import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import dev.hooon.auth.jwt.JwtAuthorization;
import dev.hooon.booking.application.BookingService;
import dev.hooon.booking.dto.response.BookingListResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
public class BookingApiController {

private final BookingService bookingService;

@GetMapping("/api/users/booking")
@Operation(summary = "예매 조회 API", description = "예매를 조회한다")
@ApiResponse(responseCode = "200", useReturnTypeSchema = true)
public ResponseEntity<BookingListResponse> getBookings(
@Parameter(hidden = true) @JwtAuthorization Long userId,
@RequestParam(name = "duration") int duration,
@PageableDefault(size = 10) Pageable pageable
) {
BookingListResponse bookingListResponse = bookingService.getBookings(
userId,
duration,
pageable
);
return ResponseEntity.ok(bookingListResponse);
}
}
98 changes: 98 additions & 0 deletions api/src/test/java/dev/hooon/booking/BookingApiControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package dev.hooon.booking;

import static org.springframework.http.HttpHeaders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import dev.hooon.common.support.ApiTestSupport;
import dev.hooon.user.domain.entity.User;

@DisplayName("[BookingApiController API 테스트]")
@Sql("/sql/user_bookings_find.sql")
class BookingApiControllerTest extends ApiTestSupport {

@Autowired
private MockMvc mockMvc;

@DisplayName("사용자는 조회 기간에 따른 예매 정보를 조회할 수 있다 - 1")
@Test
void getBookings_test_1() throws Exception {

// given
User user = new User();
ReflectionTestUtils.setField(user, "id", 1L);

// when
ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders
.get("/api/users/booking?duration=3600&page=0&size=2")
.header(AUTHORIZATION, accessToken)
);

// then
resultActions.andExpectAll(
status().isOk(),

jsonPath("$.bookingList.length()").value(2),

jsonPath("$.bookingList[0].bookingId").isNumber(),
jsonPath("$.bookingList[0].bookingDate").isString(),
jsonPath("$.bookingList[0].showInfo.showName").isString(),
jsonPath("$.bookingList[0].showInfo.showDate").isString(),
jsonPath("$.bookingList[0].showInfo.showRound").isNumber(),
jsonPath("$.bookingList[0].showInfo.showRoundStartTime").isString(),
jsonPath("$.bookingList[0].ticketNumber").isNumber(),
jsonPath("$.bookingList[0].currentState").isString(),

jsonPath("$.bookingList[1].bookingId").isNumber(),
jsonPath("$.bookingList[1].bookingDate").isString(),
jsonPath("$.bookingList[1].showInfo.showName").isString(),
jsonPath("$.bookingList[1].showInfo.showDate").isString(),
jsonPath("$.bookingList[1].showInfo.showRound").isNumber(),
jsonPath("$.bookingList[1].showInfo.showRoundStartTime").isString(),
jsonPath("$.bookingList[1].ticketNumber").isNumber(),
jsonPath("$.bookingList[1].currentState").isString()
);
}

@DisplayName("사용자는 조회 기간에 따른 예매 정보를 조회할 수 있다 - 2")
@Test
void getBookings_test_2() throws Exception {

// given
User user = new User();
ReflectionTestUtils.setField(user, "id", 1L);

// when
ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders
.get("/api/users/booking?duration=30&page=0&size=2")
.header(AUTHORIZATION, accessToken)
);

// then
resultActions.andExpectAll(
status().isOk(),

jsonPath("$.bookingList.length()").value(1),

jsonPath("$.bookingList[0].bookingId").isNumber(),
jsonPath("$.bookingList[0].bookingDate").isString(),
jsonPath("$.bookingList[0].showInfo.showName").isString(),
jsonPath("$.bookingList[0].showInfo.showDate").isString(),
jsonPath("$.bookingList[0].showInfo.showRound").isNumber(),
jsonPath("$.bookingList[0].showInfo.showRoundStartTime").isString(),
jsonPath("$.bookingList[0].ticketNumber").isNumber(),
jsonPath("$.bookingList[0].currentState").isString()

);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,22 @@

import static dev.hooon.booking.exception.BookingErrorCode.*;

import java.time.LocalDateTime;
import java.util.List;

import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import dev.hooon.booking.domain.entity.Booking;
import dev.hooon.booking.domain.entity.BookingStatus;
import dev.hooon.booking.domain.entity.Ticket;
import dev.hooon.booking.domain.repository.BookingRepository;
import dev.hooon.booking.dto.BookingMapper;
import dev.hooon.booking.dto.response.BookingCancelResponse;
import dev.hooon.booking.dto.response.BookingListResponse;
import dev.hooon.common.exception.NotFoundException;
import dev.hooon.common.exception.ValidationException;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;

@Service
Expand Down Expand Up @@ -65,4 +70,15 @@ public Booking getById(Long id) {
);
}

@Transactional(readOnly = true)
public BookingListResponse getBookings(
Long userId,
int days,
Pageable pageable
) {
LocalDateTime currentDateTime = LocalDateTime.now();
LocalDateTime createdDateTime = currentDateTime.minusDays(days);
List<Booking> bookingList = bookingRepository.findByUserIdAndDays(userId, createdDateTime, pageable);
return BookingMapper.toBookingListResponse(bookingList);
}
}
49 changes: 44 additions & 5 deletions core/src/main/java/dev/hooon/booking/domain/entity/Booking.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
import static jakarta.persistence.GenerationType.*;
import static lombok.AccessLevel.*;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -46,12 +49,12 @@ public class Booking extends TimeBaseEntity {
@JoinColumn(name = "booking_show_id", nullable = false, foreignKey = @ForeignKey(value = NO_CONSTRAINT))
private Show show;

@Enumerated(STRING)
@Column(name = "booking_status", nullable = false)
private BookingStatus bookingStatus;
@Enumerated(STRING)
@Column(name = "booking_status", nullable = false)
private BookingStatus bookingStatus;

@Column(name = "booking_ticket_count", nullable = false)
private int ticketCount = 0;
@Column(name = "booking_ticket_count", nullable = false)
private int ticketCount = 0;

@OneToMany(mappedBy = "booking", cascade = CascadeType.ALL, orphanRemoval = true)
private final List<Ticket> tickets = new ArrayList<>();
Expand All @@ -68,18 +71,54 @@ private Booking(User user, Show show) {
this.bookingStatus = BOOKED;
}

private Booking(User user, Show show, LocalDateTime localDateTime) {
this.user = user;
this.show = show;
this.bookingStatus = BOOKED;
this.createdAt = localDateTime;
}

public static Booking of(
User user,
Show show
) {
return new Booking(user, show);
}

public static Booking of(
User user,
Show show,
LocalDateTime localDateTime
) {
return new Booking(user, show, localDateTime);
}

public void markBookingStatusAsCanceled() {
this.bookingStatus = CANCELED;
}

public long getUserId() {
return this.user.getId();
}

public String getShowName() {
return this.getShow().getName();
}

public LocalDate getShowDate() {
return getFirstTicket().getShowDate();
}

public int getRound() {
return getFirstTicket().getRound();
}

public LocalTime getStartTime() {
return getFirstTicket().getStartTime();
}

public Ticket getFirstTicket() {
return this.getTickets().get(0);
}

}
15 changes: 15 additions & 0 deletions core/src/main/java/dev/hooon/booking/domain/entity/Ticket.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import static jakarta.persistence.GenerationType.*;
import static lombok.AccessLevel.*;

import java.time.LocalDate;
import java.time.LocalTime;

import dev.hooon.common.entity.TimeBaseEntity;
import dev.hooon.show.domain.entity.seat.Seat;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -54,4 +57,16 @@ public void setBooking(Booking booking) {
public void markSeatStatusAsCanceled() {
this.seat.markSeatStatusAsCanceled();
}

public LocalDate getShowDate() {
return this.getSeat().getShowDate();
}

public int getRound() {
return this.getSeat().getRound();
}

public LocalTime getStartTime() {
return this.getSeat().getStartTime();
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package dev.hooon.booking.domain.repository;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;

import org.springframework.data.domain.Pageable;

import dev.hooon.booking.domain.entity.Booking;

public interface BookingRepository {
Expand All @@ -12,4 +15,10 @@ public interface BookingRepository {
List<Booking> findAll();

Optional<Booking> findByIdWithTickets(Long id);

List<Booking> findByUserIdAndDays(
Long userId,
LocalDateTime createdDateTime,
Pageable pageable
);
}
21 changes: 21 additions & 0 deletions core/src/main/java/dev/hooon/booking/dto/BookingMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

import dev.hooon.booking.domain.entity.Booking;
import dev.hooon.booking.dto.response.BookingCancelResponse;
import dev.hooon.booking.dto.response.BookingListResponse;
import dev.hooon.booking.dto.response.BookingResponse;
import dev.hooon.booking.dto.response.ShowInfoResponse;
import dev.hooon.booking.dto.response.TicketBookingResponse;
import dev.hooon.booking.dto.response.TicketResponse;
import dev.hooon.booking.dto.response.TicketSeatResponse;
Expand Down Expand Up @@ -45,4 +48,22 @@ public static BookingCancelResponse toBookingCancelResponse(Booking booking) {
ticketSeatResponseList
);
}

public static BookingListResponse toBookingListResponse(List<Booking> bookingList) {
List<BookingResponse> bookingResponseList = bookingList.stream()
.map(booking -> new BookingResponse(
booking.getId(),
booking.getCreatedAt().toLocalDate(),
new ShowInfoResponse(
booking.getShowName(),
booking.getShowDate(),
booking.getRound(),
booking.getStartTime()
),
booking.getTicketCount(),
booking.getBookingStatus().toString()
))
.toList();
return new BookingListResponse(bookingResponseList);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.hooon.booking.dto.response;

import java.util.List;

public record BookingListResponse(
List<BookingResponse> bookingList
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package dev.hooon.booking.dto.response;

import java.time.LocalDate;

import com.fasterxml.jackson.annotation.JsonFormat;

public record BookingResponse(
long bookingId,
@JsonFormat(pattern = "yyyy-MM-dd")
LocalDate bookingDate,
ShowInfoResponse showInfo,
int ticketNumber,
String currentState
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package dev.hooon.booking.dto.response;

import java.time.LocalDate;
import java.time.LocalTime;

import com.fasterxml.jackson.annotation.JsonFormat;

public record ShowInfoResponse(
String showName,
@JsonFormat(pattern = "yyyy-MM-dd")
LocalDate showDate,
int showRound,
@JsonFormat(pattern = "HH:mm:ss")
LocalTime showRoundStartTime
) {
}
Loading

0 comments on commit 173e415

Please sign in to comment.