diff --git a/src/main/java/cc/backend/amateurShow/controller/AmateurController.java b/src/main/java/cc/backend/amateurShow/controller/AmateurController.java index 39c6d2d..e0bb7c2 100644 --- a/src/main/java/cc/backend/amateurShow/controller/AmateurController.java +++ b/src/main/java/cc/backend/amateurShow/controller/AmateurController.java @@ -30,7 +30,6 @@ @RequestMapping("/amateurs") public class AmateurController { - private final MemberService memberService; private final AmateurService amateurService; @PreAuthorize("hasRole('PERFORMER')") @@ -57,50 +56,46 @@ public ApiResponse deleteShow(@AuthenticationPrincipal(expression = "mem @GetMapping("/{amateurShowId}") @Operation(summary = "소극장 공연 조회 - 단건") - public ApiResponse getAmateurShow(@AuthenticationPrincipal(expression = "member") Member member, - @PathVariable Long amateurShowId){ - return ApiResponse.onSuccess(amateurService.getAmateurShow(member.getId(), amateurShowId)); + public ApiResponse getAmateurShow(@PathVariable Long amateurShowId){ + return ApiResponse.onSuccess(amateurService.getAmateurShow(amateurShowId)); } @GetMapping("/ranking") @Operation(summary = "소극장 공연 랭킹 조회 API") - public ApiResponse> getShowRanking(@AuthenticationPrincipal(expression = "member") Member member) { - return ApiResponse.onSuccess(amateurService.getShowRanking(member.getId())); + public ApiResponse> getShowRanking() { + return ApiResponse.onSuccess(amateurService.getShowRanking()); } @GetMapping("/today") @Operation(summary = "오늘 진행하는 소극장 공연 조회 API") - public ApiResponse> getShowToday( - @AuthenticationPrincipal(expression = "member") Member member, @ParameterObject Pageable pageable) { - return ApiResponse.onSuccess(SliceResponse.of(amateurService.getShowToday(member.getId(), pageable))); + public ApiResponse> getShowToday( @ParameterObject Pageable pageable) { + return ApiResponse.onSuccess(SliceResponse.of(amateurService.getShowToday(pageable))); } @GetMapping("/ongoing") @Operation(summary = "현재 진행중인 소극장 공연 조회 API") - public ApiResponse> getShowOngoing( - @AuthenticationPrincipal(expression = "member") Member member, @ParameterObject Pageable pageable + public ApiResponse> getShowOngoing( @ParameterObject Pageable pageable ) { - Slice sliceResult = amateurService.getShowOngoing(member.getId(), pageable); + Slice sliceResult = amateurService.getShowOngoing(pageable); return ApiResponse.onSuccess(SliceResponse.of(sliceResult)); } @GetMapping("/closing") @Operation(summary = "오늘 마감인 공연 조회 API") - public ApiResponse> getShowClosing(@AuthenticationPrincipal(expression = "member") Member member) { - return ApiResponse.onSuccess(amateurService.getShowClosing(member.getId())); + public ApiResponse> getShowClosing() { + return ApiResponse.onSuccess(amateurService.getShowClosing()); } @GetMapping("/recentlyHot") @Operation(summary = "요즘 핫한 소극장 연극 조회 API") - public ApiResponse> getRecentlyHotShow(@AuthenticationPrincipal(expression = "member") Member member) { - return ApiResponse.onSuccess(amateurService.getRecentlyHotShow(member.getId())); + public ApiResponse> getRecentlyHotShow() { + return ApiResponse.onSuccess(amateurService.getRecentlyHotShow()); } @GetMapping("/incoming") @Operation(summary = "임박한 공연 조회 API") - public ApiResponse> getShowIncoming( - @AuthenticationPrincipal(expression = "member") Member member, @ParameterObject Pageable pageable) { - Slice sliceResult = amateurService.getShowToday(member.getId(), pageable); + public ApiResponse> getShowIncoming(@ParameterObject Pageable pageable) { + Slice sliceResult = amateurService.getShowToday(pageable); return ApiResponse.onSuccess(SliceResponse.of(sliceResult)); } } \ No newline at end of file diff --git a/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java b/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java index 81ddce6..98f628e 100644 --- a/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java +++ b/src/main/java/cc/backend/amateurShow/repository/AmateurShowRepository.java @@ -18,7 +18,6 @@ @Repository public interface AmateurShowRepository extends JpaRepository, JpaSpecificationExecutor { - List findAllByMemberId(Long memberId); @Query("SELECT a FROM AmateurShow a WHERE a.id = :id") Optional findByIdWithDetails(@Param("id") Long id); @@ -34,9 +33,6 @@ Slice findAllByMemberIdAndStatusOrderByIdDesc(@Param("memberId") Lo @Param("status") AmateurShowStatus status, Pageable pageable); - List findAllByMemberIdOrderByUpdatedAtDesc(@Param("memberId") Long memberId); - - @Query(""" select s from AmateurShow s @@ -60,16 +56,15 @@ Slice findByMember_IdAndStatusInOrderByIdDesc( long countByMember_Id(Long memberId); - Page findByNameContainingIgnoreCase(String showName, Pageable pageable); - - List findByEndGreaterThanEqual(LocalDate today); + List findAllByMemberId(Long memberId); @Query(""" SELECT s FROM AmateurShow s WHERE s.end >= :today + AND s.approvalStatus = 'APPROVED' ORDER BY s.end ASC """) List findHotShows( diff --git a/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java b/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java index a33f5f1..ce102a3 100644 --- a/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java +++ b/src/main/java/cc/backend/amateurShow/repository/specification/AmateurShowSpecification.java @@ -1,19 +1,18 @@ package cc.backend.amateurShow.repository.specification; +import cc.backend.amateurShow.entity.AmateurRounds; import cc.backend.amateurShow.entity.AmateurShow; import cc.backend.amateurShow.entity.enums.ApprovalStatus; import cc.backend.member.entity.Member; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.Path; import org.springframework.data.jpa.domain.Specification; import java.time.LocalDate; public class AmateurShowSpecification { - public static Specification isAudienceVisible() { - return (root, query, criteriaBuilder) -> - criteriaBuilder.equal(root.get("approvalStatus"), ApprovalStatus.APPROVED); - } - public static Specification isWrittenBy(Member performer) { return (root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("member"), performer); @@ -45,4 +44,54 @@ public static Specification isNotEnded(LocalDate today) { return (root, query, criteriaBuilder) -> criteriaBuilder.greaterThanOrEqualTo(root.get("end"), today); } + + /** + * 오늘 날짜 회차 필터 + * performanceDateTime이 전달된 날짜(date)와 일치하는 공연만 + */ + public static Specification hasRoundOn(LocalDate date) { + return (root, query, cb) -> { + // 중복 제거 필요 시 + query.distinct(true); + + // Join to amateurRounds + var rounds = root.join("amateurRounds"); + + // 날짜만 비교 (MySQL 기준) + return cb.equal(cb.function("DATE", LocalDate.class, rounds.get("performanceDateTime")), date); + }; + } + + /** + * 마지막 회차 날짜가 오늘인 공연 필터 + */ + public static Specification hasLastRoundOn(LocalDate today) { + return (root, query, cb) -> { + query.distinct(true); + + // 서브쿼리: AmateurRounds 기준 + var subquery = query.subquery(LocalDate.class); + var roundRoot = subquery.from(AmateurRounds.class); + + // MAX(DATE(performanceDateTime)) + Expression lastRoundDate = + cb.greatest( + cb.function( + "DATE", + LocalDate.class, + roundRoot.get("performanceDateTime") + ) + ); + + subquery.select(lastRoundDate); + + // 해당 공연의 회차만 대상 + subquery.where( + cb.equal(roundRoot.get("amateurShow"), root) + ); + + // 마지막 회차 날짜 == today + return cb.equal(subquery, today); + }; + } } diff --git a/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurService.java b/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurService.java index f1aa749..606bc3b 100644 --- a/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurService.java +++ b/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurService.java @@ -5,7 +5,6 @@ import cc.backend.amateurShow.dto.AmateurShowResponseDTO; import cc.backend.amateurShow.dto.AmateurUpdateRequestDTO; import cc.backend.amateurShow.entity.AmateurShowStatus; -import cc.backend.ticket.dto.response.ReserveListResponseDTO; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Slice; import org.springframework.stereotype.Service; @@ -16,14 +15,14 @@ public interface AmateurService { AmateurEnrollResponseDTO.AmateurEnrollResult enrollShow(Long memberId, AmateurEnrollRequestDTO requestDTO); - AmateurShowResponseDTO.AmateurShowResult getAmateurShow(Long memberId, Long amateurId); + AmateurShowResponseDTO.AmateurShowResult getAmateurShow(Long amateurId); AmateurEnrollResponseDTO.AmateurEnrollResult updateShow(Long memberId, Long showId, AmateurUpdateRequestDTO requestDTO); void deleteShow(Long memberId, Long amateurShowId); - Slice getShowToday(Long memberId, Pageable pageable); - Slice getShowOngoing(Long memberId, Pageable pageable); - List getShowRanking(Long memberId); - List getRecentlyHotShow(Long memberId); - List getShowClosing(Long memberId); + Slice getShowToday(Pageable pageable); + Slice getShowOngoing(Pageable pageable); + List getShowRanking(); + List getRecentlyHotShow(); + List getShowClosing(); Slice getMyAmateurShow(Long memberId, AmateurShowStatus showStatus, Pageable pageable); diff --git a/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurServiceImpl.java b/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurServiceImpl.java index 72522fd..2991407 100644 --- a/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurServiceImpl.java +++ b/src/main/java/cc/backend/amateurShow/service/amateurShowService/AmateurServiceImpl.java @@ -3,10 +3,12 @@ import cc.backend.amateurShow.dto.AmateurShowResponseDTO; import cc.backend.amateurShow.dto.AmateurUpdateRequestDTO; import cc.backend.amateurShow.entity.*; +import cc.backend.amateurShow.entity.enums.ApprovalStatus; import cc.backend.amateurShow.repository.*; import cc.backend.amateurShow.converter.AmateurConverter; import cc.backend.amateurShow.dto.AmateurEnrollRequestDTO; import cc.backend.amateurShow.dto.AmateurEnrollResponseDTO; +import cc.backend.amateurShow.repository.specification.AmateurShowSpecification; import cc.backend.apiPayLoad.code.status.ErrorStatus; import cc.backend.apiPayLoad.exception.GeneralException; import cc.backend.board.entity.enums.BoardType; @@ -24,11 +26,9 @@ import cc.backend.memberLike.repository.MemberLikeRepository; import cc.backend.ticket.dto.response.ReserveListResponseDTO; import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.*; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.data.domain.Slice; -import org.springframework.data.domain.SliceImpl; +import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -443,134 +443,96 @@ public void deleteShow(Long memberId, Long amateurShowId) { // 소극장 공연 단건 조회 @Override - public AmateurShowResponseDTO.AmateurShowResult getAmateurShow(Long memberId, Long amateurShowId) { - Member member = memberRepository.findById(memberId) - .orElseThrow(()-> new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED)); - + public AmateurShowResponseDTO.AmateurShowResult getAmateurShow(Long amateurShowId) { AmateurShow amateurShow = amateurShowRepository.findById(amateurShowId) .orElseThrow(() -> new GeneralException(ErrorStatus.AMATEURSHOW_NOT_FOUND)); - return AmateurConverter.toResponseDTO(amateurShow); } // 오늘 진행하는 소극장 공연 리스트 조회 @Override - public Slice getShowToday(Long memberId, Pageable pageable) { - Member member = memberRepository.findById(memberId) - .orElseThrow(()-> new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED)); + public Slice getShowToday(Pageable pageable) { LocalDate today = LocalDate.now(); - List allShows = amateurShowRepository.findAllWithRounds(); - - // 오늘 날짜를 가진 회차가 있는 공연만 - List result = allShows.stream() - .filter(show -> show.getAmateurRounds().stream() - .anyMatch(round -> - round.getPerformanceDateTime() - .toLocalDate() - .equals(today) - ) - ) - .distinct() - .sorted(Comparator.comparing(AmateurShow::getStart)) // 정렬 필요하면 유지 - .map(show -> { - String schedule = AmateurConverter.mergeSchedule( - show.getStart(), - show.getEnd() - ); - return AmateurShowResponseDTO.AmateurShowList.builder() - .amateurShowId(show.getId()) - .name(show.getName()) - .detailAddress(show.getDetailAddress()) - .schedule(schedule) - .posterImageUrl(show.getPosterImageUrl()) - .build(); - }) - .collect(Collectors.toList()); - - // ===== Slice 페이징 처리 ===== - int start = (int) pageable.getOffset(); - int end = Math.min(start + pageable.getPageSize(), result.size()); - List content = new ArrayList<>(); - if (start < result.size()) { - content = result.subList(start, end); - } + // Specification 조합 : 승인된 공연 + 오늘 공연하는 회차 존재 + Specification spec = Specification + .where(AmateurShowSpecification.isApproved()) + .and(AmateurShowSpecification.hasRoundOn(today)); - boolean hasNext = end < result.size(); + // DB 레벨에서 페이징 + 필터링 + Slice showSlice = amateurShowRepository.findAll(spec, pageable); - return new SliceImpl<>(content, pageable, hasNext); + // DTO 변환 + return showSlice.map(show -> { + String schedule = AmateurConverter.mergeSchedule(show.getStart(), show.getEnd()); + return AmateurShowResponseDTO.AmateurShowList.builder() + .amateurShowId(show.getId()) + .name(show.getName()) + .detailAddress(show.getDetailAddress()) + .schedule(schedule) + .posterImageUrl(show.getPosterImageUrl()) + .build(); + }); } // 현재 진행중인 소극장 공연 리스트 조회 @Override - public Slice getShowOngoing(Long memberId, Pageable pageable) { - Member member = memberRepository.findById(memberId) - .orElseThrow(()-> new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED)); + public Slice getShowOngoing(Pageable pageable) { LocalDate today = LocalDate.now(); - List allShows = amateurShowRepository.findAllWithRounds(); - - List result = allShows.stream() - // 오늘 날짜가 schedule 기간 내에 포함된 공연만 필터링 - .filter(show -> { - LocalDate start = show.getStart(); - LocalDate end = show.getEnd(); - return start != null && end != null - && !today.isBefore(start) - && !today.isAfter(end); - }) - // 공연 시작일 기준 오름차순 정렬 - .sorted(Comparator.comparing(AmateurShow::getStart)) - // DTO로 변환 - .map(show -> { - String schedule = AmateurConverter.mergeSchedule(show.getStart(), show.getEnd()); - return AmateurShowResponseDTO.AmateurShowList.builder() - .amateurShowId(show.getId()) - .name(show.getName()) - .detailAddress(show.getDetailAddress()) - .schedule(schedule) - .posterImageUrl(show.getPosterImageUrl()) - .build(); - }) - .collect(Collectors.toList()); - int start = (int) pageable.getOffset(); - int end = Math.min(start + pageable.getPageSize(), result.size()); + // Specification 조합: 승인 + 현재 진행 중인 공연 + Specification spec = Specification + .where(AmateurShowSpecification.isApproved()) + .and(AmateurShowSpecification.isOngoing(today)); - List content = new ArrayList<>(); - if (start < result.size()) { - content = result.subList(start, end); - } + Pageable sortedPage = PageRequest.of( + pageable.getPageNumber(), + pageable.getPageSize(), + Sort.by("start").ascending() + ); - boolean hasNext = end < result.size(); + Slice showSlice = amateurShowRepository.findAll(spec, sortedPage); - return new SliceImpl<>(content, pageable, hasNext); // 시그니처 (List, pageable, hasNext) + return showSlice.map(show -> { + String schedule = AmateurConverter.mergeSchedule(show.getStart(), show.getEnd()); + return AmateurShowResponseDTO.AmateurShowList.builder() + .amateurShowId(show.getId()) + .name(show.getName()) + .detailAddress(show.getDetailAddress()) + .schedule(schedule) + .posterImageUrl(show.getPosterImageUrl()) + .build(); + }); } // 소극장 공연 랭킹 리스트 조회 @Override - public List getShowRanking(Long memberId) { - Member member = memberRepository.findById(memberId) - .orElseThrow(()-> new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED)); + public List getShowRanking() { LocalDate today = LocalDate.now(); - List shows = amateurShowRepository.findAllWithRounds(); - return shows.stream() - // 종료일이 오늘 이후인 공연만 필터링 - .filter(show -> { - LocalDate start = show.getStart(); - LocalDate end = show.getEnd(); - return start != null && end != null && !today.isAfter(end); - }) - // 정렬: 판매 티켓 수 내림차순 → 시작일 오름차순 - .sorted(Comparator - .comparing(AmateurShow::getTotalSoldTicket, Comparator.nullsLast(Comparator.reverseOrder())) - .thenComparing(AmateurShow::getStart)) - .limit(10) - // DTO 변환 + // Specification 조합: 종료일이 오늘 이후 + 승인된 공연 + Specification spec = Specification + .where(AmateurShowSpecification.isNotEnded(today)) + .and(AmateurShowSpecification.isApproved()); + + // Pageable로 정렬 + limit 10 적용 + Pageable sortedPage = PageRequest.of( + 0, + 10, + Sort.by( + Sort.Order.desc("totalSoldTicket"), // 판매 티켓 수 내림차순 + Sort.Order.asc("start") // 시작일 오름차순 + ) + ); + + Slice showSlice = amateurShowRepository.findAll(spec, sortedPage); + + // DTO 변환 + return showSlice.stream() .map(show -> { String schedule = AmateurConverter.mergeSchedule(show.getStart(), show.getEnd()); return AmateurShowResponseDTO.AmateurShowList.builder() @@ -582,40 +544,34 @@ public List getShowRanking(Long memberId .build(); }) .collect(Collectors.toList()); + } // 오늘 마감인 소극장 공연 리스트 조회 @Override - public List getShowClosing(Long memberId) { - Member member = memberRepository.findById(memberId) - .orElseThrow(()-> new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED)); + public List getShowClosing() { - List allShows = amateurShowRepository.findAllWithRounds(); LocalDate today = LocalDate.now(); - List result = new ArrayList<>(); - - for (AmateurShow show : allShows) { - // 각 공연의 회차들 중 젤 마지막 회차 날짜 구하기 - Optional lastDate = show.getAmateurRounds().stream() - .map(r -> r.getPerformanceDateTime().toLocalDate()) // 회차 날짜만 추출 - .max(Comparator.naturalOrder()); // 젤 늦은 날짜 추출 + // Specification 조합: 승인된 공연 + 마지막 회차가 오늘인 공연 + Specification spec = Specification + .where(AmateurShowSpecification.isApproved()) + .and(AmateurShowSpecification.hasLastRoundOn(today)); - if (lastDate.isPresent() && lastDate.get().isEqual(today)) { // 마지막 회차 날짜가 오늘인 경우 - String schedule = AmateurConverter.mergeSchedule(show.getStart(), show.getEnd()); - - result.add(AmateurShowResponseDTO.AmateurShowList.builder() - .amateurShowId(show.getId()) - .name(show.getName()) - //.place(show.getPlace()) - .detailAddress(show.getDetailAddress()) - .schedule(schedule) - .posterImageUrl(show.getPosterImageUrl()) - .build()); - } - } - - return result; + List shows = amateurShowRepository.findAll(spec, Sort.by("start").ascending()); + // DTO 변환 + return shows.stream() + .map(show -> { + String schedule = AmateurConverter.mergeSchedule(show.getStart(), show.getEnd()); + return AmateurShowResponseDTO.AmateurShowList.builder() + .amateurShowId(show.getId()) + .name(show.getName()) + .detailAddress(show.getDetailAddress()) + .schedule(schedule) + .posterImageUrl(show.getPosterImageUrl()) + .build(); + }) + .collect(Collectors.toList()); } @Override @@ -651,11 +607,9 @@ public Slice getMyAmateurShow(Long } @Override - public List getRecentlyHotShow (Long memberId){ - memberRepository.findById(memberId).orElseThrow(()-> new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED)); - + public List getRecentlyHotShow (){ - // 종료되지 않은 공연 중, 마감이 얼마 안남은 3개 + // 종료되지 않은 공연 중, 마감이 얼마 안남은 3개 - specification 없이 바로 LocalDate today = LocalDate.now(); List shows = amateurShowRepository.findHotShows(today, PageRequest.of(0, 3)); diff --git a/src/main/java/cc/backend/photoAlbum/controller/PhotoAlbumController.java b/src/main/java/cc/backend/photoAlbum/controller/PhotoAlbumController.java index a3a3a65..9ddf7c4 100644 --- a/src/main/java/cc/backend/photoAlbum/controller/PhotoAlbumController.java +++ b/src/main/java/cc/backend/photoAlbum/controller/PhotoAlbumController.java @@ -29,6 +29,15 @@ public class PhotoAlbumController { private final PhotoAlbumService photoAlbumService; + @PreAuthorize("hasRole('PERFORMER')") + @GetMapping("/getMyShows") + @Operation(summary = "사진첩 등록/수정 시 연결할 내 공연 조회 API", description = "내가 등록한 공연 조회 API") + public ApiResponse> getMyShows( + @AuthenticationPrincipal(expression = "member") Member member) { + return ApiResponse.onSuccess(photoAlbumService.getMyShows(member.getId())); + } + + @GetMapping("/{photoAlbumId}") @Operation(summary = "사진첩 단건 조회 API", description = "공연별 사진첩을 단건 조회하는 API 입니다.") public ApiResponse getPhotoAlbum( @@ -66,6 +75,7 @@ public ApiResponse updatePhotoAlbum( return ApiResponse.onSuccess(photoAlbumService.updatePhotoAlbum(photoAlbumId,requestDTO, member.getId())); } + @PreAuthorize("hasRole('PERFORMER')") @DeleteMapping("/{photoAlbumId}") @Operation(summary = "사진첩 삭제 API", description = "공연별 사진첩을 삭제하는 API 입니다.") public ApiResponse deletePhotoAlbum( @@ -77,10 +87,9 @@ public ApiResponse deletePhotoAlbum( @GetMapping("") @Operation(summary = "메뉴에서 전체 사진첩 조회 API", description = "최근 올라온 사진첩을 전체 조회하는 API 입니다.") public ApiResponse getAllPhotoAlbum( - @AuthenticationPrincipal(expression = "member") Member member, @RequestParam(required = false) Long cursorId, @RequestParam(defaultValue = "20") int size) { - return ApiResponse.onSuccess(photoAlbumService.getAllRecentPhotoAlbumList(member.getId(), cursorId, size)); + return ApiResponse.onSuccess(photoAlbumService.getAllRecentPhotoAlbumList(cursorId, size)); } @GetMapping("/member/{memberId}/shows") diff --git a/src/main/java/cc/backend/photoAlbum/dto/PhotoAlbumResponseDTO.java b/src/main/java/cc/backend/photoAlbum/dto/PhotoAlbumResponseDTO.java index 39e5bb3..5167933 100644 --- a/src/main/java/cc/backend/photoAlbum/dto/PhotoAlbumResponseDTO.java +++ b/src/main/java/cc/backend/photoAlbum/dto/PhotoAlbumResponseDTO.java @@ -73,6 +73,15 @@ public static class ScrollMemberPhotoAlbumDTO { //커서 기반 private Long nextCursor; } + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class MyShowsForPhotoAlbumDTO { + private Long memberId; + private Long amateurShowId; + private String schedule; + } } diff --git a/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumService.java b/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumService.java index aff78cb..24ea1f9 100644 --- a/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumService.java +++ b/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumService.java @@ -17,6 +17,7 @@ public interface PhotoAlbumService { public Slice getPhotoAlbumList(Long memberId, Long performerId, Pageable pageable); public PhotoAlbumResponseDTO.PhotoAlbumResultDTO updatePhotoAlbum(Long photoAlbumId, PhotoAlbumRequestDTO.CreatePhotoAlbumDTO requestDTO, Long memberId); public String deletePhotoAlbum(Long photoAlbumId, Long memberId); - public PhotoAlbumResponseDTO.ScrollMemberPhotoAlbumDTO getAllRecentPhotoAlbumList(Long memberId, Long cursorId, int size); + public PhotoAlbumResponseDTO.ScrollMemberPhotoAlbumDTO getAllRecentPhotoAlbumList(Long cursorId, int size); public PerformerShowListResponseDTO getPerformerShows(Long memberId, Pageable pageable); + public List getMyShows(Long memberId); } diff --git a/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumServiceImpl.java b/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumServiceImpl.java index eab856b..7435dc6 100644 --- a/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumServiceImpl.java +++ b/src/main/java/cc/backend/photoAlbum/service/PhotoAlbumServiceImpl.java @@ -12,6 +12,7 @@ import cc.backend.image.repository.ImageRepository; import cc.backend.image.service.ImageService; import cc.backend.member.entity.Member; +import cc.backend.member.enumerate.Role; import cc.backend.member.repository.MemberRepository; import cc.backend.photoAlbum.dto.PerformerShowListResponseDTO; import cc.backend.photoAlbum.dto.PhotoAlbumRequestDTO; @@ -24,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -42,7 +44,6 @@ public class PhotoAlbumServiceImpl implements PhotoAlbumService { private final ImageRepository imageRepository; private final ImageService imageService; private final MemberRepository memberRepository; - private final S3Service s3Service; @Override @Transactional @@ -264,12 +265,9 @@ public String deletePhotoAlbum(Long photoAlbumId, Long memberId) { } @Override - public PhotoAlbumResponseDTO.ScrollMemberPhotoAlbumDTO getAllRecentPhotoAlbumList(Long memberId, Long cursorId, int size){ - - //로그인 검사 - memberRepository.findById(memberId) - .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED)); + public PhotoAlbumResponseDTO.ScrollMemberPhotoAlbumDTO getAllRecentPhotoAlbumList(Long cursorId, int size){ + //로그인 검사 X -> 방문자 첫화면 허용 // 다음 사진첩 조회 (cursor 기반, size + 1로 hasNext 판단) Pageable pageable = PageRequest.of(0, size + 1); @@ -367,4 +365,46 @@ private Map getFirstImage return result; } + @Override + public List getMyShows(Long memberId) { + + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND)); + + if(member.getRole() != Role.PERFORMER){ + throw new GeneralException(ErrorStatus.MEMBER_NOT_AUTHORIZED); + } + + List amateurShows = amateurShowRepository.findAllByMemberId(memberId); + + return amateurShows.stream() + .map(show->{ + String schedule = mergeScheduleWithoutDays(show.getStart(), show.getEnd()); + return PhotoAlbumResponseDTO.MyShowsForPhotoAlbumDTO.builder() + .amateurShowId(show.getId()) + .memberId(memberId) + .schedule(schedule) + .build(); + }) + .collect(Collectors.toList()); + } + + private static String mergeScheduleWithoutDays(LocalDate start, LocalDate end) { + try { + if (start == null || end == null) { + return ""; + } + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd"); + + String startStr = start.format(formatter); + String endStr = end.format(formatter); + + // 최종 결과: "2025.10.02~2025.10.05" + return startStr + "~" + endStr; + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } }