From f7626317e06341f9e2e2e48d17cfc86002b4759f Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Fri, 12 Dec 2025 20:57:55 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=EA=B3=B5=EC=97=B0=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20/=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=ED=95=B4=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConcertController.java | 29 +++++++++++++++---- .../domain/concerts/entity/ConcertLike.java | 5 ++++ .../repository/ConcertLikeRepository.java | 3 ++ .../concerts/service/ConcertService.java | 24 +++++++++++++++ 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java index 5459d2f6..1012de2a 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java @@ -19,10 +19,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -55,7 +52,7 @@ public ConcertPlaceListResponse setConcertPlace() throws InterruptedException { public RsData> getList ( @RequestParam @Schema(description = "page입니다. 일단은 ?page={page} 로 넘기시면 됩니다.", example = "1") - int page + int page // todo : pageable로 변경하기 ) { Pageable pageable = PageRequest.of(page, 10, Sort.by("startDate").ascending()); return RsData.success(concertService.getConcertsList(pageable)); @@ -66,7 +63,7 @@ public RsData> getList ( public RsData> getUpComingList ( @RequestParam @Schema(description = "page입니다. 일단은 ?page={page} 로 넘기시면 됩니다.", example = "1") - int page + int page // todo : pageable로 변경하기 ) { Pageable pageable = PageRequest.of(page, 10); return RsData.success(concertService.getUpcomingConcertsList(pageable)); @@ -92,4 +89,24 @@ public RsData> getTicketOffices ( return RsData.success(concertService.getTicketOfficesList(concertId)); } + @Operation(summary = "공연 좋아요 기능") + @PostMapping("like/{concertId}") + public RsData likeConcert( + @PathVariable long concertId, + @RequestParam long userId // todo: 사용자 Id 조회법 통일하기 + ) { + concertService.likeConcert(concertId, userId); + return RsData.success(null); + } + + @Operation(summary = "공연 좋아요 해제 기능") + @DeleteMapping("dislike/{concertId}") + public RsData dislikeConcert( + @PathVariable long concertId, + @RequestParam long userId // todo: 사용자 Id 조회법 통일하기 + ) { + concertService.dislikeConcert(concertId, userId); + return RsData.success(null); + } + } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java index fbdb9267..3e179801 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java @@ -20,4 +20,9 @@ public class ConcertLike { @ManyToOne private User user; + + public ConcertLike(Concert concert, User user) { + this.concert = concert; + this.user = user; + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java index 928be3c3..cb192534 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java @@ -1,10 +1,13 @@ package com.back.web7_9_codecrete_be.domain.concerts.repository; +import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert; import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertLike; +import com.back.web7_9_codecrete_be.domain.users.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ConcertLikeRepository extends JpaRepository { + ConcertLike findConcertLikeByConcertAndUser(Concert concert, User user); } 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 80b0c172..c67811ec 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 @@ -4,10 +4,17 @@ import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertItem; import com.back.web7_9_codecrete_be.domain.concerts.dto.ticketOffice.TicketOfficeElement; import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert; +import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertLike; import com.back.web7_9_codecrete_be.domain.concerts.entity.TicketOffice; +import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertLikeRepository; import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertPlaceRepository; import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertRepository; import com.back.web7_9_codecrete_be.domain.concerts.repository.TicketOfficeRepository; +import com.back.web7_9_codecrete_be.domain.users.entity.User; +import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository; +import com.back.web7_9_codecrete_be.global.error.code.AuthErrorCode; +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 org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; @@ -21,10 +28,14 @@ public class ConcertService { private final ConcertRepository concertRepository; + private final ConcertLikeRepository concertLikeRepository; + private final ConcertPlaceRepository concertPlaceRepository; private final TicketOfficeRepository ticketOfficeRepository; + private final UserRepository userRepository; + public List getConcertsList(Pageable pageable) { return concertRepository.getConcertItems(pageable); } @@ -61,4 +72,17 @@ public List getTicketOfficesList(long concertId) { } + public void likeConcert(long concertId, long userId) { + User user = userRepository.findById(userId).orElseThrow(); + Concert concert = concertRepository.findById(concertId).orElseThrow(); + ConcertLike concertLike = new ConcertLike(concert, user); + concertLikeRepository.save(concertLike); + } + + public void dislikeConcert(long concertId, long userId) { + User user = userRepository.findById(userId).orElseThrow(); + Concert concert = concertRepository.findById(concertId).orElseThrow(); + ConcertLike concertLike = concertLikeRepository.findConcertLikeByConcertAndUser(concert, user); + concertLikeRepository.delete(concertLike); + } } From 9aca865c7596404fcd9062710dbd2d6cc6f34f0b Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Sun, 14 Dec 2025 10:04:29 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20AdminController=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20=EA=B3=B5=EC=97=B0=20=EA=B0=B1=EC=8B=A0=EC=9A=A9?= =?UTF-8?q?=20dto=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConcertAdminController.java | 37 +++++++++++++++++++ .../controller/ConcertController.java | 16 -------- .../dto/concert/ConcertUpdateRequest.java | 19 ++++++++++ 3 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java new file mode 100644 index 00000000..b051048a --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java @@ -0,0 +1,37 @@ +package com.back.web7_9_codecrete_be.domain.concerts.controller; + +import com.back.web7_9_codecrete_be.domain.concerts.dto.KopisApiDto.concert.ConcertListResponse; +import com.back.web7_9_codecrete_be.domain.concerts.dto.KopisApiDto.concertPlace.ConcertPlaceListResponse; +import com.back.web7_9_codecrete_be.domain.concerts.service.KopisApiService; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/admin/concerts/") +@Tag(name = "Concerts Admin", description = "공연에 대해서 관리하는 API입니다. ") +public class ConcertAdminController { + private final KopisApiService kopisApiService; + + @GetMapping("tests") + public ConcertListResponse tests() { + return kopisApiService.getConcertsList(); + } + + @GetMapping("totalGetTest") + public ConcertListResponse totalGetTest() throws InterruptedException { + return kopisApiService.setConcertsList(); + } + + @GetMapping("setConcertPlace") + public ConcertPlaceListResponse setConcertPlace() throws InterruptedException { + return kopisApiService.setConcertPlace(); + } + + +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java index 1012de2a..87277344 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java @@ -30,22 +30,6 @@ @Tag(name = "Concerts", description = "공연에 대한 정보를 제공하는 API 입니다.") public class ConcertController { private final ConcertService concertService; - private final KopisApiService kopisApiService; - - @GetMapping("tests") - public ConcertListResponse tests() { - return kopisApiService.getConcertsList(); - } - - @GetMapping("totalGetTest") - public ConcertListResponse totalGetTest() throws InterruptedException { - return kopisApiService.setConcertsList(); - } - - @GetMapping("setConcertPlace") - public ConcertPlaceListResponse setConcertPlace() throws InterruptedException { - return kopisApiService.setConcertPlace(); - } @Operation(summary = "공연목록", description = "공연 전체 목록을 조회합니다. 시작일자를 기준으로 오름차순 조회합니다.") @GetMapping("list") diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java new file mode 100644 index 00000000..4b1df11e --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java @@ -0,0 +1,19 @@ +package com.back.web7_9_codecrete_be.domain.concerts.dto.concert; + +import lombok.Getter; + +import java.time.LocalDate; + +@Getter +public class ConcertUpdateRequest { + private Long concertId; + private String name; + private String description; + private Long placeId; + private LocalDate StartDate; + private LocalDate EndDate; + private String posterUrl; + private int maxPrice; + private int minPrice; + +} From 52db2918cb25e753232ed628d22154bfb9697056 Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Sun, 14 Dec 2025 20:31:19 +0900 Subject: [PATCH 3/7] =?UTF-8?q?feat:=20=EA=B3=B5=EC=97=B0=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConcertAdminController.java | 25 +++++++++++++++---- .../dto/concert/ConcertUpdateRequest.java | 1 - .../domain/concerts/entity/Concert.java | 15 +++++++++++ .../concerts/service/ConcertService.java | 20 +++++++++++++-- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java index b051048a..6b1eeebf 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertAdminController.java @@ -2,20 +2,22 @@ import com.back.web7_9_codecrete_be.domain.concerts.dto.KopisApiDto.concert.ConcertListResponse; import com.back.web7_9_codecrete_be.domain.concerts.dto.KopisApiDto.concertPlace.ConcertPlaceListResponse; +import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertItem; +import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertUpdateRequest; +import com.back.web7_9_codecrete_be.domain.concerts.service.ConcertService; import com.back.web7_9_codecrete_be.domain.concerts.service.KopisApiService; +import com.back.web7_9_codecrete_be.global.rsData.RsData; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/admin/concerts/") @Tag(name = "Concerts Admin", description = "공연에 대해서 관리하는 API입니다. ") -public class ConcertAdminController { +public class ConcertAdminController { // todo : 인증 권한 추가하기 + private final ConcertService concertService; private final KopisApiService kopisApiService; @GetMapping("tests") @@ -33,5 +35,18 @@ public ConcertPlaceListResponse setConcertPlace() throws InterruptedException { return kopisApiService.setConcertPlace(); } + @PatchMapping("updateConcert/{concertId}") + public RsData updateConcert( + @PathVariable Long concertId, + @RequestBody ConcertUpdateRequest concertUpdateRequest + ){ + ConcertItem concertItem = concertService.updateConcert(concertId, concertUpdateRequest); + return RsData.success("공연 정보 수정이 완료되었습니다.",concertItem); + } + @DeleteMapping("deleteConcert/{concertId}") + public RsData deleteConcert(@PathVariable Long concertId){ + concertService.deleteConcert(concertId); + return RsData.success("공연 정보 삭제에 성공하였습니다.",null); + } } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java index 4b1df11e..69d61b9b 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertUpdateRequest.java @@ -15,5 +15,4 @@ public class ConcertUpdateRequest { private String posterUrl; private int maxPrice; private int minPrice; - } 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 b3e6ecde..36733a36 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 @@ -1,5 +1,6 @@ package com.back.web7_9_codecrete_be.domain.concerts.entity; +import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertUpdateRequest; import jakarta.persistence.*; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -90,4 +91,18 @@ public Concert update(ConcertPlace concertPlace, String content, String ticketTi return this; } + + public Concert update(ConcertUpdateRequest concertUpdateRequest,ConcertPlace concertPlace) { + this.name = concertUpdateRequest.getName(); + this.concertPlace = concertPlace; + this.content = concertUpdateRequest.getDescription(); + this.maxPrice = concertUpdateRequest.getMaxPrice(); + this.minPrice = concertUpdateRequest.getMinPrice(); + this.posterUrl = concertUpdateRequest.getPosterUrl(); + this.startDate = concertUpdateRequest.getStartDate(); + this.endDate = concertUpdateRequest.getEndDate(); + this.modifiedDate = LocalDateTime.now(); + return this; + } + } 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 c67811ec..cdb4cc04 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 @@ -2,9 +2,11 @@ import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertDetailResponse; import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertItem; +import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertUpdateRequest; import com.back.web7_9_codecrete_be.domain.concerts.dto.ticketOffice.TicketOfficeElement; import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert; import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertLike; +import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertPlace; import com.back.web7_9_codecrete_be.domain.concerts.entity.TicketOffice; import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertLikeRepository; import com.back.web7_9_codecrete_be.domain.concerts.repository.ConcertPlaceRepository; @@ -41,8 +43,7 @@ public List getConcertsList(Pageable pageable) { } public List getUpcomingConcertsList(Pageable pageable) { - LocalDate today = LocalDate.now(); - return concertRepository.getUpComingConcertItems(pageable, today); + return concertRepository.getUpComingConcertItems(pageable, LocalDate.now()); } public ConcertDetailResponse getConcertDetail(long concertId) { @@ -85,4 +86,19 @@ public void dislikeConcert(long concertId, long userId) { ConcertLike concertLike = concertLikeRepository.findConcertLikeByConcertAndUser(concert, user); concertLikeRepository.delete(concertLike); } + + public ConcertItem updateConcert(long concertId, ConcertUpdateRequest concertUpdateRequest) { + Concert concert = concertRepository.findById(concertId).orElseThrow(); + ConcertPlace concertPlace = concertPlaceRepository.findById(concertUpdateRequest.getPlaceId()).orElseThrow(); + concert.update(concertUpdateRequest, concertPlace); + Concert updatedConcert = concertRepository.save(concert); + return new ConcertItem(updatedConcert); + } + + public void deleteConcert(long concertId) { + Concert concert = concertRepository.findById(concertId).orElseThrow(); + concertRepository.deleteById(concertId); + } + + } From 74a81b1ada347d70cd6760c3542648ae6cb7a666 Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Mon, 15 Dec 2025 11:04:35 +0900 Subject: [PATCH 4/7] =?UTF-8?q?feat=20:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConcertController.java | 25 ++++++++++++++----- .../repository/ConcertLikeRepository.java | 2 ++ .../repository/ConcertRepository.java | 2 ++ .../concerts/service/ConcertService.java | 11 +++++--- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java index 87277344..db46b02d 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java @@ -8,6 +8,8 @@ import com.back.web7_9_codecrete_be.domain.concerts.entity.TicketOffice; import com.back.web7_9_codecrete_be.domain.concerts.service.ConcertService; import com.back.web7_9_codecrete_be.domain.concerts.service.KopisApiService; +import com.back.web7_9_codecrete_be.domain.users.entity.User; +import com.back.web7_9_codecrete_be.global.rq.Rq; import com.back.web7_9_codecrete_be.global.rsData.RsData; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Schema; @@ -30,6 +32,7 @@ @Tag(name = "Concerts", description = "공연에 대한 정보를 제공하는 API 입니다.") public class ConcertController { private final ConcertService concertService; + private final Rq rq; @Operation(summary = "공연목록", description = "공연 전체 목록을 조회합니다. 시작일자를 기준으로 오름차순 조회합니다.") @GetMapping("list") @@ -76,21 +79,31 @@ public RsData> getTicketOffices ( @Operation(summary = "공연 좋아요 기능") @PostMapping("like/{concertId}") public RsData likeConcert( - @PathVariable long concertId, - @RequestParam long userId // todo: 사용자 Id 조회법 통일하기 + @PathVariable long concertId ) { - concertService.likeConcert(concertId, userId); + User user = rq.getUser(); + concertService.likeConcert(concertId, user); return RsData.success(null); } @Operation(summary = "공연 좋아요 해제 기능") @DeleteMapping("dislike/{concertId}") public RsData dislikeConcert( - @PathVariable long concertId, - @RequestParam long userId // todo: 사용자 Id 조회법 통일하기 + @PathVariable long concertId ) { - concertService.dislikeConcert(concertId, userId); + User user = rq.getUser(); + concertService.dislikeConcert(concertId, user); return RsData.success(null); } + @Operation(summary = "공연 좋아요 여부 확인") + @GetMapping("isLike/{concertId}") + public RsData isLikeConcert( + @PathVariable long concertId + ){ + User user = rq.getUser(); + return RsData.success(concertService.isLikeConcert(concertId, user)); + } + + } diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java index cb192534..9da937a2 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java @@ -9,5 +9,7 @@ @Repository public interface ConcertLikeRepository extends JpaRepository { ConcertLike findConcertLikeByConcertAndUser(Concert concert, User user); + + ConcertLike existsConcertLikeByConcertAndUser(Concert concert, User user); } 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 74454d26..db1a5b3b 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 @@ -86,4 +86,6 @@ List getUpComingConcertItems( c.concertId = :concertId """) ConcertDetailResponse getConcertDetailById(@Param("concertId")long concertId); + + Concert getConcertByConcertId(Long concertId); } 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 cdb4cc04..dd3d7e04 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 @@ -72,16 +72,19 @@ public List getTicketOfficesList(long concertId) { return ticketOfficeList; } + public boolean isLikeConcert(Long concertId,User user) { + Concert concert = concertRepository.getConcertByConcertId(concertId); + ConcertLike concertLike = concertLikeRepository.existsConcertLikeByConcertAndUser(concert,user); + return concertLike != null; + } - public void likeConcert(long concertId, long userId) { - User user = userRepository.findById(userId).orElseThrow(); + public void likeConcert(long concertId, User user) { Concert concert = concertRepository.findById(concertId).orElseThrow(); ConcertLike concertLike = new ConcertLike(concert, user); concertLikeRepository.save(concertLike); } - public void dislikeConcert(long concertId, long userId) { - User user = userRepository.findById(userId).orElseThrow(); + public void dislikeConcert(long concertId, User user) { Concert concert = concertRepository.findById(concertId).orElseThrow(); ConcertLike concertLike = concertLikeRepository.findConcertLikeByConcertAndUser(concert, user); concertLikeRepository.delete(concertLike); From fc724cfe1c961a149163780d2e26dfb0817969e0 Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Mon, 15 Dec 2025 12:17:02 +0900 Subject: [PATCH 5/7] =?UTF-8?q?feat=20:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=20=EC=9E=85=EB=A0=A5=EC=8B=9C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC,=20=EC=A2=8B=EC=95=84=EC=9A=94?= =?UTF-8?q?=20=EC=95=88=ED=95=9C=20=EB=8C=80=EC=83=81=EC=97=90=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=ED=95=B4=EC=A0=9C=20=EC=8B=9C=20=EC=98=88?= =?UTF-8?q?=EC=99=B8=20=EC=B2=98=EB=A6=AC,=20=EC=A2=8B=EC=95=84=EC=9A=94?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20DTO=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConcertController.java | 3 ++- .../dto/concert/ConcertLikeResponse.java | 16 ++++++++++++++ .../repository/ConcertLikeRepository.java | 2 +- .../concerts/service/ConcertService.java | 21 ++++++++++++++++--- .../global/error/code/ConcertErrorCode.java | 18 ++++++++++++++++ 5 files changed, 55 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertLikeResponse.java create mode 100644 src/main/java/com/back/web7_9_codecrete_be/global/error/code/ConcertErrorCode.java diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java index db46b02d..b2402f74 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java @@ -4,6 +4,7 @@ import com.back.web7_9_codecrete_be.domain.concerts.dto.KopisApiDto.concertPlace.ConcertPlaceListResponse; import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertDetailResponse; import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertItem; +import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertLikeResponse; import com.back.web7_9_codecrete_be.domain.concerts.dto.ticketOffice.TicketOfficeElement; import com.back.web7_9_codecrete_be.domain.concerts.entity.TicketOffice; import com.back.web7_9_codecrete_be.domain.concerts.service.ConcertService; @@ -98,7 +99,7 @@ public RsData dislikeConcert( @Operation(summary = "공연 좋아요 여부 확인") @GetMapping("isLike/{concertId}") - public RsData isLikeConcert( + public RsData isLikeConcert( @PathVariable long concertId ){ User user = rq.getUser(); diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertLikeResponse.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertLikeResponse.java new file mode 100644 index 00000000..919e6f5d --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/dto/concert/ConcertLikeResponse.java @@ -0,0 +1,16 @@ +package com.back.web7_9_codecrete_be.domain.concerts.dto.concert; + +import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert; +import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertLike; +import lombok.Getter; + +@Getter +public class ConcertLikeResponse { + private Long concertId; + private Boolean isLike; + + public ConcertLikeResponse(Concert concert, Boolean isLike) { + this.concertId = concert.getConcertId(); + this.isLike = isLike; + } +} diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java index 9da937a2..0f616737 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/repository/ConcertLikeRepository.java @@ -10,6 +10,6 @@ public interface ConcertLikeRepository extends JpaRepository { ConcertLike findConcertLikeByConcertAndUser(Concert concert, User user); - ConcertLike existsConcertLikeByConcertAndUser(Concert concert, User user); + boolean existsConcertLikeByConcertAndUser(Concert concert, User user); } 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 dd3d7e04..f922e0b3 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 @@ -2,6 +2,7 @@ import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertDetailResponse; import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertItem; +import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertLikeResponse; import com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertUpdateRequest; import com.back.web7_9_codecrete_be.domain.concerts.dto.ticketOffice.TicketOfficeElement; import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert; @@ -15,10 +16,12 @@ import com.back.web7_9_codecrete_be.domain.users.entity.User; import com.back.web7_9_codecrete_be.domain.users.repository.UserRepository; import com.back.web7_9_codecrete_be.global.error.code.AuthErrorCode; +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 org.springframework.data.domain.Pageable; +import org.springframework.security.core.parameters.P; import org.springframework.stereotype.Service; import java.time.LocalDate; @@ -72,14 +75,23 @@ public List getTicketOfficesList(long concertId) { return ticketOfficeList; } - public boolean isLikeConcert(Long concertId,User user) { + public ConcertLikeResponse isLikeConcert(Long concertId, User user) { Concert concert = concertRepository.getConcertByConcertId(concertId); - ConcertLike concertLike = concertLikeRepository.existsConcertLikeByConcertAndUser(concert,user); - return concertLike != null; + ConcertLikeResponse concertLikeResponse; + if(concertLikeRepository.existsConcertLikeByConcertAndUser(concert,user)){ + concertLikeResponse = new ConcertLikeResponse(concert,true); + } else { + concertLikeResponse = new ConcertLikeResponse(concert,false); + } + + return concertLikeResponse; } public void likeConcert(long concertId, User user) { Concert concert = concertRepository.findById(concertId).orElseThrow(); + if(concertLikeRepository.existsConcertLikeByConcertAndUser(concert,user)){ + throw new BusinessException(ConcertErrorCode.LIKE_CONFLICT); + } ConcertLike concertLike = new ConcertLike(concert, user); concertLikeRepository.save(concertLike); } @@ -87,6 +99,9 @@ public void likeConcert(long concertId, User user) { public void dislikeConcert(long concertId, User user) { Concert concert = concertRepository.findById(concertId).orElseThrow(); ConcertLike concertLike = concertLikeRepository.findConcertLikeByConcertAndUser(concert, user); + if(concertLike == null){ + throw new BusinessException(ConcertErrorCode.NOT_FOUND_CONCERTLIKE); + } concertLikeRepository.delete(concertLike); } 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 new file mode 100644 index 00000000..01b7bd8c --- /dev/null +++ b/src/main/java/com/back/web7_9_codecrete_be/global/error/code/ConcertErrorCode.java @@ -0,0 +1,18 @@ +package com.back.web7_9_codecrete_be.global.error.code; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum ConcertErrorCode implements ErrorCode { + + LIKE_CONFLICT(HttpStatus.CONFLICT,"C131","이미 좋아요를 누른 공연입니다."), + NOT_FOUND_CONCERTLIKE(HttpStatus.NOT_FOUND,"C130","좋아요를 누르지 않은 공연입니다.") + ; + + private final HttpStatus status; + private final String code; + private final String message; +} From 180cc1c46669b02f657b175f60f1f952cf750a6b Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Mon, 15 Dec 2025 12:43:32 +0900 Subject: [PATCH 6/7] =?UTF-8?q?feat:=20=EC=A2=8B=EC=95=84=EC=9A=94=20?= =?UTF-8?q?=ED=95=9C=20=EA=B3=B5=EC=97=B0=EC=9D=98=20=EB=AA=A9=EB=A1=9D=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ConcertController.java | 18 +++++++++-- .../domain/concerts/entity/ConcertLike.java | 10 ++++-- .../repository/ConcertRepository.java | 32 +++++++++++++++++++ .../concerts/service/ConcertService.java | 4 +++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java index b2402f74..bd6aad4e 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java @@ -57,6 +57,16 @@ public RsData> getUpComingList ( return RsData.success(concertService.getUpcomingConcertsList(pageable)); } + @Operation(summary = "좋아요 한 공연 조회", description = "좋아요를 누른 공연에 대한 목록을 조회합니다. 저장 날짜를 기준으로 내림차순 정렬로 표시합니다.(최신으로 추가된 목록순입니다.)") + @GetMapping("likedConcertList") + public RsData> getLikedConcertList ( + @RequestParam + Pageable pageable + ){ + User user = rq.getUser(); + return RsData.success(concertService.getLikedConcertsList(pageable,user)); + } + @Operation(summary = "공연 상세 조회", description = "공연에 대한 상세 목록을 조회합니다.") @GetMapping("concertDetail") public ConcertDetailResponse getConcertDetail( @@ -67,6 +77,8 @@ public ConcertDetailResponse getConcertDetail( return concertService.getConcertDetail(concertId); } + + @Operation(summary = "공연 예매처 조회", description = "공연에 대한 예매처들을 조회합니다.") @GetMapping("ticketOffices") public RsData> getTicketOffices ( @@ -77,7 +89,7 @@ public RsData> getTicketOffices ( return RsData.success(concertService.getTicketOfficesList(concertId)); } - @Operation(summary = "공연 좋아요 기능") + @Operation(summary = "공연 좋아요 기능", description = "사용자가 마음에 드는 공연에 대해 좋아요를 통해 저장할 수 있습니다.") @PostMapping("like/{concertId}") public RsData likeConcert( @PathVariable long concertId @@ -87,7 +99,7 @@ public RsData likeConcert( return RsData.success(null); } - @Operation(summary = "공연 좋아요 해제 기능") + @Operation(summary = "공연 좋아요 해제 기능", description = "좋아요를 해제할 수 있습니다.") @DeleteMapping("dislike/{concertId}") public RsData dislikeConcert( @PathVariable long concertId @@ -97,7 +109,7 @@ public RsData dislikeConcert( return RsData.success(null); } - @Operation(summary = "공연 좋아요 여부 확인") + @Operation(summary = "공연 좋아요 여부 확인", description = "좋아요 여부를 확인합니다.") @GetMapping("isLike/{concertId}") public RsData isLikeConcert( @PathVariable long concertId diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java index 3e179801..0d37d309 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/entity/ConcertLike.java @@ -4,6 +4,9 @@ import jakarta.persistence.*; import lombok.Getter; import lombok.RequiredArgsConstructor; +import org.hibernate.annotations.CreationTimestamp; + +import java.time.LocalDateTime; @Entity @Getter @@ -15,12 +18,15 @@ public class ConcertLike { @Column(name = "concert_like_id") private Long concertLikeId; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private Concert concert; - @ManyToOne + @ManyToOne(fetch = FetchType.LAZY) private User user; + @CreationTimestamp + private LocalDateTime createdAt; + public ConcertLike(Concert concert, User user) { this.concert = concert; this.user = user; 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 db1a5b3b..66c48830 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 @@ -5,6 +5,7 @@ import com.back.web7_9_codecrete_be.domain.concerts.entity.Concert; import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertPlace; import com.back.web7_9_codecrete_be.domain.concerts.entity.ConcertTime; +import com.back.web7_9_codecrete_be.domain.users.entity.User; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; @@ -65,6 +66,35 @@ List getUpComingConcertItems( @Param("fromDate") LocalDate fromDate ); + @Query(""" + SELECT + new com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertItem( + c.concertId as id, + c.name as name, + c.concertPlace.placeName as placeName, + c.startDate as startDate, + c.endDate as endDate, + c.posterUrl as posterUrl, + c.maxPrice as maxPrice, + c.minPrice as minPrice, + c.viewCount as viewCount, + c.likeCount as likeCount + ) + FROM + Concert c, + ConcertLike cl + WHERE + c.concertId = cl.concert.concertId + AND + cl.user.id = :userId + ORDER BY + cl.createdAt + DESC +""" + ) + List getLikedConcertsList(Pageable pageable, + @Param("userId") Long userId); + @Query(""" SELECT new com.back.web7_9_codecrete_be.domain.concerts.dto.concert.ConcertDetailResponse( @@ -87,5 +117,7 @@ List getUpComingConcertItems( """) ConcertDetailResponse getConcertDetailById(@Param("concertId")long concertId); + + Concert getConcertByConcertId(Long concertId); } 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 f922e0b3..7ac6f001 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 @@ -49,6 +49,10 @@ public List getUpcomingConcertsList(Pageable pageable) { return concertRepository.getUpComingConcertItems(pageable, LocalDate.now()); } + public List getLikedConcertsList(Pageable pageable,User user) { + return concertRepository.getLikedConcertsList(pageable, user.getId()); + } + public ConcertDetailResponse getConcertDetail(long concertId) { return concertRepository.getConcertDetailById(concertId); } From 8554f97f7ebd411e65022e8a7fe44786cbeae69c Mon Sep 17 00:00:00 2001 From: Creamcheesepie Date: Mon, 15 Dec 2025 12:48:59 +0900 Subject: [PATCH 7/7] =?UTF-8?q?feat:=20pageable=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../concerts/controller/ConcertController.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java index bd6aad4e..b28084d8 100644 --- a/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java +++ b/src/main/java/com/back/web7_9_codecrete_be/domain/concerts/controller/ConcertController.java @@ -38,29 +38,25 @@ public class ConcertController { @Operation(summary = "공연목록", description = "공연 전체 목록을 조회합니다. 시작일자를 기준으로 오름차순 조회합니다.") @GetMapping("list") public RsData> getList ( - @RequestParam - @Schema(description = "page입니다. 일단은 ?page={page} 로 넘기시면 됩니다.", example = "1") - int page // todo : pageable로 변경하기 + @Schema(description = "페이징 처리 또는 무한 스크롤 구현에 쓸 Pageable 객체입니다.") + Pageable pageable ) { - Pageable pageable = PageRequest.of(page, 10, Sort.by("startDate").ascending()); return RsData.success(concertService.getConcertsList(pageable)); } @Operation(summary = "다가오는 공연 목록", description = "오늘을 기준으로 다가오는 공연 목록을 조회합니다.") @GetMapping("upComingList") public RsData> getUpComingList ( - @RequestParam - @Schema(description = "page입니다. 일단은 ?page={page} 로 넘기시면 됩니다.", example = "1") - int page // todo : pageable로 변경하기 + @Schema(description = "페이징 처리 또는 무한 스크롤 구현에 쓸 Pageable 객체입니다.") + Pageable pageable ) { - Pageable pageable = PageRequest.of(page, 10); return RsData.success(concertService.getUpcomingConcertsList(pageable)); } @Operation(summary = "좋아요 한 공연 조회", description = "좋아요를 누른 공연에 대한 목록을 조회합니다. 저장 날짜를 기준으로 내림차순 정렬로 표시합니다.(최신으로 추가된 목록순입니다.)") @GetMapping("likedConcertList") public RsData> getLikedConcertList ( - @RequestParam + @Schema(description = "페이징 처리 또는 무한 스크롤 구현에 쓸 Pageable 객체입니다.") Pageable pageable ){ User user = rq.getUser();