diff --git a/src/main/java/cc/backend/amateurShow/entity/AmateurTicket.java b/src/main/java/cc/backend/amateurShow/entity/AmateurTicket.java index 37ebc60..cffe0a4 100644 --- a/src/main/java/cc/backend/amateurShow/entity/AmateurTicket.java +++ b/src/main/java/cc/backend/amateurShow/entity/AmateurTicket.java @@ -2,7 +2,7 @@ import cc.backend.amateurShow.dto.AmateurUpdateRequestDTO; import cc.backend.domain.common.BaseEntity; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Builder; @@ -32,7 +32,7 @@ public class AmateurTicket extends BaseEntity { @OneToMany(mappedBy = "amateurTicket", cascade = CascadeType.ALL) @Builder.Default - private List memberTicketList = new ArrayList<>(); + private List tempTicketList = new ArrayList<>(); public void update(AmateurUpdateRequestDTO.UpdateTickets dto) { if (dto.getDiscountName() != null) this.discountName = dto.getDiscountName(); diff --git a/src/main/java/cc/backend/kakaoPay/controller/KakaoPayController.java b/src/main/java/cc/backend/kakaoPay/controller/KakaoPayController.java index ca98670..0f5e1fc 100644 --- a/src/main/java/cc/backend/kakaoPay/controller/KakaoPayController.java +++ b/src/main/java/cc/backend/kakaoPay/controller/KakaoPayController.java @@ -1,11 +1,9 @@ package cc.backend.kakaoPay.controller; import cc.backend.apiPayLoad.ApiResponse; -import cc.backend.kakaoPay.dto.responseDTO.KakaoPayApproveResponseDTO; import cc.backend.kakaoPay.dto.responseDTO.KakaoPayReadyResponseDTO; import cc.backend.kakaoPay.dto.responseDTO.KakaoPayResultResponseDTO; import cc.backend.kakaoPay.service.KakaoPayBusinessService; -import cc.backend.kakaoPay.service.KakaoPayService; import cc.backend.member.entity.Member; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -14,7 +12,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.*; -import reactor.core.publisher.Mono; import java.io.IOException; diff --git a/src/main/java/cc/backend/kakaoPay/service/KakaoPayBusinessService.java b/src/main/java/cc/backend/kakaoPay/service/KakaoPayBusinessService.java index eaf1001..323c92f 100644 --- a/src/main/java/cc/backend/kakaoPay/service/KakaoPayBusinessService.java +++ b/src/main/java/cc/backend/kakaoPay/service/KakaoPayBusinessService.java @@ -7,11 +7,11 @@ import cc.backend.kakaoPay.dto.responseDTO.KakaoPayReadyResponseDTO; import cc.backend.kakaoPay.dto.responseDTO.KakaoPayResultResponseDTO; import cc.backend.ticket.dto.response.RealTicketResponseDTO; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import cc.backend.ticket.entity.RealTicket; import cc.backend.ticket.entity.enums.CancelFeeType; import cc.backend.ticket.entity.enums.ReservationStatus; -import cc.backend.ticket.repository.MemberTicketRepository; +import cc.backend.ticket.repository.TempTicketRepository; import cc.backend.ticket.repository.RealTicketRepository; import cc.backend.ticket.service.RealTicketService; import cc.backend.ticket.util.CancelPolicy; @@ -27,29 +27,29 @@ @Slf4j public class KakaoPayBusinessService { - private final MemberTicketRepository memberTicketRepository; + private final TempTicketRepository tempTicketRepository; private final AmateurRoundsRepository amateurRoundsRepository; private final RealTicketService realTicketService; private final RealTicketRepository realTicketRepository; private final KakaoPayService kakaoPayService; // 결제 준비 비즈니스 로직 - public KakaoPayReadyResponseDTO preparePayment(Long memberTicketId, String partnerUserId) { + public KakaoPayReadyResponseDTO preparePayment(Long tempTicketId, String partnerUserId) { // DB에서 결제할 티켓 정보를 미리 조회 - MemberTicket memberTicket = memberTicketRepository.findWithTicketAndShowById(memberTicketId) + TempTicket tempTicket = tempTicketRepository.findWithTicketAndShowById(tempTicketId) .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_TICKET_NOT_FOUND)); // 현재 로그인한 사용자(partnerUserId)와 티켓의 소유주가 같은지 확인 - if (!memberTicket.getMember().getId().toString().equals(partnerUserId)) { + if (!tempTicket.getMember().getId().toString().equals(partnerUserId)) { throw new GeneralException(ErrorStatus.NOT_MEMBER_TICKET_OWNER); } // 재고 선점 - preemptStock(memberTicket); + preemptStock(tempTicket); // 카카오페이 결제 준비 API 호출 - KakaoPayReadyResponseDTO responseDTO = kakaoPayService.ready(memberTicketId, partnerUserId); + KakaoPayReadyResponseDTO responseDTO = kakaoPayService.ready(tempTicketId, partnerUserId); if (responseDTO == null) { // 재고 복구 @@ -57,16 +57,16 @@ public KakaoPayReadyResponseDTO preparePayment(Long memberTicketId, String partn } // 응답받은 tid를 DB에 저장 - memberTicket.updateTid(responseDTO.getTid()); - memberTicketRepository.save(memberTicket); + tempTicket.updateTid(responseDTO.getTid()); + tempTicketRepository.save(tempTicket); return responseDTO; } - private void preemptStock(MemberTicket memberTicket) { + private void preemptStock(TempTicket tempTicket) { // 재고 감소 - int updated = amateurRoundsRepository.decreaseStock(memberTicket.getAmateurRound().getId(), memberTicket.getQuantity()); + int updated = amateurRoundsRepository.decreaseStock(tempTicket.getAmateurRound().getId(), tempTicket.getQuantity()); if (updated == 0) { // 재고 부족하면 예외 throw new GeneralException(ErrorStatus.MEMBER_TICKET_STOCK); @@ -78,21 +78,21 @@ public KakaoPayResultResponseDTO completePayment(String partnerOrderId, String p Long ticketId = Long.valueOf(partnerOrderId); - MemberTicket memberTicket = memberTicketRepository.findWithTicketAndShowById(ticketId) + TempTicket tempTicket = tempTicketRepository.findWithTicketAndShowById(ticketId) .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_TICKET_NOT_FOUND)); - if (memberTicket.getReservationStatus().equals(ReservationStatus.EXPIRED)) { + if (tempTicket.getReservationStatus().equals(ReservationStatus.EXPIRED)) { throw new GeneralException(ErrorStatus.MEMBER_TICKET_EXPIRED); } // 저장된 tid 가져오기 - String tid = memberTicket.getKakaoTid(); + String tid = tempTicket.getKakaoTid(); if (tid == null) { throw new GeneralException(ErrorStatus.MEMBER_TICKET_TID_NOT_FOUND); } // 멤버를 DB에서 추적하기 - String partnerUserId = memberTicket.getMember().getId().toString(); + String partnerUserId = tempTicket.getMember().getId().toString(); KakaoPayApproveResponseDTO responseDTO; try { @@ -107,41 +107,41 @@ public KakaoPayResultResponseDTO completePayment(String partnerOrderId, String p // 결제 승인 실패 시 재고 복구 amateurRoundsRepository.increaseStock( - memberTicket.getAmateurRound().getId(), - memberTicket.getQuantity() + tempTicket.getAmateurRound().getId(), + tempTicket.getQuantity() ); - memberTicket.updateReservationStatus(ReservationStatus.EXPIRED); - memberTicketRepository.save(memberTicket); + tempTicket.updateReservationStatus(ReservationStatus.EXPIRED); + tempTicketRepository.save(tempTicket); throw new GeneralException(ErrorStatus._INTERNAL_SERVER_ERROR); } // 예약 확정 및 최종 티켓 생성 - confirmReservation(memberTicket); - realTicketService.createRealTicketFromMemberTicket(ticketId); + confirmReservation(tempTicket); + realTicketService.createRealTicketFromTempTicket(ticketId); - Long amateurShowId = memberTicket.getAmateurTicket().getAmateurShow().getId(); + Long amateurShowId = tempTicket.getAmateurTicket().getAmateurShow().getId(); return new KakaoPayResultResponseDTO( amateurShowId, responseDTO ); } - private void confirmReservation(MemberTicket memberTicket) { + private void confirmReservation(TempTicket tempTicket) { // 중복 예약 방지 - if (memberTicket.getReservationStatus().equals(ReservationStatus.RESERVED)) return; + if (tempTicket.getReservationStatus().equals(ReservationStatus.RESERVED)) return; // 상태가 PENDING이 아니면 예외 (잘못된 요청) - if (!memberTicket.getReservationStatus().equals(ReservationStatus.PENDING)) { + if (!tempTicket.getReservationStatus().equals(ReservationStatus.PENDING)) { throw new GeneralException(ErrorStatus.MEMBER_TICKET_STATUS_INVALID); } // 예약 확정 - memberTicket.updateReservationStatus(ReservationStatus.RESERVED); + tempTicket.updateReservationStatus(ReservationStatus.RESERVED); // 누적 티켓 판매 수 증가 - memberTicket.getAmateurTicket().getAmateurShow().increaseSoldTicket(memberTicket.getQuantity()); + tempTicket.getAmateurTicket().getAmateurShow().increaseSoldTicket(tempTicket.getQuantity()); } // cancel @@ -191,21 +191,21 @@ public void stopPayment(String partnerOrderId) { Long ticketId = Long.valueOf(partnerOrderId); - MemberTicket memberTicket = memberTicketRepository.findById(ticketId) + TempTicket tempTicket = tempTicketRepository.findById(ticketId) .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_TICKET_NOT_FOUND)); // 이미 처리된 건이면 패스 - if (memberTicket.getReservationStatus() != ReservationStatus.PENDING) { + if (tempTicket.getReservationStatus() != ReservationStatus.PENDING) { return; } // 1. 재고 복구 (증가) amateurRoundsRepository.increaseStock( - memberTicket.getAmateurRound().getId(), - memberTicket.getQuantity() + tempTicket.getAmateurRound().getId(), + tempTicket.getQuantity() ); // 2. 티켓 상태 변경 - memberTicket.updateReservationStatus(ReservationStatus.EXPIRED); + tempTicket.updateReservationStatus(ReservationStatus.EXPIRED); } } diff --git a/src/main/java/cc/backend/kakaoPay/service/KakaoPayService.java b/src/main/java/cc/backend/kakaoPay/service/KakaoPayService.java index 3dad274..3d97c92 100644 --- a/src/main/java/cc/backend/kakaoPay/service/KakaoPayService.java +++ b/src/main/java/cc/backend/kakaoPay/service/KakaoPayService.java @@ -8,9 +8,9 @@ import cc.backend.kakaoPay.dto.responseDTO.KakaoPayApproveResponseDTO; import cc.backend.kakaoPay.dto.responseDTO.KakaoPayCancelResponseDTO; import cc.backend.kakaoPay.dto.responseDTO.KakaoPayReadyResponseDTO; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import cc.backend.ticket.entity.enums.ReservationStatus; -import cc.backend.ticket.repository.MemberTicketRepository; +import cc.backend.ticket.repository.TempTicketRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; @@ -27,7 +27,7 @@ public class KakaoPayService { private final WebClient kakaoWebClient; - private final MemberTicketRepository memberTicketRepository; + private final TempTicketRepository tempTicketRepository; @Value("${kakaopay.cid}") private String cid; @@ -41,31 +41,31 @@ public class KakaoPayService { @Value("${kakaopay.url.fail}") private String failUrl; - public KakaoPayReadyResponseDTO ready(Long memberTicketId, String partnerUserId) { + public KakaoPayReadyResponseDTO ready(Long tempTicketId, String partnerUserId) { - MemberTicket memberTicket = memberTicketRepository.findWithTicketAndShowById(memberTicketId) + TempTicket tempTicket = tempTicketRepository.findWithTicketAndShowById(tempTicketId) .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_TICKET_NOT_FOUND)); // 재고 상태 검증 - if (memberTicket.getReservationStatus() != ReservationStatus.PENDING) { + if (tempTicket.getReservationStatus() != ReservationStatus.PENDING) { throw new GeneralException(ErrorStatus.MEMBER_TICKET_STATUS_INVALID); } // itemName (할인명 - 공연이름) - String itemName = memberTicket.getAmateurTicket().getDiscountName() + " - " + - memberTicket.getAmateurTicket().getAmateurShow().getName(); + String itemName = tempTicket.getAmateurTicket().getDiscountName() + " - " + + tempTicket.getAmateurTicket().getAmateurShow().getName(); KakaoPayReadyRequestDTO requestDTO = KakaoPayReadyRequestDTO.builder() .cid(cid) - .partnerOrderId(String.valueOf(memberTicketId)) + .partnerOrderId(String.valueOf(tempTicketId)) .partnerUserId(partnerUserId) .itemName(itemName) - .quantity(memberTicket.getQuantity()) - .totalAmount(memberTicket.getTotalPrice()) + .quantity(tempTicket.getQuantity()) + .totalAmount(tempTicket.getTotalPrice()) .taxFreeAmount(0) - .approvalUrl(approvalUrl + "?partner_order_id=" + memberTicketId) - .cancelUrl(cancelUrl + "?partner_order_id=" + memberTicketId) - .failUrl(failUrl + "?partner_order_id=" + memberTicketId) + .approvalUrl(approvalUrl + "?partner_order_id=" + tempTicketId) + .cancelUrl(cancelUrl + "?partner_order_id=" + tempTicketId) + .failUrl(failUrl + "?partner_order_id=" + tempTicketId) .build(); // post 요청 (ready) @@ -86,11 +86,11 @@ public KakaoPayReadyResponseDTO ready(Long memberTicketId, String partnerUserId) public KakaoPayApproveResponseDTO approve(String tid, String partnerOrderId, String partnerUserId, String pgToken) { // partnerOrderId로 MemberTicket 조회 - MemberTicket memberTicket = memberTicketRepository.findById(Long.valueOf(partnerOrderId)) + TempTicket tempTicket = tempTicketRepository.findById(Long.valueOf(partnerOrderId)) .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_TICKET_NOT_FOUND)); // 티켓 상태가 EXPIRED 이면 승인 불가 - if (memberTicket.getReservationStatus().equals(ReservationStatus.EXPIRED)) { + if (tempTicket.getReservationStatus().equals(ReservationStatus.EXPIRED)) { throw new GeneralException(ErrorStatus.MEMBER_TICKET_EXPIRED); } diff --git a/src/main/java/cc/backend/member/entity/Member.java b/src/main/java/cc/backend/member/entity/Member.java index cd98037..9d7fe54 100644 --- a/src/main/java/cc/backend/member/entity/Member.java +++ b/src/main/java/cc/backend/member/entity/Member.java @@ -8,8 +8,7 @@ import cc.backend.member.enumerate.Role; import cc.backend.memberLike.entity.MemberLike; import cc.backend.notice.entity.MemberNotice; -import cc.backend.notice.entity.Notice; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import jakarta.persistence.*; import lombok.*; @@ -66,7 +65,7 @@ public class Member extends BaseEntity { private List memberNotices = new ArrayList<>(); @OneToMany (mappedBy = "member", cascade = CascadeType.ALL) - private List memberTickets = new ArrayList<>(); + private List tempTickets = new ArrayList<>(); @Builder public Member(String username, String name, Role role, String address, String email, String phone, diff --git a/src/main/java/cc/backend/notice/service/NoticeScheduler.java b/src/main/java/cc/backend/notice/service/NoticeScheduler.java index f2855d6..a66e2ff 100644 --- a/src/main/java/cc/backend/notice/service/NoticeScheduler.java +++ b/src/main/java/cc/backend/notice/service/NoticeScheduler.java @@ -1,16 +1,13 @@ package cc.backend.notice.service; import cc.backend.amateurShow.entity.AmateurShow; -import cc.backend.amateurShow.repository.AmateurShowRepository; -import cc.backend.member.entity.Member; -import cc.backend.notice.dto.NoticeResponseDTO; import cc.backend.notice.entity.MemberNotice; import cc.backend.notice.entity.Notice; import cc.backend.notice.entity.enums.NoticeType; import cc.backend.notice.repository.MemberNoticeRepository; import cc.backend.notice.repository.NoticeRepository; -import cc.backend.ticket.entity.MemberTicket; -import cc.backend.ticket.repository.MemberTicketRepository; +import cc.backend.ticket.entity.TempTicket; +import cc.backend.ticket.repository.TempTicketRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; @@ -20,13 +17,12 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import java.util.stream.Stream; @Slf4j @Component @RequiredArgsConstructor public class NoticeScheduler { - private final MemberTicketRepository memberTicketRepository; + private final TempTicketRepository tempTicketRepository; private final NoticeRepository noticeRepository; private final MemberNoticeRepository memberNoticeRepository; @@ -38,16 +34,16 @@ public void notifyTodayPerformances() { LocalDate today = LocalDate.now(); // 오늘 공연 티켓 전체 조회 - List tickets = memberTicketRepository.findAllByPerformanceDate(today); + List tickets = tempTicketRepository.findAllByPerformanceDate(today); // 공연별로 티켓 그룹핑 - Map> ticketsByShowId = tickets.stream() + Map> ticketsByShowId = tickets.stream() .collect(Collectors.groupingBy(ticket -> ticket.getAmateurTicket().getAmateurShow().getId())); // 공연별로 Notice 및 MemberNotice 생성 - for (Map.Entry> entry : ticketsByShowId.entrySet()) { + for (Map.Entry> entry : ticketsByShowId.entrySet()) { Long amateurShowId = entry.getKey(); - List showTickets = entry.getValue(); + List showTickets = entry.getValue(); AmateurShow show = showTickets.get(0).getAmateurTicket().getAmateurShow(); @@ -62,7 +58,7 @@ public void notifyTodayPerformances() { // 이 공연을 예매한 모든 멤버에 대해 MemberNotice 생성 List memberNotices = showTickets.stream() - .map(MemberTicket::getMember) // 멤버 추출 + .map(TempTicket::getMember) // 멤버 추출 .distinct() // 멤버 중복 제거 .map(member -> MemberNotice.builder() .notice(notice) diff --git a/src/main/java/cc/backend/ticket/controller/MyTicketController.java b/src/main/java/cc/backend/ticket/controller/MyTicketController.java index 95ed8ee..efb2795 100644 --- a/src/main/java/cc/backend/ticket/controller/MyTicketController.java +++ b/src/main/java/cc/backend/ticket/controller/MyTicketController.java @@ -4,11 +4,8 @@ import cc.backend.apiPayLoad.SliceResponse; import cc.backend.kakaoPay.service.KakaoPayBusinessService; import cc.backend.member.entity.Member; -import cc.backend.ticket.dto.response.MemberTicketListResponseDTO; -import cc.backend.ticket.dto.response.MemberTicketResponseDTO; import cc.backend.ticket.dto.response.RealTicketResponseDTO; -import cc.backend.ticket.entity.enums.ReservationStatus; -import cc.backend.ticket.service.MemberTicketService; +import cc.backend.ticket.service.TempTicketService; import cc.backend.ticket.service.RealTicketService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -22,14 +19,12 @@ import org.springframework.web.ErrorResponse; import org.springframework.web.bind.annotation.*; -import java.util.List; - @Tag(name = "내 공연 티켓") @RestController @RequiredArgsConstructor @RequestMapping("/myTickets") public class MyTicketController { - private final MemberTicketService memberTicketService; + private final TempTicketService tempTicketService; private final RealTicketService realTicketService; private final KakaoPayBusinessService kakaoPayBusinessService; diff --git a/src/main/java/cc/backend/ticket/controller/MemberTicketController.java b/src/main/java/cc/backend/ticket/controller/TempTicketController.java similarity index 88% rename from src/main/java/cc/backend/ticket/controller/MemberTicketController.java rename to src/main/java/cc/backend/ticket/controller/TempTicketController.java index 1fc0acc..71d7a32 100644 --- a/src/main/java/cc/backend/ticket/controller/MemberTicketController.java +++ b/src/main/java/cc/backend/ticket/controller/TempTicketController.java @@ -1,17 +1,15 @@ package cc.backend.ticket.controller; import cc.backend.apiPayLoad.ApiResponse; -import cc.backend.member.MemberService; import cc.backend.member.entity.Member; import cc.backend.ticket.dto.response.*; -import cc.backend.ticket.dto.request.MemberTicketCreateRequestDTO; -import cc.backend.ticket.service.MemberTicketService; +import cc.backend.ticket.dto.request.TempTicketCreateRequestDTO; +import cc.backend.ticket.service.TempTicketService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.security.core.annotation.AuthenticationPrincipal; @@ -24,9 +22,9 @@ @RestController @RequiredArgsConstructor @RequestMapping("/tickets") -public class MemberTicketController { +public class TempTicketController { - private final MemberTicketService memberTicketService; + private final TempTicketService tempTicketService; @GetMapping("/{amateurShowId}/showSimple") @Operation( @@ -39,7 +37,7 @@ public class MemberTicketController { } ) public ApiResponse getSimpleAmateurShow(@Parameter(name = "amateurShowId", description = "공연 ID", required = true) @PathVariable Long amateurShowId) { - return ApiResponse.onSuccess(memberTicketService.getSimpleAmateurShow(amateurShowId)); + return ApiResponse.onSuccess(tempTicketService.getSimpleAmateurShow(amateurShowId)); } @GetMapping("/{amateurShowId}/selectRound") @@ -70,7 +68,7 @@ public ApiResponse getSimpleAmateurShow(@Parameter(name = }) public ApiResponse> getAmateurRounds(@PathVariable Long amateurShowId, @AuthenticationPrincipal(expression = "member") Member member){ - return ApiResponse.onSuccess(memberTicketService.getRoundsList(member.getId(), amateurShowId)); + return ApiResponse.onSuccess(tempTicketService.getRoundsList(member.getId(), amateurShowId)); } @GetMapping("/{amateurShowId}/selectTicket") @@ -98,7 +96,7 @@ public ApiResponse> getAmateurRounds(@PathVariable Long amat public ApiResponse> getAmateurTicketList(@PathVariable Long amateurShowId, @AuthenticationPrincipal(expression = "member") Member member){ - return ApiResponse.onSuccess(memberTicketService.getAmateurTicketList(member.getId(), amateurShowId)); + return ApiResponse.onSuccess(tempTicketService.getAmateurTicketList(member.getId(), amateurShowId)); } @@ -115,7 +113,7 @@ public ApiResponse> getAmateurTicketList(@PathVariabl responseCode = "200", description = "티켓 예매 성공", content = @Content( - schema = @Schema(implementation = MemberTicketCreateResponseDTO.class) + schema = @Schema(implementation = TempTicketCreateResponseDTO.class) ) ), @io.swagger.v3.oas.annotations.responses.ApiResponse( @@ -141,14 +139,14 @@ public ApiResponse> getAmateurTicketList(@PathVariabl ) } ) - public ApiResponse createMemberTicket( + public ApiResponse createTempTicket( @PathVariable Long amateurShowId, @RequestParam Long amateurRoundId, @RequestParam Long amateurTicketId, @AuthenticationPrincipal(expression = "member") Member member, - @RequestBody MemberTicketCreateRequestDTO requestDTO) { + @RequestBody TempTicketCreateRequestDTO requestDTO) { return ApiResponse.onSuccess( - memberTicketService.createTicket(amateurShowId, amateurRoundId, amateurTicketId, member, requestDTO) + tempTicketService.createTicket(amateurShowId, amateurRoundId, amateurTicketId, member, requestDTO) ); } diff --git a/src/main/java/cc/backend/ticket/dto/request/MemberTicketCreateRequestDTO.java b/src/main/java/cc/backend/ticket/dto/request/TempTicketCreateRequestDTO.java similarity index 77% rename from src/main/java/cc/backend/ticket/dto/request/MemberTicketCreateRequestDTO.java rename to src/main/java/cc/backend/ticket/dto/request/TempTicketCreateRequestDTO.java index 76e20d4..bfcf691 100644 --- a/src/main/java/cc/backend/ticket/dto/request/MemberTicketCreateRequestDTO.java +++ b/src/main/java/cc/backend/ticket/dto/request/TempTicketCreateRequestDTO.java @@ -5,12 +5,10 @@ import lombok.Getter; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; - @Builder @AllArgsConstructor @NoArgsConstructor @Getter -public class MemberTicketCreateRequestDTO { +public class TempTicketCreateRequestDTO { private int quantity; // 수량 } diff --git a/src/main/java/cc/backend/ticket/dto/response/MemberTicketCreateResponseDTO.java b/src/main/java/cc/backend/ticket/dto/response/TempTicketCreateResponseDTO.java similarity index 86% rename from src/main/java/cc/backend/ticket/dto/response/MemberTicketCreateResponseDTO.java rename to src/main/java/cc/backend/ticket/dto/response/TempTicketCreateResponseDTO.java index e560224..9cf55ba 100644 --- a/src/main/java/cc/backend/ticket/dto/response/MemberTicketCreateResponseDTO.java +++ b/src/main/java/cc/backend/ticket/dto/response/TempTicketCreateResponseDTO.java @@ -12,11 +12,10 @@ @AllArgsConstructor @NoArgsConstructor @Getter -public class MemberTicketCreateResponseDTO { - private Long memberTicketId; +public class TempTicketCreateResponseDTO { + private Long tempTicketId; private String bookingNumber; private String showTitle; // 공연 이름 - //private String place; // 공연 장소 private String detailAddress; // 상세 주소 private int quantity; // 예매 수량 private LocalDateTime reserveDate; // 예매일 diff --git a/src/main/java/cc/backend/ticket/dto/response/MemberTicketListResponseDTO.java b/src/main/java/cc/backend/ticket/dto/response/TempTicketListResponseDTO.java similarity index 80% rename from src/main/java/cc/backend/ticket/dto/response/MemberTicketListResponseDTO.java rename to src/main/java/cc/backend/ticket/dto/response/TempTicketListResponseDTO.java index 6a6b290..406a703 100644 --- a/src/main/java/cc/backend/ticket/dto/response/MemberTicketListResponseDTO.java +++ b/src/main/java/cc/backend/ticket/dto/response/TempTicketListResponseDTO.java @@ -1,6 +1,6 @@ package cc.backend.ticket.dto.response; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import cc.backend.ticket.entity.enums.ReservationStatus; import lombok.Builder; import lombok.Getter; @@ -9,9 +9,9 @@ @Getter @Builder -public class MemberTicketListResponseDTO { +public class TempTicketListResponseDTO { - private Long memberTicketId; + private Long tempTicketId; private String bookingNumber; private String showTitle; private int quantity; @@ -22,9 +22,9 @@ public class MemberTicketListResponseDTO { private LocalDateTime cancelAvailableUntil; private ReservationStatus reservationStatus; - public static MemberTicketListResponseDTO from(MemberTicket ticket) { - return MemberTicketListResponseDTO.builder() - .memberTicketId(ticket.getId()) + public static TempTicketListResponseDTO from(TempTicket ticket) { + return TempTicketListResponseDTO.builder() + .tempTicketId(ticket.getId()) .bookingNumber(ticket.getBookingNumber()) .showTitle(ticket.getAmateurTicket().getAmateurShow().getName()) //.place(ticket.getAmateurTicket().getAmateurShow().getPlace()) diff --git a/src/main/java/cc/backend/ticket/dto/response/MemberTicketResponseDTO.java b/src/main/java/cc/backend/ticket/dto/response/TempTicketResponseDTO.java similarity index 86% rename from src/main/java/cc/backend/ticket/dto/response/MemberTicketResponseDTO.java rename to src/main/java/cc/backend/ticket/dto/response/TempTicketResponseDTO.java index f1ff7bb..6d19f58 100644 --- a/src/main/java/cc/backend/ticket/dto/response/MemberTicketResponseDTO.java +++ b/src/main/java/cc/backend/ticket/dto/response/TempTicketResponseDTO.java @@ -1,7 +1,7 @@ package cc.backend.ticket.dto.response; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import cc.backend.ticket.entity.enums.ReservationStatus; import lombok.Builder; import lombok.Getter; @@ -10,7 +10,7 @@ @Getter @Builder -public class MemberTicketResponseDTO { +public class TempTicketResponseDTO { private String posterImageUrl; private Long memberTicketId; @@ -24,8 +24,8 @@ public class MemberTicketResponseDTO { private LocalDateTime cancelAvailableUntil; private ReservationStatus reservationStatus; - public static MemberTicketResponseDTO from(MemberTicket ticket) { - return MemberTicketResponseDTO.builder() + public static TempTicketResponseDTO from(TempTicket ticket) { + return TempTicketResponseDTO.builder() .posterImageUrl(ticket.getAmateurTicket().getAmateurShow().getPosterImageUrl()) .memberTicketId(ticket.getId()) .bookingNumber(ticket.getBookingNumber()) diff --git a/src/main/java/cc/backend/ticket/entity/MemberTicket.java b/src/main/java/cc/backend/ticket/entity/TempTicket.java similarity index 97% rename from src/main/java/cc/backend/ticket/entity/MemberTicket.java rename to src/main/java/cc/backend/ticket/entity/TempTicket.java index 041511e..db0e638 100644 --- a/src/main/java/cc/backend/ticket/entity/MemberTicket.java +++ b/src/main/java/cc/backend/ticket/entity/TempTicket.java @@ -18,7 +18,7 @@ @Builder @NoArgsConstructor @AllArgsConstructor -public class MemberTicket extends BaseEntity { +public class TempTicket extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/src/main/java/cc/backend/ticket/repository/MemberTicketRepository.java b/src/main/java/cc/backend/ticket/repository/MemberTicketRepository.java deleted file mode 100644 index ae35422..0000000 --- a/src/main/java/cc/backend/ticket/repository/MemberTicketRepository.java +++ /dev/null @@ -1,41 +0,0 @@ -package cc.backend.ticket.repository; - -import cc.backend.ticket.entity.MemberTicket; -import cc.backend.ticket.entity.enums.ReservationStatus; -import org.springframework.data.jpa.repository.EntityGraph; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.List; -import java.util.Optional; - -@Repository -public interface MemberTicketRepository extends JpaRepository { - - List findAllByMemberId(Long memberId); - List findAllByMemberIdAndReservationStatus(Long memberId, ReservationStatus reservationStatus); - Optional findByMemberIdAndId(Long memberId, Long ticketId); - - List findAllByAmateurRound_PerformanceDateTimeBetween(LocalDateTime start, LocalDateTime end); - default List findAllByPerformanceDate(LocalDate date) { - return findAllByAmateurRound_PerformanceDateTimeBetween( - date.atStartOfDay(), - date.plusDays(1).atStartOfDay().minusNanos(1) - ); - } - - // 결제시 사용 - @EntityGraph(attributePaths = { - "amateurTicket", - "amateurTicket.amateurShow", - "amateurRound" - }) - Optional findWithTicketAndShowById(Long id); - - // 스케줄러에서 사용 (15분 이상 PENDING 상태인 티켓을 EXPIRED로 변경) - List findByReservationStatusAndCreatedAtBefore(ReservationStatus status, LocalDateTime expirationTime); -} diff --git a/src/main/java/cc/backend/ticket/repository/TempTicketRepository.java b/src/main/java/cc/backend/ticket/repository/TempTicketRepository.java new file mode 100644 index 0000000..b4a75ba --- /dev/null +++ b/src/main/java/cc/backend/ticket/repository/TempTicketRepository.java @@ -0,0 +1,39 @@ +package cc.backend.ticket.repository; + +import cc.backend.ticket.entity.TempTicket; +import cc.backend.ticket.entity.enums.ReservationStatus; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +@Repository +public interface TempTicketRepository extends JpaRepository { + + List findAllByMemberId(Long memberId); + List findAllByMemberIdAndReservationStatus(Long memberId, ReservationStatus reservationStatus); + Optional findByMemberIdAndId(Long memberId, Long ticketId); + + List findAllByAmateurRound_PerformanceDateTimeBetween(LocalDateTime start, LocalDateTime end); + default List findAllByPerformanceDate(LocalDate date) { + return findAllByAmateurRound_PerformanceDateTimeBetween( + date.atStartOfDay(), + date.plusDays(1).atStartOfDay().minusNanos(1) + ); + } + + // 결제시 사용 + @EntityGraph(attributePaths = { + "amateurTicket", + "amateurTicket.amateurShow", + "amateurRound" + }) + Optional findWithTicketAndShowById(Long id); + + // 스케줄러에서 사용 (15분 이상 PENDING 상태인 티켓을 EXPIRED로 변경) + List findByReservationStatusAndCreatedAtBefore(ReservationStatus status, LocalDateTime expirationTime); +} diff --git a/src/main/java/cc/backend/ticket/service/RealTicketService.java b/src/main/java/cc/backend/ticket/service/RealTicketService.java index f7f0f38..8da7e0c 100644 --- a/src/main/java/cc/backend/ticket/service/RealTicketService.java +++ b/src/main/java/cc/backend/ticket/service/RealTicketService.java @@ -4,13 +4,12 @@ import cc.backend.amateurShow.repository.AmateurRoundsRepository; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; -import cc.backend.kakaoPay.service.KakaoPayService; import cc.backend.ticket.dto.response.RealTicketResponseDTO; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import cc.backend.ticket.entity.RealTicket; import cc.backend.ticket.entity.enums.CancelFeeType; import cc.backend.ticket.entity.enums.ReservationStatus; -import cc.backend.ticket.repository.MemberTicketRepository; +import cc.backend.ticket.repository.TempTicketRepository; import cc.backend.ticket.repository.RealTicketRepository; import cc.backend.ticket.util.CancelPolicy; import lombok.RequiredArgsConstructor; @@ -22,20 +21,19 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; -import java.util.List; @Service @RequiredArgsConstructor @Transactional(readOnly = true) public class RealTicketService { private final RealTicketRepository realTicketRepository; - private final MemberTicketRepository memberTicketRepository; + private final TempTicketRepository tempTicketRepository; private final AmateurRoundsRepository amateurRoundsRepository; @Transactional - public void createRealTicketFromMemberTicket(Long memberTicketId) { - MemberTicket ticket = memberTicketRepository.findById(memberTicketId) + public void createRealTicketFromTempTicket(Long tempTicketId) { + TempTicket ticket = tempTicketRepository.findById(tempTicketId) .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_TICKET_NOT_FOUND)); AmateurRounds round = ticket.getAmateurRound(); diff --git a/src/main/java/cc/backend/ticket/service/MemberTicketService.java b/src/main/java/cc/backend/ticket/service/TempTicketService.java similarity index 57% rename from src/main/java/cc/backend/ticket/service/MemberTicketService.java rename to src/main/java/cc/backend/ticket/service/TempTicketService.java index a5b2c5b..6332071 100644 --- a/src/main/java/cc/backend/ticket/service/MemberTicketService.java +++ b/src/main/java/cc/backend/ticket/service/TempTicketService.java @@ -1,17 +1,16 @@ package cc.backend.ticket.service; -import cc.backend.amateurShow.entity.AmateurTicket; import cc.backend.member.entity.Member; import cc.backend.ticket.dto.response.*; -import cc.backend.ticket.dto.request.MemberTicketCreateRequestDTO; +import cc.backend.ticket.dto.request.TempTicketCreateRequestDTO; import org.springframework.stereotype.Service; import java.util.List; @Service -public interface MemberTicketService { +public interface TempTicketService { - MemberTicketCreateResponseDTO createTicket(Long amateurShowId, Long amateurRoundId, Long amateurTicketId, Member member, MemberTicketCreateRequestDTO requestDTO); + TempTicketCreateResponseDTO createTicket(Long amateurShowId, Long amateurRoundId, Long amateurTicketId, Member member, TempTicketCreateRequestDTO requestDTO); List getRoundsList(Long memberId, Long amateurShowId); List getAmateurTicketList(Long memberId, Long amateurShowId); AmateurShowSimpleDTO getSimpleAmateurShow(Long amateurShowId); diff --git a/src/main/java/cc/backend/ticket/service/MemberTicketServiceImpl.java b/src/main/java/cc/backend/ticket/service/TempTicketServiceImpl.java similarity index 85% rename from src/main/java/cc/backend/ticket/service/MemberTicketServiceImpl.java rename to src/main/java/cc/backend/ticket/service/TempTicketServiceImpl.java index 45f8007..65224dd 100644 --- a/src/main/java/cc/backend/ticket/service/MemberTicketServiceImpl.java +++ b/src/main/java/cc/backend/ticket/service/TempTicketServiceImpl.java @@ -3,25 +3,22 @@ import cc.backend.amateurShow.entity.AmateurRounds; import cc.backend.amateurShow.entity.AmateurShow; import cc.backend.amateurShow.entity.AmateurTicket; -import cc.backend.amateurShow.repository.AmateurCastingRepository; -import cc.backend.amateurShow.repository.AmateurNoticeRepository; import cc.backend.amateurShow.repository.AmateurRoundsRepository; import cc.backend.amateurShow.repository.AmateurShowRepository; -import cc.backend.amateurShow.repository.AmateurStaffRepository; import cc.backend.amateurShow.repository.AmateurTicketRepository; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; import cc.backend.event.entity.TicketReservationEvent; import cc.backend.member.entity.Member; import cc.backend.member.repository.MemberRepository; -import cc.backend.ticket.dto.request.MemberTicketCreateRequestDTO; +import cc.backend.ticket.dto.request.TempTicketCreateRequestDTO; import cc.backend.ticket.dto.response.AmateurShowSimpleDTO; import cc.backend.ticket.dto.response.AmateurTicketListDTO; -import cc.backend.ticket.dto.response.MemberTicketCreateResponseDTO; +import cc.backend.ticket.dto.response.TempTicketCreateResponseDTO; import cc.backend.ticket.dto.response.RoundsListDTO; -import cc.backend.ticket.entity.MemberTicket; +import cc.backend.ticket.entity.TempTicket; import cc.backend.ticket.entity.enums.ReservationStatus; -import cc.backend.ticket.repository.MemberTicketRepository; +import cc.backend.ticket.repository.TempTicketRepository; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.List; @@ -34,9 +31,9 @@ @Service @RequiredArgsConstructor @Transactional(readOnly = true) -public class MemberTicketServiceImpl implements MemberTicketService { +public class TempTicketServiceImpl implements TempTicketService { - private final MemberTicketRepository memberTicketRepository; + private final TempTicketRepository tempTicketRepository; private final AmateurShowRepository amateurShowRepository; private final AmateurTicketRepository amateurTicketRepository; private final AmateurRoundsRepository amateurRoundsRepository; @@ -47,7 +44,7 @@ public class MemberTicketServiceImpl implements MemberTicketService { @Override @Transactional - public MemberTicketCreateResponseDTO createTicket(Long amateurShowId, Long amateurRoundId, Long amateurTicketId, Member member, MemberTicketCreateRequestDTO requestDTO) { + public TempTicketCreateResponseDTO createTicket(Long amateurShowId, Long amateurRoundId, Long amateurTicketId, Member member, TempTicketCreateRequestDTO requestDTO) { Member memberRef = memberRepository.getReferenceById(member.getId()); AmateurShow show = amateurShowRepository.findById(amateurShowId) @@ -72,7 +69,7 @@ public MemberTicketCreateResponseDTO createTicket(Long amateurShowId, Long amate int totalPrice = requestDTO.getQuantity() * amateurTicket.getPrice(); String bookingNumber = generateBookingNumber(); - MemberTicket ticket = MemberTicket.builder() + TempTicket ticket = TempTicket.builder() .member(memberRef) .amateurTicket(amateurTicket) .amateurRound(round) @@ -85,15 +82,15 @@ public MemberTicketCreateResponseDTO createTicket(Long amateurShowId, Long amate .reservationStatus(ReservationStatus.PENDING) .build(); - MemberTicket saved = memberTicketRepository.save(ticket); + TempTicket saved = tempTicketRepository.save(ticket); //티켓 예매 알림 이벤트 생성 eventPublisher.publishEvent(new TicketReservationEvent(ticket.getAmateurTicket().getAmateurShow(), ticket.getAmateurTicket(), memberRef)); // realTicket은 API를 사용해 호출 - //realTicketService.createRealTicketFromMemberTicket(saved.getId()); - return MemberTicketCreateResponseDTO.builder() - .memberTicketId(saved.getId()) + + return TempTicketCreateResponseDTO.builder() + .tempTicketId(saved.getId()) .bookingNumber(bookingNumber) .showTitle(amateurTicket.getAmateurShow().getName()) .detailAddress(amateurTicket.getAmateurShow().getDetailAddress()) diff --git a/src/test/java/cc/backend/kakaoPay/service/KakaoPayBusinessServiceConcurrencyTest.java b/src/test/java/cc/backend/kakaoPay/service/KakaoPayBusinessServiceConcurrencyTest.java index 09a50bd..7f5dbac 100644 --- a/src/test/java/cc/backend/kakaoPay/service/KakaoPayBusinessServiceConcurrencyTest.java +++ b/src/test/java/cc/backend/kakaoPay/service/KakaoPayBusinessServiceConcurrencyTest.java @@ -44,7 +44,7 @@ void ready_Fails_When_Stock_Is_Insufficient() { transactionTemplate.executeWithoutResult(status -> { em.createQuery("UPDATE AmateurRounds a SET a.totalTicket = 1 WHERE a.id = :id") .setParameter("id", roundId).executeUpdate(); - em.createQuery("UPDATE MemberTicket m SET m.quantity = 2 WHERE m.id = :id") + em.createQuery("UPDATE TempTicket m SET m.quantity = 2 WHERE m.id = :id") .setParameter("id", targetTicketId).executeUpdate(); }); @@ -66,7 +66,7 @@ void concurrentReady_With_One_Stock_Only_One_Succeeds() { transactionTemplate.executeWithoutResult(status -> { em.createQuery("UPDATE AmateurRounds a SET a.totalTicket = 1 WHERE a.id = :id") .setParameter("id", roundId).executeUpdate(); - em.createQuery("UPDATE MemberTicket m SET m.quantity = 1 WHERE m.id IN :ids") + em.createQuery("UPDATE TempTicket m SET m.quantity = 1 WHERE m.id IN :ids") .setParameter("ids", ticketIds).executeUpdate(); }); @@ -124,7 +124,7 @@ void concurrentReady_With_Sufficient_Stock_But_Limited_Success() { transactionTemplate.executeWithoutResult(status -> { em.createQuery("UPDATE AmateurRounds a SET a.totalTicket = 4 WHERE a.id = :id") .setParameter("id", roundId).executeUpdate(); - em.createQuery("UPDATE MemberTicket m SET m.quantity = 2 WHERE m.id IN :ids") + em.createQuery("UPDATE TempTicket m SET m.quantity = 2 WHERE m.id IN :ids") .setParameter("ids", ticketIds).executeUpdate(); });