From 4a8e99b677a0a2a7dcc7afd52185030820125e2f Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Tue, 23 Dec 2025 10:36:50 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat=20:=20=EA=B3=B5=EC=97=B0=20=EC=98=88?= =?UTF-8?q?=EB=A7=A4=20=EC=A2=85=EB=A3=8C=20=EC=8B=9C=EA=B0=84=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/concert/ConcertDetailResponse.java | 6 ++ .../concerts/dto/concert/ConcertItem.java | 6 ++ .../concert/ConcertTicketTimeSetRequest.java | 7 +- .../domain/concerts/entity/Concert.java | 9 +- .../repository/ConcertRepository.java | 1 + .../concerts/service/ConcertService.java | 2 +- .../concerts/service/KopisApiService.java | 2 + .../global/initData/BaseInitData.java | 101 +++++++++--------- 8 files changed, 81 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertDetailResponse.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertDetailResponse.java index b4f53888..18f16db8 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertDetailResponse.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertDetailResponse.java @@ -40,6 +40,11 @@ public class ConcertDetailResponse { @Schema(description = "콘서트 예매 시작 날짜입니다.") private LocalDateTime ticketTime; + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @Schema(description = "콘서트 예매 종료 날짜입니다.") + private LocalDateTime ticketEndTime; + @JsonSerialize(using = LocalDateSerializer.class) @JsonDeserialize(using = LocalDateDeserializer.class) @Schema(description = "콘서트 시작 날짜입니다.",format = "yyyy-MM-dd") @@ -69,4 +74,5 @@ public class ConcertDetailResponse { private List concertImageUrls; + } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertItem.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertItem.java index 5132c2a1..d69cfc89 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertItem.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertItem.java @@ -34,6 +34,11 @@ public class ConcertItem { @Schema(description = "콘서트 예매 시작 날짜입니다.",format = "yyyy-MM-ddThh:mm:ss") private LocalDateTime ticketTime; + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @Schema(description = "콘서트 예매 종료 날짜입니다.") + private LocalDateTime ticketEndTime; + @JsonSerialize(using = LocalDateSerializer.class) @JsonDeserialize(using = LocalDateDeserializer.class) @Schema(description = "콘서트 시작 날짜입니다.",format = "yyyy-MM-dd") @@ -64,6 +69,7 @@ public ConcertItem(Concert concert) { this.name = concert.getName(); this.placeName = concert.getConcertPlace().getPlaceName(); this.ticketTime = concert.getTicketTime(); + this.ticketEndTime = concert.getTicketEndTime(); this.startDate = concert.getStartDate(); this.endDate =concert.getEndDate(); this.posterUrl = concert.getPosterUrl(); diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertTicketTimeSetRequest.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertTicketTimeSetRequest.java index e7eb182b..1f0268ac 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertTicketTimeSetRequest.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertTicketTimeSetRequest.java @@ -13,7 +13,12 @@ public class ConcertTicketTimeSetRequest { @NotNull(message = "예매 시작 시간 입력시 해당 공연의 ID 값 입력은 필수입니다.") private Long concertId; - @Schema(description = "티켓팅 시간입니다.") + @Schema(description = "티켓팅 시작 시간입니다.") @NotNull(message = "예매 시작 시간 설정시 시간 입력은 필수입니다.") private LocalDateTime ticketTime; + + + @Schema(description = "티켓팅 종료 시간입니다.") + @NotNull(message = "예매 종료 시간 설정시 시간 입력은 필수입니다.") + private LocalDateTime ticketEndTime; } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/Concert.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/Concert.java index beaefc56..27389ea5 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/Concert.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/Concert.java @@ -38,6 +38,9 @@ public class Concert { @Column(name = "ticket_time", nullable = true) private LocalDateTime ticketTime; + @Column(name = "ticket_end_time", nullable = true) + private LocalDateTime ticketEndTime; + @Column(name = "created_date", nullable = false) private LocalDateTime createdDate; @@ -62,11 +65,12 @@ public class Concert { - public Concert(ConcertPlace concertPlace, String name, String content, LocalDate startDate, LocalDate endDate, LocalDateTime ticketTime, int maxPrice, int minPrice, String posterUrl,String apiConcertId) { + public Concert(ConcertPlace concertPlace, String name, String content, LocalDate startDate, LocalDate endDate, LocalDateTime ticketTime,LocalDateTime ticketEndTime, int maxPrice, int minPrice, String posterUrl,String apiConcertId) { this.concertPlace = concertPlace; this.name = name; this.content = content; this.ticketTime = ticketTime; + this.ticketEndTime = ticketTime; this.startDate = startDate; this.endDate = endDate; this.createdDate = LocalDateTime.now(); @@ -109,8 +113,9 @@ public Concert update(ConcertUpdateRequest concertUpdateRequest,ConcertPlace con return this; } - public Concert ticketTimeSet(LocalDateTime ticketTime){ + public Concert ticketTimeSet(LocalDateTime ticketTime, LocalDateTime ticketEndTime) { this.ticketTime = ticketTime; + this.ticketEndTime = ticketEndTime; return this; } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertRepository.java index f369e306..befaeed4 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertRepository.java @@ -173,6 +173,7 @@ List getConcertItemsByKeyword( c.concertPlace.placeName as placeName, c.concertPlace.address as placeAddress, c.ticketTime as ticketTime, + c.ticketEndTime as ticketEndTime, c.startDate as startDate, c.endDate as endDate, c.posterUrl as posterUrl, diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java index 88ea1476..e3d44c1d 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java @@ -211,7 +211,7 @@ public ConcertItem updateConcert(long concertId, ConcertUpdateRequest concertUpd // 공연 시간 설정 public ConcertDetailResponse setConcertTicketingTime(ConcertTicketTimeSetRequest concertTicketTimeSetRequest) { Concert concert = findConcertByConcertId(concertTicketTimeSetRequest.getConcertId()); - concert.ticketTimeSet(concertTicketTimeSetRequest.getTicketTime()); + concert.ticketTimeSet(concertTicketTimeSetRequest.getTicketTime(), concertTicketTimeSetRequest.getTicketEndTime()); Concert savedConcert = concertRepository.save(concert); return concertRepository.getConcertDetailById(savedConcert.getConcertId()); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/KopisApiService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/KopisApiService.java index 49e98342..70015a6a 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/KopisApiService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/KopisApiService.java @@ -156,6 +156,7 @@ public void setConcertsList() throws InterruptedException { dateStringToDateTime(concertDetail.getStartDate()), dateStringToDateTime(concertDetail.getEndDate()), null, + null, ticketPrice.maxPrice, ticketPrice.minPrice, concertDetail.getPosterUrl(), @@ -261,6 +262,7 @@ public SetResultResponse updateConcertData() throws InterruptedException { dateStringToDateTime(concertDetail.getStartDate()), dateStringToDateTime(concertDetail.getEndDate()), null, + null, ticketPrice.maxPrice, ticketPrice.minPrice, concertDetail.getPosterUrl(), diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/initData/BaseInitData.java b/src/main/java/com/back/web7_9_codecrete_be/global/initData/BaseInitData.java index 661c244d..d82b3a73 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/initData/BaseInitData.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/initData/BaseInitData.java @@ -85,68 +85,71 @@ private void createConcertsForChatTest() { } ConcertPlace place = concertPlaceRepository.findAll().stream() - .findFirst() - .orElseGet(() -> - concertPlaceRepository.save( - new ConcertPlace( - "테스트 공연장", - "서울특별시 중구 테스트로 123", - 37.5665, - 126.9780, - 5000, - "API-CONCERT-PLACE-1" - ) - ) - ); + .findFirst() + .orElseGet(() -> + concertPlaceRepository.save( + new ConcertPlace( + "테스트 공연장", + "서울특별시 중구 테스트로 123", + 37.5665, + 126.9780, + 5000, + "API-CONCERT-PLACE-1" + ) + ) + ); LocalDateTime now = LocalDateTime.now(); // 채팅 가능 (정책 기간 중) concertRepository.save( - new Concert( - place, - "채팅 가능 공연", - "채팅 테스트용 공연 (정책 기간 중)", - LocalDate.now(), - LocalDate.now().plusDays(2), - LocalDateTime.of(2025, 12, 19, 0, 0), - 150000, - 50000, - "https://example.com/poster1.jpg", - "API-CONCERT-CHAT-1" - ) + new Concert( + place, + "채팅 가능 공연", + "채팅 테스트용 공연 (정책 기간 중)", + LocalDate.now(), + LocalDate.now().plusDays(2), + LocalDateTime.of(2025, 12, 19, 0, 0), + LocalDateTime.of(2025, 12, 21, 0, 0), + 150000, + 50000, + "https://example.com/poster1.jpg", + "API-CONCERT-CHAT-1" + ) ); // 채팅 불가 (정책 시작 전) concertRepository.save( - new Concert( - place, - "채팅 불가 공연 - 시작 전", - "아직 채팅이 오픈되지 않은 공연", - LocalDate.now().plusDays(5), - LocalDate.now().plusDays(7), - LocalDateTime.of(2025, 12, 25, 0, 0), - 120000, - 40000, - "https://example.com/poster2.jpg", - "API-CONCERT-CHAT-2" - ) + new Concert( + place, + "채팅 불가 공연 - 시작 전", + "아직 채팅이 오픈되지 않은 공연", + LocalDate.now().plusDays(5), + LocalDate.now().plusDays(7), + LocalDateTime.of(2025, 12, 25, 0, 0), + LocalDateTime.of(2025, 12, 30, 0, 0), + 120000, + 40000, + "https://example.com/poster2.jpg", + "API-CONCERT-CHAT-2" + ) ); // 채팅 불가 (정책 종료 후) concertRepository.save( - new Concert( - place, - "채팅 종료된 공연", - "채팅 가능 기간이 지난 공연", - LocalDate.now().minusDays(10), - LocalDate.now().minusDays(7), - LocalDateTime.of(2025, 11, 1, 0, 0), - 100000, - 30000, - "https://example.com/poster3.jpg", - "API-CONCERT-CHAT-3" - ) + new Concert( + place, + "채팅 종료된 공연", + "채팅 가능 기간이 지난 공연", + LocalDate.now().minusDays(10), + LocalDate.now().minusDays(7), + LocalDateTime.of(2025, 11, 1, 0, 0), + LocalDateTime.of(2025, 11, 15, 0, 0), + 100000, + 30000, + "https://example.com/poster3.jpg", + "API-CONCERT-CHAT-3" + ) ); } } From a77ca6c09e8b4e7e13f1f4acfc515c1ed49f08e5 Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Tue, 23 Dec 2025 12:35:16 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EA=B3=B5=EC=97=B0=20=EC=98=88?= =?UTF-8?q?=EB=A7=A4=EC=9D=BC=20=EC=B6=94=EA=B0=80=EC=8B=9C=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/concerts/service/ConcertService.java | 14 ++++++++++---- .../global/error/code/ConcertErrorCode.java | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java index e3d44c1d..28adc335 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/service/ConcertService.java @@ -7,6 +7,7 @@ import com.back.web7_9_codecrete_be.domain.concerts.repository.*; import com.back.web7_9_codecrete_be.domain.users.entity.User; import com.back.web7_9_codecrete_be.global.error.code.ConcertErrorCode; +import com.back.web7_9_codecrete_be.global.error.code.ErrorCode; import com.back.web7_9_codecrete_be.global.error.exception.BusinessException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -121,14 +122,14 @@ public Long getTotalConcertsCount() { return result; } - // todo : 티켓팅 공연 개수 조회 + // 티켓팅 공연 개수 조회 public Long getTotalTicketingConcertsCount() { Long result = concertRedisRepository.getTotalConcertsCount(ListSort.TICKETING); if(result == -1) result = concertRedisRepository.saveTotalConcertsCount(concertRepository.countTicketingConcertsFromLocalDateTime(LocalDateTime.of(LocalDate.now(), LocalTime.MIN)), ListSort.TICKETING); return result; } - // todo : 좋아요한 공연 개수 조회 + // 좋아요한 공연 개수 조회 public Long getTotalLikedConcertsCount(User user) { Long result = concertRedisRepository.getUserLikedCount(user); if(result == -1) result = concertRedisRepository.saveUserLikedCount(user,concertLikeRepository.countByUser(user)); @@ -208,10 +209,15 @@ public ConcertItem updateConcert(long concertId, ConcertUpdateRequest concertUpd return new ConcertItem(updatedConcert); } - // 공연 시간 설정 + // 공연 예매 시간 설정 public ConcertDetailResponse setConcertTicketingTime(ConcertTicketTimeSetRequest concertTicketTimeSetRequest) { Concert concert = findConcertByConcertId(concertTicketTimeSetRequest.getConcertId()); - concert.ticketTimeSet(concertTicketTimeSetRequest.getTicketTime(), concertTicketTimeSetRequest.getTicketEndTime()); + LocalDateTime ticketTime = concertTicketTimeSetRequest.getTicketTime(); + LocalDateTime ticketEndTime = concertTicketTimeSetRequest.getTicketEndTime(); + if(ticketTime.isAfter(ticketEndTime)) throw new BusinessException(ConcertErrorCode.NOT_VALID_TICKETING_TIME); + if(ticketTime.isBefore(LocalDateTime.now())) throw new BusinessException(ConcertErrorCode.NOT_VALID_TICKETING_TIME); + + concert.ticketTimeSet(ticketTime, ticketEndTime); Concert savedConcert = concertRepository.save(concert); return concertRepository.getConcertDetailById(savedConcert.getConcertId()); } diff --git a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/ConcertErrorCode.java b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/ConcertErrorCode.java index 5dad2a26..7804f68d 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/global/error/code/ConcertErrorCode.java +++ b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/ConcertErrorCode.java @@ -13,7 +13,8 @@ public enum ConcertErrorCode implements ErrorCode { CONCERT_NOT_FOUND(HttpStatus.NOT_FOUND,"C-101","공연을 찾을 수 없습니다."), KEYWORD_IS_NULL(HttpStatus.BAD_REQUEST,"C-102","검색 키워드를 입력해주세요."), LIKE_CONFLICT(HttpStatus.CONFLICT,"C-131","이미 좋아요를 누른 공연입니다."), - NOT_FOUND_CONCERTLIKE(HttpStatus.NOT_FOUND,"C-130","좋아요를 누르지 않은 공연입니다.") + NOT_FOUND_CONCERTLIKE(HttpStatus.NOT_FOUND,"C-130","좋아요를 누르지 않은 공연입니다."), + NOT_VALID_TICKETING_TIME(HttpStatus.BAD_REQUEST, "C-140","공연 예매 시간이 옳지 않습니다. 확인해 주십시오.") ; private final HttpStatus status;