diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/Ticket.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/Ticket.java new file mode 100644 index 00000000..287c1d1e --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/Ticket.java @@ -0,0 +1,36 @@ +package com.thirdparty.ticketing.domain.ticket; + +import java.util.UUID; + +import jakarta.persistence.*; + +import com.thirdparty.ticketing.domain.BaseEntity; +import com.thirdparty.ticketing.domain.member.Member; +import com.thirdparty.ticketing.domain.seat.Seat; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Entity +@AllArgsConstructor +@Table(name = "ticket") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Ticket extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long ticketId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member member; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "seat_id") + private Seat seat; + + private UUID ticketSerialNumber; +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/controller/TicketController.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/controller/TicketController.java new file mode 100644 index 00000000..d6f4adef --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/controller/TicketController.java @@ -0,0 +1,45 @@ +package com.thirdparty.ticketing.domain.ticket.controller; + +import jakarta.validation.Valid; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import com.thirdparty.ticketing.domain.ItemResult; +import com.thirdparty.ticketing.domain.ticket.dto.SeatSelectionRequest; +import com.thirdparty.ticketing.domain.ticket.dto.TicketElement; +import com.thirdparty.ticketing.domain.ticket.dto.TicketPaymentRequest; +import com.thirdparty.ticketing.domain.ticket.service.TicketService; +import com.thirdparty.ticketing.global.security.LoginMember; + +import lombok.RequiredArgsConstructor; + +@RestController("/api") +@RequiredArgsConstructor +public class TicketController { + private final TicketService ticketService; + + @GetMapping("/members/tickets") + public ResponseEntity> selectMyTickets( + @LoginMember String memberEmail) { + ItemResult tickets = ticketService.selectMyTicket(memberEmail); + return ResponseEntity.ok().body(tickets); + } + + @PostMapping("/seats/select") + public ResponseEntity selectSeat( + @RequestBody @Valid SeatSelectionRequest seatSelectionRequest) { + ticketService.selectSeat(seatSelectionRequest); + return ResponseEntity.ok().build(); + } + + @PostMapping("/tickets") + public ResponseEntity payTicket( + @RequestBody @Valid TicketPaymentRequest ticketPaymentRequest) { + ticketService.reservationTicket(ticketPaymentRequest); + return ResponseEntity.ok().build(); + } +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/SeatSelectionRequest.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/SeatSelectionRequest.java new file mode 100644 index 00000000..c4f6e2ce --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/SeatSelectionRequest.java @@ -0,0 +1,13 @@ +package com.thirdparty.ticketing.domain.ticket.dto; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class SeatSelectionRequest { + @NotNull(message = "좌석 ID를 요청하지 않았습니다.") + @Min(value = 1, message = "좌석 ID는 1 이상이어야 합니다.") + private Long seatId; +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/TicketElement.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/TicketElement.java new file mode 100644 index 00000000..085c03e6 --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/TicketElement.java @@ -0,0 +1,16 @@ +package com.thirdparty.ticketing.domain.ticket.dto; + +import java.util.UUID; + +import com.thirdparty.ticketing.domain.ticket.Ticket; + +import lombok.Data; + +@Data +public class TicketElement { + private final UUID serialNumber; + + public static TicketElement of(Ticket ticket) { + return new TicketElement(ticket.getTicketSerialNumber()); + } +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/TicketPaymentRequest.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/TicketPaymentRequest.java new file mode 100644 index 00000000..b812c0e0 --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/dto/TicketPaymentRequest.java @@ -0,0 +1,13 @@ +package com.thirdparty.ticketing.domain.ticket.dto; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; + +import lombok.Data; + +@Data +public class TicketPaymentRequest { + @NotNull(message = "좌석 ID를 요청하지 않았습니다.") + @Min(value = 1, message = "좌석 ID는 1 이상이어야 합니다.") + private Long seatId; +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/repository/TicketRepository.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/repository/TicketRepository.java new file mode 100644 index 00000000..97118480 --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/repository/TicketRepository.java @@ -0,0 +1,12 @@ +package com.thirdparty.ticketing.domain.ticket.repository; + +import java.util.List; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.thirdparty.ticketing.domain.member.Member; +import com.thirdparty.ticketing.domain.ticket.Ticket; + +public interface TicketRepository extends JpaRepository { + List findAllByMember(Member member); +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/service/CacheTicketService.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/service/CacheTicketService.java new file mode 100644 index 00000000..270f5953 --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/service/CacheTicketService.java @@ -0,0 +1,22 @@ +package com.thirdparty.ticketing.domain.ticket.service; + +import com.thirdparty.ticketing.domain.member.repository.MemberRepository; +import com.thirdparty.ticketing.domain.seat.repository.SeatRepository; +import com.thirdparty.ticketing.domain.ticket.dto.SeatSelectionRequest; +import com.thirdparty.ticketing.domain.ticket.dto.TicketPaymentRequest; +import com.thirdparty.ticketing.domain.ticket.repository.TicketRepository; + +public class CacheTicketService extends TicketService { + public CacheTicketService( + MemberRepository memberRepository, + TicketRepository ticketRepository, + SeatRepository seatRepository) { + super(memberRepository, ticketRepository, seatRepository); + } + + @Override + public void selectSeat(SeatSelectionRequest seatSelectionRequest) {} + + @Override + public void reservationTicket(TicketPaymentRequest ticketPaymentRequest) {} +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/service/PersistenceTicketService.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/service/PersistenceTicketService.java new file mode 100644 index 00000000..8688b981 --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/service/PersistenceTicketService.java @@ -0,0 +1,25 @@ +package com.thirdparty.ticketing.domain.ticket.service; + +import org.springframework.stereotype.Service; + +import com.thirdparty.ticketing.domain.member.repository.MemberRepository; +import com.thirdparty.ticketing.domain.seat.repository.SeatRepository; +import com.thirdparty.ticketing.domain.ticket.dto.SeatSelectionRequest; +import com.thirdparty.ticketing.domain.ticket.dto.TicketPaymentRequest; +import com.thirdparty.ticketing.domain.ticket.repository.TicketRepository; + +@Service +public class PersistenceTicketService extends TicketService { + public PersistenceTicketService( + MemberRepository memberRepository, + TicketRepository ticketRepository, + SeatRepository seatRepository) { + super(memberRepository, ticketRepository, seatRepository); + } + + @Override + public void selectSeat(SeatSelectionRequest seatSelectionRequest) {} + + @Override + public void reservationTicket(TicketPaymentRequest ticketPaymentRequest) {} +} diff --git a/src/main/java/com/thirdparty/ticketing/domain/ticket/service/TicketService.java b/src/main/java/com/thirdparty/ticketing/domain/ticket/service/TicketService.java new file mode 100644 index 00000000..134330b8 --- /dev/null +++ b/src/main/java/com/thirdparty/ticketing/domain/ticket/service/TicketService.java @@ -0,0 +1,38 @@ +package com.thirdparty.ticketing.domain.ticket.service; + +import java.util.List; + +import com.thirdparty.ticketing.domain.ItemResult; +import com.thirdparty.ticketing.domain.common.TicketingException; +import com.thirdparty.ticketing.domain.member.Member; +import com.thirdparty.ticketing.domain.member.repository.MemberRepository; +import com.thirdparty.ticketing.domain.seat.repository.SeatRepository; +import com.thirdparty.ticketing.domain.ticket.dto.SeatSelectionRequest; +import com.thirdparty.ticketing.domain.ticket.dto.TicketElement; +import com.thirdparty.ticketing.domain.ticket.dto.TicketPaymentRequest; +import com.thirdparty.ticketing.domain.ticket.repository.TicketRepository; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public abstract class TicketService { + private final MemberRepository memberRepository; + private final TicketRepository ticketRepository; + private final SeatRepository seatRepository; + + public ItemResult selectMyTicket(String memberEmail) { + Member member = + memberRepository + .findByEmail(memberEmail) + .orElseThrow(() -> new TicketingException("Member not found")); + + List tickets = + ticketRepository.findAllByMember(member).stream().map(TicketElement::of).toList(); + + return ItemResult.of(tickets); + } + + public abstract void selectSeat(SeatSelectionRequest seatSelectionRequest); + + public abstract void reservationTicket(TicketPaymentRequest ticketPaymentRequest); +}