From 26e891ea1108c80caef5b02fd9298833d3405a75 Mon Sep 17 00:00:00 2001 From: byulcode Date: Sun, 7 Jan 2024 16:23:27 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=ED=9A=8C=EC=9B=90=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20=EC=97=B0=EB=8F=99=20(#142)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 멤버 예매 연동 * test: 테스트코드 멤버 연동 * test: 테스트코드 멤버 생성 수정 * refactor: booking의 member nullable=false 설정 추가 * fix: 불필요한 출력 제거 * fix: custom exception으로 처리 --- .../booking/controller/BookingController.java | 7 ++- .../booking/service/BookingService.java | 25 ++++++-- .../exception/BookingErrorCode.java | 1 + .../service/BookingServiceTest.java | 60 +++++++++++++------ .../coredomain/domain/booking/Booking.java | 2 +- 5 files changed, 71 insertions(+), 24 deletions(-) diff --git a/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java b/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java index 54ef0fab..3c783d64 100644 --- a/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java +++ b/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/controller/BookingController.java @@ -15,6 +15,7 @@ import com.pgms.apibooking.domain.booking.dto.response.BookingCreateResponse; import com.pgms.apibooking.domain.booking.service.BookingService; import com.pgms.coredomain.response.ApiResponse; +import com.pgms.coresecurity.security.resolver.CurrentAccount; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; @@ -29,9 +30,10 @@ public class BookingController { @PostMapping public ResponseEntity> createBooking( + @CurrentAccount Long memberId, @RequestBody @Valid BookingCreateRequest request, HttpServletRequest httpRequest) { - BookingCreateResponse createdBooking = bookingService.createBooking(request); + BookingCreateResponse createdBooking = bookingService.createBooking(request, memberId); ApiResponse response = ApiResponse.ok(createdBooking); URI location = UriComponentsBuilder .fromHttpUrl(httpRequest.getRequestURL().toString()) @@ -43,9 +45,10 @@ public ResponseEntity> createBooking( @PostMapping("/{id}/cancel") public ResponseEntity cancelBooking( + @CurrentAccount Long memberId, @PathVariable String id, @RequestBody @Valid BookingCancelRequest request) { - bookingService.cancelBooking(id, request); + bookingService.cancelBooking(id, request, memberId); return ResponseEntity.ok().build(); } diff --git a/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/service/BookingService.java b/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/service/BookingService.java index 2eadb612..d2eb4197 100644 --- a/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/service/BookingService.java +++ b/api/api-booking/src/main/java/com/pgms/apibooking/domain/booking/service/BookingService.java @@ -1,6 +1,8 @@ package com.pgms.apibooking.domain.booking.service; import java.util.List; +import java.util.NoSuchElementException; +import java.util.Objects; import java.util.Optional; import org.springframework.stereotype.Service; @@ -29,6 +31,8 @@ import com.pgms.coredomain.domain.booking.Ticket; import com.pgms.coredomain.domain.event.repository.EventSeatRepository; import com.pgms.coredomain.domain.event.repository.EventTimeRepository; +import com.pgms.coredomain.domain.member.Member; +import com.pgms.coredomain.domain.member.repository.MemberRepository; import lombok.RequiredArgsConstructor; @@ -41,17 +45,19 @@ public class BookingService { //TODO: 테스트 코드 작성 private final EventSeatRepository eventSeatRepository; private final BookingRepository bookingRepository; private final TicketRepository ticketRepository; + private final MemberRepository memberRepository; private final TossPaymentConfig tossPaymentConfig; private final PaymentService paymentService; - public BookingCreateResponse createBooking(BookingCreateRequest request) { + public BookingCreateResponse createBooking(BookingCreateRequest request, Long memberId) { + Member member = getMemberById(memberId); EventTime time = getBookableTimeWithEvent(request.timeId()); List seats = getBookableSeatsWithArea(request.timeId(), request.seatIds()); ReceiptType receiptType = ReceiptType.fromDescription(request.receiptType()); validateDeliveryAddress(receiptType, request.deliveryAddress()); - Booking booking = BookingCreateRequest.toEntity(request, time, seats, null); //TODO: 인증된 멤버 지정 + Booking booking = BookingCreateRequest.toEntity(request, time, seats, member); seats.forEach(seat -> booking.addTicket( Ticket.builder() @@ -73,10 +79,15 @@ public BookingCreateResponse createBooking(BookingCreateRequest request) { return BookingCreateResponse.of(booking, tossPaymentConfig.getSuccessUrl(), tossPaymentConfig.getFailUrl()); } - public void cancelBooking(String id, BookingCancelRequest request) { + public void cancelBooking(String id, BookingCancelRequest request, Long memberId) { + Member member = getMemberById(memberId); Booking booking = bookingRepository.findBookingInfoById(id) .orElseThrow(() -> new BookingException(BookingErrorCode.BOOKING_NOT_FOUND)); + if (!Objects.equals(member, booking.getMember())) { + throw new BookingException(BookingErrorCode.NOT_SAME_BOOKER); + } + if (!booking.isCancelable()) { throw new BookingException(BookingErrorCode.UNCANCELABLE_BOOKING); } @@ -95,7 +106,7 @@ public void cancelBooking(String id, BookingCancelRequest request) { ); booking.cancel( - BookingCancelRequest.toEntity(request, cancelAmount, "사용자", booking) //TODO: 취소 요청자 지정 + BookingCancelRequest.toEntity(request, cancelAmount, member.getEmail(), booking) ); } @@ -143,4 +154,10 @@ private void validateRefundReceiveAccount(PaymentMethod paymentMethod, throw new BookingException(BookingErrorCode.REFUND_ACCOUNT_REQUIRED); } } + + private Member getMemberById(Long memberId) { + System.out.println("member id get " + memberId); + return memberRepository.findById(memberId) + .orElseThrow(() -> new NoSuchElementException("Member not found")); + } } diff --git a/api/api-booking/src/main/java/com/pgms/apibooking/exception/BookingErrorCode.java b/api/api-booking/src/main/java/com/pgms/apibooking/exception/BookingErrorCode.java index 2dcdaede..69b4dda5 100644 --- a/api/api-booking/src/main/java/com/pgms/apibooking/exception/BookingErrorCode.java +++ b/api/api-booking/src/main/java/com/pgms/apibooking/exception/BookingErrorCode.java @@ -18,6 +18,7 @@ public enum BookingErrorCode { UNBOOKABLE_SEAT_INCLUSION(HttpStatus.BAD_REQUEST, "UNBOOKABLE_SEAT_INCLUSION", "예매가 불가능한 좌석이 포함되어 있습니다."), DELIVERY_ADDRESS_REQUIRED(HttpStatus.BAD_REQUEST, "DELIVERY_ADDRESS_REQUIRED", "배송지 정보를 입력해주세요."), + NOT_SAME_BOOKER(HttpStatus.BAD_REQUEST, "NOT_SAME_BOOKER", "해당 예약의 예약자가 아닙니다."), UNCANCELABLE_BOOKING(HttpStatus.BAD_REQUEST, "UNCANCELABLE_BOOKING", "취소할 수 없는 예매입니다."), REFUND_ACCOUNT_REQUIRED(HttpStatus.BAD_REQUEST, "REFUND_ACCOUNT_REQUIRED", "환불 받을 계좌 정보를 입력해주세요."), diff --git a/api/api-booking/src/test/java/com/pgms/apibooking/service/BookingServiceTest.java b/api/api-booking/src/test/java/com/pgms/apibooking/service/BookingServiceTest.java index 7ec20550..4dd47881 100644 --- a/api/api-booking/src/test/java/com/pgms/apibooking/service/BookingServiceTest.java +++ b/api/api-booking/src/test/java/com/pgms/apibooking/service/BookingServiceTest.java @@ -6,18 +6,19 @@ import java.util.List; import java.util.Optional; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.context.annotation.Import; import org.springframework.transaction.annotation.Transactional; -import com.pgms.apibooking.domain.booking.service.BookingService; import com.pgms.apibooking.config.TestConfig; import com.pgms.apibooking.domain.booking.dto.request.BookingCancelRequest; import com.pgms.apibooking.domain.booking.dto.request.BookingCreateRequest; -import com.pgms.apibooking.domain.payment.dto.request.RefundAccountRequest; import com.pgms.apibooking.domain.booking.dto.response.BookingCreateResponse; +import com.pgms.apibooking.domain.booking.service.BookingService; +import com.pgms.apibooking.domain.payment.dto.request.RefundAccountRequest; import com.pgms.apibooking.exception.BookingErrorCode; import com.pgms.apibooking.exception.BookingException; import com.pgms.apibooking.factory.BookingFactory; @@ -49,6 +50,11 @@ import com.pgms.coredomain.domain.event.repository.EventSeatAreaRepository; import com.pgms.coredomain.domain.event.repository.EventSeatRepository; import com.pgms.coredomain.domain.event.repository.EventTimeRepository; +import com.pgms.coredomain.domain.member.Member; +import com.pgms.coredomain.domain.member.Role; +import com.pgms.coredomain.domain.member.enums.Provider; +import com.pgms.coredomain.domain.member.repository.MemberRepository; +import com.pgms.coredomain.domain.member.repository.RoleRepository; @SpringBootTest @Import(TestConfig.class) @@ -77,6 +83,26 @@ class BookingServiceTest { @Autowired private BookingService bookingService; + @Autowired + private MemberRepository memberRepository; + + @Autowired + private RoleRepository roleRepository; + + private Member member; + + @BeforeEach + void setup() { + Role role = roleRepository.save(new Role("ROLE_USER")); + member = memberRepository.save(Member.builder() + .email("test@gmail.com") + .password("test1234!") + .name("홍길동") + .provider(Provider.KAKAO) + .role(role) + .phoneNumber("010-123-456") + .build()); + } @Test void 예매를_생성한다() { @@ -130,7 +156,7 @@ class BookingServiceTest { ); // when - BookingCreateResponse response = bookingService.createBooking(request); + BookingCreateResponse response = bookingService.createBooking(request, member.getId()); // then Booking booking = bookingRepository.findBookingInfoById(response.bookingId()).get(); @@ -201,7 +227,7 @@ class BookingServiceTest { ); // when & then - assertThatThrownBy(() -> bookingService.createBooking(request)) + assertThatThrownBy(() -> bookingService.createBooking(request, member.getId())) .isInstanceOf(BookingException.class) .hasMessage(BookingErrorCode.UNBOOKABLE_EVENT.getMessage()); } @@ -253,7 +279,7 @@ class BookingServiceTest { ); // when & then - assertThatThrownBy(() -> bookingService.createBooking(request)) + assertThatThrownBy(() -> bookingService.createBooking(request, member.getId())) .isInstanceOf(BookingException.class) .hasMessage(BookingErrorCode.NON_EXISTENT_SEAT_INCLUSION.getMessage()); } @@ -303,7 +329,7 @@ class BookingServiceTest { ); // when & then - assertThatThrownBy(() -> bookingService.createBooking(request)) + assertThatThrownBy(() -> bookingService.createBooking(request, member.getId())) .isInstanceOf(BookingException.class) .hasMessage(BookingErrorCode.UNBOOKABLE_SEAT_INCLUSION.getMessage()); } @@ -353,7 +379,7 @@ class BookingServiceTest { ); // when & then - assertThatThrownBy(() -> bookingService.createBooking(request)) + assertThatThrownBy(() -> bookingService.createBooking(request, member.getId())) .isInstanceOf(BookingException.class) .hasMessage(BookingErrorCode.DELIVERY_ADDRESS_REQUIRED.getMessage()); } @@ -388,7 +414,7 @@ class BookingServiceTest { eventSeatRepository.save(seat); Booking booking = BookingFactory.generate( - null, + member, time, seat.getEventSeatArea().getPrice(), BookingStatus.PAYMENT_COMPLETED @@ -407,7 +433,7 @@ class BookingServiceTest { ); // when - bookingService.cancelBooking(booking.getId(), request); + bookingService.cancelBooking(booking.getId(), request, member.getId()); // then Booking canceledBooking = bookingRepository.findBookingInfoById(booking.getId()).get(); @@ -455,7 +481,7 @@ class BookingServiceTest { eventSeatRepository.save(seat); Booking booking = BookingFactory.generate( - null, + member, time, seat.getEventSeatArea().getPrice(), BookingStatus.CANCELED @@ -474,7 +500,7 @@ class BookingServiceTest { ); // when & then - assertThatThrownBy(() -> bookingService.cancelBooking(booking.getId(), request)) + assertThatThrownBy(() -> bookingService.cancelBooking(booking.getId(), request, member.getId())) .isInstanceOf(BookingException.class) .hasMessage(BookingErrorCode.UNCANCELABLE_BOOKING.getMessage()); } @@ -509,7 +535,7 @@ class BookingServiceTest { eventSeatRepository.save(seat); Booking booking = BookingFactory.generate( - null, + member, time, seat.getEventSeatArea().getPrice(), BookingStatus.PAYMENT_COMPLETED @@ -529,7 +555,7 @@ class BookingServiceTest { ); // when & then - assertThatThrownBy(() -> bookingService.cancelBooking(booking.getId(), request)) + assertThatThrownBy(() -> bookingService.cancelBooking(booking.getId(), request, member.getId())) .isInstanceOf(BookingException.class) .hasMessage(BookingErrorCode.REFUND_ACCOUNT_REQUIRED.getMessage()); } @@ -564,7 +590,7 @@ class BookingServiceTest { eventSeatRepository.save(seat); Booking booking = BookingFactory.generate( - null, + member, time, seat.getEventSeatArea().getPrice(), BookingStatus.PAYMENT_COMPLETED @@ -583,7 +609,7 @@ class BookingServiceTest { ); // when - bookingService.cancelBooking(booking.getId(), request); + bookingService.cancelBooking(booking.getId(), request, member.getId()); // then Booking canceledBooking = bookingRepository.findBookingInfoById(booking.getId()).get(); @@ -620,7 +646,7 @@ class BookingServiceTest { eventSeatRepository.save(seat); Booking booking = BookingFactory.generate( - null, + member, time, seat.getEventSeatArea().getPrice(), BookingStatus.WAITING_FOR_PAYMENT @@ -646,7 +672,7 @@ class BookingServiceTest { ); // when - bookingService.cancelBooking(booking.getId(), request); + bookingService.cancelBooking(booking.getId(), request, member.getId()); // then Booking canceledBooking = bookingRepository.findBookingInfoById(booking.getId()).get(); diff --git a/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/Booking.java b/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/Booking.java index 2cbd215c..ff9eba3e 100644 --- a/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/Booking.java +++ b/core/core-domain/src/main/java/com/pgms/coredomain/domain/booking/Booking.java @@ -73,7 +73,7 @@ public class Booking extends BaseEntity { private Integer amount; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) //TODO: nullalbe = false 추가 + @JoinColumn(name = "member_id", nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT)) private Member member; @ManyToOne(fetch = FetchType.LAZY)