From dd3c1f45c833694ae9c1de0d2ac3c8b09817abd0 Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 15 Apr 2024 20:24:50 +0900 Subject: [PATCH 1/2] =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20-=20=EC=8B=9C?= =?UTF-8?q?=EB=A6=AC=EC=A6=88=20=EC=9E=A5=EB=A5=B4=20=EB=93=B1=EB=A1=9D,?= =?UTF-8?q?=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20API=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 크리에이터 관리자 - 시리즈 장르 조회 API 추가 --- .../AdminContentSeriesGenreController.kt | 30 ++++++++++++ .../AdminContentSeriesGenreRepository.kt | 9 ++++ .../genre/AdminContentSeriesGenreService.kt | 49 +++++++++++++++++++ .../series/genre/CreateSeriesGenreRequest.kt | 3 ++ .../series/genre/ModifySeriesGenreRequest.kt | 5 ++ .../admin/content/series/genre/SeriesGenre.kt | 17 +++++++ .../creator/admin/content/series/Series.kt | 42 ++++++++++++++++ ...reatorAdminContentSeriesGenreController.kt | 24 +++++++++ ...reatorAdminContentSeriesGenreRepository.kt | 32 ++++++++++++ .../CreatorAdminContentSeriesGenreService.kt | 10 ++++ .../series/genre/GetGenreListResponse.kt | 5 ++ .../content/series/keyword/SeriesKeyword.kt | 22 +++++++++ 12 files changed, 248 insertions(+) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreController.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreService.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/CreateSeriesGenreRequest.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/ModifySeriesGenreRequest.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/SeriesGenre.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreController.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreRepository.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreService.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/GetGenreListResponse.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/keyword/SeriesKeyword.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreController.kt new file mode 100644 index 0000000..b0dd061 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreController.kt @@ -0,0 +1,30 @@ +package kr.co.vividnext.sodalive.admin.content.series.genre + +import kr.co.vividnext.sodalive.common.ApiResponse +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestBody +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@PreAuthorize("hasRole('ADMIN')") +@RequestMapping("/admin/audio-content/series/genre") +class AdminContentSeriesGenreController(private val service: AdminContentSeriesGenreService) { + @PostMapping + fun createSeriesGenre(@RequestBody request: CreateSeriesGenreRequest) = + ApiResponse.ok(service.createSeriesGenre(genre = request.genre), "생성되었습니다.") + + @PutMapping + fun modifySeriesGenre(@RequestBody request: ModifySeriesGenreRequest) = ApiResponse.ok( + service.modifySeriesGenre(request = request), + "수정되었습니다." + ) + + @PutMapping("/orders") + fun modifySeriesGenreOrders(@RequestBody request: ModifySeriesGenreOrderRequest) = ApiResponse.ok( + service.modifySeriesGenreOrders(ids = request.ids), + "수정되었습니다." + ) +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreRepository.kt new file mode 100644 index 0000000..b91ffa5 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreRepository.kt @@ -0,0 +1,9 @@ +package kr.co.vividnext.sodalive.admin.content.series.genre + +import org.springframework.data.jpa.repository.JpaRepository + +interface AdminContentSeriesGenreRepository : JpaRepository, AdminContentSeriesGenreQueryRepository + +interface AdminContentSeriesGenreQueryRepository + +class AdminContentSeriesGenreQueryRepositoryImpl : AdminContentSeriesGenreQueryRepository diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreService.kt new file mode 100644 index 0000000..058b782 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/AdminContentSeriesGenreService.kt @@ -0,0 +1,49 @@ +package kr.co.vividnext.sodalive.admin.content.series.genre + +import kr.co.vividnext.sodalive.common.SodaException +import org.springframework.data.repository.findByIdOrNull +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional + +@Service +class AdminContentSeriesGenreService(private val repository: AdminContentSeriesGenreRepository) { + + @Transactional + fun createSeriesGenre(genre: String) { + val seriesGenre = SeriesGenre(genre = genre.trim()) + repository.save(seriesGenre) + } + + @Transactional + fun modifySeriesGenre(request: ModifySeriesGenreRequest) { + if (request.genre == null && request.isAdult == null && request.isActive == null) { + throw SodaException("변경사항이 없습니다.") + } + + val seriesGenre = repository.findByIdOrNull(id = request.id) + ?: throw SodaException("잘못된 요청입니다.") + + if (request.genre != null) { + seriesGenre.genre = request.genre + } + + if (request.isAdult != null) { + seriesGenre.isAdult = request.isAdult + } + + if (request.isActive != null) { + seriesGenre.isActive = request.isActive + } + } + + @Transactional + fun modifySeriesGenreOrders(ids: List) { + for (index in ids.indices) { + val seriesGenre = repository.findByIdOrNull(ids[index]) + + if (seriesGenre != null) { + seriesGenre.orders = index + 1 + } + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/CreateSeriesGenreRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/CreateSeriesGenreRequest.kt new file mode 100644 index 0000000..8852125 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/CreateSeriesGenreRequest.kt @@ -0,0 +1,3 @@ +package kr.co.vividnext.sodalive.admin.content.series.genre + +data class CreateSeriesGenreRequest(val genre: String, val isAdult: Boolean) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/ModifySeriesGenreRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/ModifySeriesGenreRequest.kt new file mode 100644 index 0000000..a9f2121 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/ModifySeriesGenreRequest.kt @@ -0,0 +1,5 @@ +package kr.co.vividnext.sodalive.admin.content.series.genre + +data class ModifySeriesGenreRequest(val id: Long, val genre: String?, val isAdult: Boolean?, val isActive: Boolean?) + +data class ModifySeriesGenreOrderRequest(val ids: List) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/SeriesGenre.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/SeriesGenre.kt new file mode 100644 index 0000000..ec87c95 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/content/series/genre/SeriesGenre.kt @@ -0,0 +1,17 @@ +package kr.co.vividnext.sodalive.admin.content.series.genre + +import kr.co.vividnext.sodalive.common.BaseEntity +import javax.persistence.Column +import javax.persistence.Entity + +@Entity +data class SeriesGenre( + @Column(nullable = false) + var genre: String, + @Column(nullable = false) + var isAdult: Boolean = false, + @Column(nullable = false) + var isActive: Boolean = true, + @Column(nullable = false) + var orders: Int = 1 +) : BaseEntity() diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt new file mode 100644 index 0000000..b8c7521 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/Series.kt @@ -0,0 +1,42 @@ +package kr.co.vividnext.sodalive.creator.admin.content.series + +import kr.co.vividnext.sodalive.admin.content.series.genre.SeriesGenre +import kr.co.vividnext.sodalive.common.BaseEntity +import javax.persistence.CollectionTable +import javax.persistence.Column +import javax.persistence.ElementCollection +import javax.persistence.Entity +import javax.persistence.EnumType +import javax.persistence.Enumerated +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.OneToOne + +enum class SeriesPublishedDaysOfWeek { + SUN, MON, TUE, WED, THU, FRI, SAT, RANDOM +} + +enum class SeriesState { + PROCEEDING, SUSPEND, COMPLETE +} + +@Entity +data class Series( + var title: String, + @Column(columnDefinition = "TEXT", nullable = false) + var introduction: String, + @Enumerated(value = EnumType.STRING) + var state: SeriesState = SeriesState.PROCEEDING, + @ElementCollection(targetClass = SeriesPublishedDaysOfWeek::class, fetch = FetchType.EAGER) + @Enumerated(value = EnumType.STRING) + @CollectionTable(name = "series_published_days_of_week", joinColumns = [JoinColumn(name = "series_id")]) + val publishedDaysOfWeek: Set = mutableSetOf(), + var isAdult: Boolean = false, + var isActive: Boolean = true +) : BaseEntity() { + @OneToOne(fetch = FetchType.EAGER) + @JoinColumn(name = "genre_id", nullable = false) + var genre: SeriesGenre? = null + + var coverImage: String? = null +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreController.kt new file mode 100644 index 0000000..48004c5 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreController.kt @@ -0,0 +1,24 @@ +package kr.co.vividnext.sodalive.creator.admin.content.series.genre + +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.member.Member +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@PreAuthorize("hasRole('CREATOR')") +@RequestMapping("/creator-admin/audio-content/series/genre") +class CreatorAdminContentSeriesGenreController(private val service: CreatorAdminContentSeriesGenreService) { + @GetMapping + fun getGenreList( + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok(service.getGenreList(isAdult = member.auth != null)) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreRepository.kt new file mode 100644 index 0000000..e35112d --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreRepository.kt @@ -0,0 +1,32 @@ +package kr.co.vividnext.sodalive.creator.admin.content.series.genre + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.admin.content.series.genre.QSeriesGenre.seriesGenre +import kr.co.vividnext.sodalive.admin.content.series.genre.SeriesGenre +import org.springframework.data.jpa.repository.JpaRepository + +interface CreatorAdminContentSeriesGenreRepository : + JpaRepository, CreatorAdminContentSeriesGenreQueryRepository + +interface CreatorAdminContentSeriesGenreQueryRepository { + fun getGenreList(isAdult: Boolean): List +} + +class CreatorAdminContentSeriesGenreQueryRepositoryImpl( + private val queryFactory: JPAQueryFactory +) : CreatorAdminContentSeriesGenreQueryRepository { + override fun getGenreList(isAdult: Boolean): List { + var where = seriesGenre.isActive.isTrue + + if (!isAdult) { + where = where.and(seriesGenre.isAdult.isFalse) + } + + return queryFactory + .select(QGetGenreListResponse(seriesGenre.id, seriesGenre.genre)) + .from(seriesGenre) + .where(where) + .orderBy(seriesGenre.orders.asc()) + .fetch() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreService.kt new file mode 100644 index 0000000..d16a700 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/CreatorAdminContentSeriesGenreService.kt @@ -0,0 +1,10 @@ +package kr.co.vividnext.sodalive.creator.admin.content.series.genre + +import org.springframework.stereotype.Service + +@Service +class CreatorAdminContentSeriesGenreService(private val repository: CreatorAdminContentSeriesGenreRepository) { + fun getGenreList(isAdult: Boolean): List { + return repository.getGenreList(isAdult = isAdult) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/GetGenreListResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/GetGenreListResponse.kt new file mode 100644 index 0000000..cf986c7 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/genre/GetGenreListResponse.kt @@ -0,0 +1,5 @@ +package kr.co.vividnext.sodalive.creator.admin.content.series.genre + +import com.querydsl.core.annotations.QueryProjection + +data class GetGenreListResponse @QueryProjection constructor(val id: Long, val genre: String) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/keyword/SeriesKeyword.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/keyword/SeriesKeyword.kt new file mode 100644 index 0000000..32d90dd --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/content/series/keyword/SeriesKeyword.kt @@ -0,0 +1,22 @@ +package kr.co.vividnext.sodalive.creator.admin.content.series.keyword + +import kr.co.vividnext.sodalive.common.BaseEntity +import kr.co.vividnext.sodalive.content.hashtag.HashTag +import kr.co.vividnext.sodalive.creator.admin.content.series.Series +import javax.persistence.Entity +import javax.persistence.FetchType +import javax.persistence.JoinColumn +import javax.persistence.ManyToOne + +@Entity +class SeriesKeyword : BaseEntity() { + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "series_id", nullable = false) + var series: Series? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "keyword_id", nullable = false) + var keyword: HashTag? = null + + var isActive: Boolean = true +} -- 2.40.1 From c40220f76622c713b744c43153b797c49c156d4b Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 15 Apr 2024 21:24:39 +0900 Subject: [PATCH 2/2] =?UTF-8?q?=EC=95=88=EB=93=9C=EB=A1=9C=EC=9D=B4?= =?UTF-8?q?=EB=93=9C=20=EC=9D=B8=20=EC=95=B1=20=EA=B2=B0=EC=A0=9C=20-=20?= =?UTF-8?q?=EB=B0=A9=EC=96=B4=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sodalive/can/charge/ChargeService.kt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt index 4f3b017..31e9310 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/can/charge/ChargeService.kt @@ -269,10 +269,21 @@ class ChargeService( productId, purchaseToken ) - charge.payment!!.status = PaymentStatus.COMPLETE - member.charge(charge.chargeCan, 0, "aos") - return true + val response = androidPublisher.purchases().products() + .get("kr.co.vividnext.sodalive", productId, purchaseToken) + .execute() ?: throw SodaException("결제정보에 오류가 있습니다.") + + if (response.consumptionState == 1) { + charge.payment!!.status = PaymentStatus.COMPLETE + member.charge(charge.chargeCan, 0, "aos") + + return true + } else { + attempt += 1 + Thread.sleep(delay) + delay *= 2 + } } catch (e: Exception) { lastError = e attempt += 1 @@ -280,6 +291,7 @@ class ChargeService( delay *= 2 } } + lastError?.printStackTrace() return false } -- 2.40.1