From 1fb2a0214264daa1b592c7b4e8f60775595f89f4 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:43:12 +0900 Subject: [PATCH 01/15] =?UTF-8?q?fix:=20=EC=83=88=EB=A1=9C=EC=9A=B4=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85=EC=9D=B4=20=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecase/SubscribeWorkbookUseCase.kt | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt b/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt index b93e6947b..f91c76c4e 100644 --- a/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt +++ b/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt @@ -28,27 +28,35 @@ class SubscribeWorkbookUseCase( ) val subTargetWorkbookId = useCaseIn.workbookId + val command = InsertWorkbookSubscriptionCommand( + memberId = memberId, + workbookId = subTargetWorkbookId + ) + + /** 구독 히스토리가 있는지 확인 */ SelectAllWorkbookSubscriptionStatusQueryNotConsiderDeletedAt(memberId = memberId, workbookId = subTargetWorkbookId).let { query -> subscriptionDao.selectAllWorkbookSubscriptionStatus(query).let { subscriptionStatusList -> + /** 이미 구독한 경우가 있는 경우 */ if (subscriptionStatusList.isNotEmpty()) { subscriptionStatusList.stream().filter { status -> status.id == query.workbookId }.findAny().get().let { status -> - InsertWorkbookSubscriptionCommand(memberId = memberId, workbookId = subTargetWorkbookId).let { command -> - if (status.subHistory) { - CountWorkbookMappedArticlesQuery(subTargetWorkbookId).let { query -> - subscriptionDao.countWorkbookMappedArticles(query) - }?.let { lastDay -> - if (lastDay <= (status.day)) { - throw RuntimeException("이미 학습을 완료한 워크북입니다.") - } - subscriptionDao.reSubscribeWorkbookSubscription(command) + if (status.subHistory) { + CountWorkbookMappedArticlesQuery(subTargetWorkbookId).let { query -> + subscriptionDao.countWorkbookMappedArticles(query) + }?.let { lastDay -> + /** 이미 학습을 완료한 경우 */ + if (lastDay <= (status.day)) { + throw RuntimeException("이미 학습을 완료한 워크북입니다.") } - } else { - subscriptionDao.insertWorkbookSubscription(command) + /** 재구독 */ + subscriptionDao.reSubscribeWorkbookSubscription(command) } } } + } else { + /** 구독한 경우가 없는 경우 */ + subscriptionDao.insertWorkbookSubscription(command) } } } From 8c25193287f0c5d327c7976eff27ef23bba919de Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:45:08 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20api/client=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/main/resources/application-client-local.yml | 7 +++++++ api/src/main/resources/application-client-prd.yml | 7 +++++++ api/src/main/resources/application.yml | 2 ++ resources/docker/docker-compose-api.yml | 3 +++ 4 files changed, 19 insertions(+) create mode 100644 api/src/main/resources/application-client-local.yml create mode 100644 api/src/main/resources/application-client-prd.yml diff --git a/api/src/main/resources/application-client-local.yml b/api/src/main/resources/application-client-local.yml new file mode 100644 index 000000000..dd778ef74 --- /dev/null +++ b/api/src/main/resources/application-client-local.yml @@ -0,0 +1,7 @@ +client: + timeout: + connect: 5000 + read: 5000 + +webhook: + discord: ${WEBHOOK_DISCORD} diff --git a/api/src/main/resources/application-client-prd.yml b/api/src/main/resources/application-client-prd.yml new file mode 100644 index 000000000..042942ce2 --- /dev/null +++ b/api/src/main/resources/application-client-prd.yml @@ -0,0 +1,7 @@ +client: + timeout: + connect: ${TIMEOUT_CONNECT:5000} + read: ${TIMEOUT_READ:5000} + +webhook: + discord: ${WEBHOOK_DISCORD} diff --git a/api/src/main/resources/application.yml b/api/src/main/resources/application.yml index 89cce7fad..e0ee1a2f4 100644 --- a/api/src/main/resources/application.yml +++ b/api/src/main/resources/application.yml @@ -5,10 +5,12 @@ spring: profiles: group: local: + - client-local - api-repo-local - email-local - storage-local prd: + - client-prd - api-repo-prd - email-prd - storage-prd diff --git a/resources/docker/docker-compose-api.yml b/resources/docker/docker-compose-api.yml index 038477c8a..a115e19fb 100644 --- a/resources/docker/docker-compose-api.yml +++ b/resources/docker/docker-compose-api.yml @@ -19,3 +19,6 @@ services: IMAGE_STORE_BUCKET_NAME: ${IMAGE_STORE_BUCKET_NAME} DOCUMENT_STORE_BUCKET_NAME: ${DOCUMENT_STORE_BUCKET_NAME} CDN_URL: ${CDN_URL} + WEBHOOK_DISCORD: ${WEBHOOK_DISCORD} + TIMEOUT_CONNECT: ${TIMEOUT_CONNECT} + TIMEOUT_READ: ${TIMEOUT_READ} From e131c6f732b39d4209cfe4d5b19b866db8ee9156 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:45:38 +0900 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20ClientConfig=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/few/api/client/config/ClientConfig.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 api/src/main/kotlin/com/few/api/client/config/ClientConfig.kt diff --git a/api/src/main/kotlin/com/few/api/client/config/ClientConfig.kt b/api/src/main/kotlin/com/few/api/client/config/ClientConfig.kt new file mode 100644 index 000000000..8bccbb19a --- /dev/null +++ b/api/src/main/kotlin/com/few/api/client/config/ClientConfig.kt @@ -0,0 +1,24 @@ +package com.few.api.client.config + +import org.springframework.beans.factory.annotation.Value +import org.springframework.boot.web.client.RestTemplateBuilder +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.client.RestTemplate +import java.time.Duration + +@Configuration +class ClientConfig { + + @Bean + fun restTemplate( + restTemplateBuilder: RestTemplateBuilder, + @Value("\${client.timeout.connect}") connectTimeout: Int, + @Value("\${client.timeout.read}") readTimeout: Int + ): RestTemplate { + return restTemplateBuilder + .setConnectTimeout(Duration.ofSeconds(connectTimeout.toLong())) + .setReadTimeout(Duration.ofSeconds(readTimeout.toLong())) + .build() + } +} \ No newline at end of file From 4a6f96b4da6b2ade74f0e5deaf1088c1b9f37d5c Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:45:49 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat:=20DiscordBodyProperty=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 --- .../client/config/properties/DiscordBodyProperty.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 api/src/main/kotlin/com/few/api/client/config/properties/DiscordBodyProperty.kt diff --git a/api/src/main/kotlin/com/few/api/client/config/properties/DiscordBodyProperty.kt b/api/src/main/kotlin/com/few/api/client/config/properties/DiscordBodyProperty.kt new file mode 100644 index 000000000..9950977aa --- /dev/null +++ b/api/src/main/kotlin/com/few/api/client/config/properties/DiscordBodyProperty.kt @@ -0,0 +1,11 @@ +package com.few.api.client.config.properties + +data class DiscordBodyProperty( + val content: String, + val embeds: List +) + +data class Embed( + val title: String, + val description: String +) \ No newline at end of file From 56f9d36ac1f8bda07308a7b8f0dbdc56436cad7c Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:46:23 +0900 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20announceWorkbookSubscription=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/subscription/SubscriptionClient.kt | 45 +++++++++++++++++++ .../dto/WorkbookSubscriptionArgs.kt | 7 +++ 2 files changed, 52 insertions(+) create mode 100644 api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt create mode 100644 api/src/main/kotlin/com/few/api/client/subscription/dto/WorkbookSubscriptionArgs.kt diff --git a/api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt b/api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt new file mode 100644 index 000000000..b06c7aa6c --- /dev/null +++ b/api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt @@ -0,0 +1,45 @@ +package com.few.api.client.subscription + +import com.few.api.client.config.properties.DiscordBodyProperty +import com.few.api.client.config.properties.Embed +import com.few.api.client.subscription.dto.WorkbookSubscriptionArgs +import org.springframework.beans.factory.annotation.Value +import org.springframework.http.HttpEntity +import org.springframework.http.HttpMethod +import org.springframework.stereotype.Service +import org.springframework.web.client.RestTemplate + +@Service +class SubscriptionClient( + private val restTemplate: RestTemplate, + @Value("\${webhook.discord}") private val discordWebhook: String +) { + fun announceWorkbookSubscription(args: WorkbookSubscriptionArgs) { + args.let { + DiscordBodyProperty( + content = "🎉 신규 구독 알림 ", + embeds = listOf( + Embed( + title = "Total Subscriptions", + description = it.totalSubscriptions.toString() + ), + Embed( + title = "Active Subscriptions", + description = it.activeSubscriptions.toString() + ), + Embed( + title = "Workbook Title", + description = it.workbookTitle + ) + ) + ) + }.let { body -> + restTemplate.exchange( + discordWebhook, + HttpMethod.POST, + HttpEntity(body), + String::class.java + ) + } + } +} \ No newline at end of file diff --git a/api/src/main/kotlin/com/few/api/client/subscription/dto/WorkbookSubscriptionArgs.kt b/api/src/main/kotlin/com/few/api/client/subscription/dto/WorkbookSubscriptionArgs.kt new file mode 100644 index 000000000..b1e70cc3d --- /dev/null +++ b/api/src/main/kotlin/com/few/api/client/subscription/dto/WorkbookSubscriptionArgs.kt @@ -0,0 +1,7 @@ +package com.few.api.client.subscription.dto + +data class WorkbookSubscriptionArgs( + val totalSubscriptions: Long, + val activeSubscriptions: Long, + val workbookTitle: String +) \ No newline at end of file From f36b055a826167990e56b0bcd557bc7232e06085 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:46:48 +0900 Subject: [PATCH 06/15] =?UTF-8?q?feat:=20@EnableAsync=20=ED=99=9C=EC=84=B1?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/main/kotlin/com/few/api/config/ApiConfig.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/api/src/main/kotlin/com/few/api/config/ApiConfig.kt b/api/src/main/kotlin/com/few/api/config/ApiConfig.kt index c2a019a7e..18cc18f23 100644 --- a/api/src/main/kotlin/com/few/api/config/ApiConfig.kt +++ b/api/src/main/kotlin/com/few/api/config/ApiConfig.kt @@ -7,12 +7,14 @@ import com.few.storage.image.config.ImageStorageConfig import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration import org.springframework.context.annotation.Import +import org.springframework.scheduling.annotation.EnableAsync import org.springframework.web.servlet.config.annotation.EnableWebMvc @Configuration @ComponentScan(basePackages = [ApiConfig.BASE_PACKAGE]) @Import(ApiRepoConfig::class, BatchConfig::class, ImageStorageConfig::class, DocumentStorageConfig::class) @EnableWebMvc +@EnableAsync class ApiConfig { companion object { const val BASE_PACKAGE = "com.few.api" From 3b2dcc6919dc0f41c13096ede9150b490701ec02 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:47:53 +0900 Subject: [PATCH 07/15] =?UTF-8?q?feat:=20countAllSubscriptionStatus=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../few/api/repo/dao/subscription/SubscriptionDao.kt | 12 ++++++++++++ .../record/CountAllSubscriptionStatusRecord.kt | 6 ++++++ 2 files changed, 18 insertions(+) create mode 100644 api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/CountAllSubscriptionStatusRecord.kt diff --git a/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt index 3db94dabf..1afedfe58 100644 --- a/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt +++ b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt @@ -6,6 +6,7 @@ import com.few.api.repo.dao.subscription.command.UpdateDeletedAtInWorkbookSubscr import com.few.api.repo.dao.subscription.query.SelectAllWorkbookSubscriptionStatusQueryNotConsiderDeletedAt import com.few.api.repo.dao.subscription.record.WorkbookSubscriptionStatus import com.few.api.repo.dao.subscription.query.CountWorkbookMappedArticlesQuery +import com.few.api.repo.dao.subscription.record.CountAllSubscriptionStatusRecord import jooq.jooq_dsl.Tables.MAPPING_WORKBOOK_ARTICLE import jooq.jooq_dsl.Tables.SUBSCRIPTION import org.jooq.DSLContext @@ -68,4 +69,15 @@ class SubscriptionDao( .where(MAPPING_WORKBOOK_ARTICLE.WORKBOOK_ID.eq(query.workbookId)) .fetchOne(0, Int::class.java) } + + fun countAllSubscriptionStatus(): CountAllSubscriptionStatusRecord { + val total = dslContext.selectCount() + .from(SUBSCRIPTION) + .fetchOne(0, Int::class.java)!! + val active = dslContext.selectCount() + .from(SUBSCRIPTION) + .where(SUBSCRIPTION.DELETED_AT.isNull) + .fetchOne(0, Int::class.java)!! + return CountAllSubscriptionStatusRecord(total.toLong(), active.toLong()) + } } \ No newline at end of file diff --git a/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/CountAllSubscriptionStatusRecord.kt b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/CountAllSubscriptionStatusRecord.kt new file mode 100644 index 000000000..ca97acc9f --- /dev/null +++ b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/CountAllSubscriptionStatusRecord.kt @@ -0,0 +1,6 @@ +package com.few.api.repo.dao.subscription.record + +data class CountAllSubscriptionStatusRecord( + val totalSubscriptions: Long, + val activeSubscriptions: Long +) \ No newline at end of file From fa0b643c716ae0efd8d252badb1a7a019fb6fc12 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:49:23 +0900 Subject: [PATCH 08/15] =?UTF-8?q?feat:=20readWorkbookTitle=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../subscription/service/WorkbookService.kt | 18 ++++++++++++++++++ .../service/dto/ReadWorkbookTitleDto.kt | 5 +++++ 2 files changed, 23 insertions(+) create mode 100644 api/src/main/kotlin/com/few/api/domain/subscription/service/WorkbookService.kt create mode 100644 api/src/main/kotlin/com/few/api/domain/subscription/service/dto/ReadWorkbookTitleDto.kt diff --git a/api/src/main/kotlin/com/few/api/domain/subscription/service/WorkbookService.kt b/api/src/main/kotlin/com/few/api/domain/subscription/service/WorkbookService.kt new file mode 100644 index 000000000..26c2e1893 --- /dev/null +++ b/api/src/main/kotlin/com/few/api/domain/subscription/service/WorkbookService.kt @@ -0,0 +1,18 @@ +package com.few.api.domain.subscription.service + +import com.few.api.domain.subscription.service.dto.ReadWorkbookTitleDto +import com.few.api.repo.dao.workbook.WorkbookDao +import com.few.api.repo.dao.workbook.query.SelectWorkBookRecordQuery +import org.springframework.stereotype.Service + +@Service +class WorkbookService( + private val workbookDao: WorkbookDao +) { + + fun readWorkbookTitle(dto: ReadWorkbookTitleDto): String? { + return SelectWorkBookRecordQuery(dto.workbookId).let { query -> + workbookDao.selectWorkBook(query)?.title + } + } +} \ No newline at end of file diff --git a/api/src/main/kotlin/com/few/api/domain/subscription/service/dto/ReadWorkbookTitleDto.kt b/api/src/main/kotlin/com/few/api/domain/subscription/service/dto/ReadWorkbookTitleDto.kt new file mode 100644 index 000000000..e5128b4e3 --- /dev/null +++ b/api/src/main/kotlin/com/few/api/domain/subscription/service/dto/ReadWorkbookTitleDto.kt @@ -0,0 +1,5 @@ +package com.few.api.domain.subscription.service.dto + +data class ReadWorkbookTitleDto( + val workbookId: Long +) \ No newline at end of file From 4d7df8aa681f2e061f91d06feb107e3e5f756b03 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:49:45 +0900 Subject: [PATCH 09/15] =?UTF-8?q?feat:=20WorkbookSubscriptionEvent=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WorkbookSubscriptionEventListener.kt | 37 +++++++++++++++++++ .../event/dto/WorkbookSubscriptionEvent.kt | 5 +++ 2 files changed, 42 insertions(+) create mode 100644 api/src/main/kotlin/com/few/api/domain/subscription/event/WorkbookSubscriptionEventListener.kt create mode 100644 api/src/main/kotlin/com/few/api/domain/subscription/event/dto/WorkbookSubscriptionEvent.kt diff --git a/api/src/main/kotlin/com/few/api/domain/subscription/event/WorkbookSubscriptionEventListener.kt b/api/src/main/kotlin/com/few/api/domain/subscription/event/WorkbookSubscriptionEventListener.kt new file mode 100644 index 000000000..e5324c4d5 --- /dev/null +++ b/api/src/main/kotlin/com/few/api/domain/subscription/event/WorkbookSubscriptionEventListener.kt @@ -0,0 +1,37 @@ +package com.few.api.domain.subscription.event + +import com.few.api.client.subscription.SubscriptionClient +import com.few.api.client.subscription.dto.WorkbookSubscriptionArgs +import com.few.api.domain.subscription.event.dto.WorkbookSubscriptionEvent +import com.few.api.domain.subscription.service.WorkbookService +import com.few.api.domain.subscription.service.dto.ReadWorkbookTitleDto +import com.few.api.repo.dao.subscription.SubscriptionDao +import org.springframework.context.event.EventListener +import org.springframework.scheduling.annotation.Async +import org.springframework.stereotype.Component + +@Component +class WorkbookSubscriptionEventListener( + private val subscriptionDao: SubscriptionDao, + private val subscriptionClient: SubscriptionClient, + private val workbookService: WorkbookService +) { + + @Async + @EventListener + fun handleWorkbookSubscriptionEvent(event: WorkbookSubscriptionEvent) { + val title = ReadWorkbookTitleDto(event.workbookId).let { dto -> + workbookService.readWorkbookTitle(dto) + ?: throw RuntimeException("Workbook not found") + } + subscriptionDao.countAllSubscriptionStatus().let { record -> + WorkbookSubscriptionArgs( + totalSubscriptions = record.totalSubscriptions, + activeSubscriptions = record.activeSubscriptions, + workbookTitle = title + ).let { args -> + subscriptionClient.announceWorkbookSubscription(args) + } + } + } +} \ No newline at end of file diff --git a/api/src/main/kotlin/com/few/api/domain/subscription/event/dto/WorkbookSubscriptionEvent.kt b/api/src/main/kotlin/com/few/api/domain/subscription/event/dto/WorkbookSubscriptionEvent.kt new file mode 100644 index 000000000..c617fcde6 --- /dev/null +++ b/api/src/main/kotlin/com/few/api/domain/subscription/event/dto/WorkbookSubscriptionEvent.kt @@ -0,0 +1,5 @@ +package com.few.api.domain.subscription.event.dto + +data class WorkbookSubscriptionEvent( + val workbookId: Long +) \ No newline at end of file From 0fba9455928b12107c6a8866593dcc9037386318 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 21:50:11 +0900 Subject: [PATCH 10/15] =?UTF-8?q?feat:=20WorkbookSubscriptionEvent=20?= =?UTF-8?q?=EB=B0=9C=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/subscription/usecase/SubscribeWorkbookUseCase.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt b/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt index f91c76c4e..e9297667d 100644 --- a/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt +++ b/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt @@ -1,5 +1,6 @@ package com.few.api.domain.subscription.usecase +import com.few.api.domain.subscription.event.dto.WorkbookSubscriptionEvent import com.few.api.domain.subscription.service.MemberService import com.few.api.domain.subscription.service.dto.InsertMemberDto import com.few.api.domain.subscription.service.dto.ReadMemberIdDto @@ -9,13 +10,15 @@ import com.few.api.repo.dao.subscription.query.SelectAllWorkbookSubscriptionStat import com.few.api.domain.subscription.usecase.`in`.SubscribeWorkbookUseCaseIn import com.few.api.repo.dao.subscription.query.CountWorkbookMappedArticlesQuery import com.few.data.common.code.MemberType +import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Component import org.springframework.transaction.annotation.Transactional @Component class SubscribeWorkbookUseCase( private val subscriptionDao: SubscriptionDao, - private val memberService: MemberService + private val memberService: MemberService, + private val applicationEventPublisher: ApplicationEventPublisher ) { // todo 이미 가입된 경우 @@ -58,6 +61,7 @@ class SubscribeWorkbookUseCase( /** 구독한 경우가 없는 경우 */ subscriptionDao.insertWorkbookSubscription(command) } + applicationEventPublisher.publishEvent(WorkbookSubscriptionEvent(workbookId = subTargetWorkbookId)) } } } From 74c35a18025fec1eb3cbe41ee075076040d937eb Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 22:03:13 +0900 Subject: [PATCH 11/15] =?UTF-8?q?feat:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=97=90=20=EC=B6=94=EA=B0=80=EB=90=9C=20api/client=20?= =?UTF-8?q?=EA=B5=AC=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/test/resources/application-test.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/src/test/resources/application-test.yml b/api/src/test/resources/application-test.yml index d6d07a721..c387cea4c 100644 --- a/api/src/test/resources/application-test.yml +++ b/api/src/test/resources/application-test.yml @@ -40,3 +40,11 @@ document: cdn: url: http://127.0.0.1:9000 + +client: + timeout: + connect: 5000 + read: 5000 + +webhook: + discord: https://discord.com/api/webhooks/1234567890/abcdefg From 9161c98f5c045c8d43371020c47b906f22d178d6 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 23:53:24 +0900 Subject: [PATCH 12/15] =?UTF-8?q?refactor:=20WorkbookSubscriptionStatus=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - id -> workbookId - subHistory -> isActiveSub --- .../dao/subscription/record/WorkbookSubscriptionStatus.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/WorkbookSubscriptionStatus.kt b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/WorkbookSubscriptionStatus.kt index de7f37f95..beafa0a93 100644 --- a/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/WorkbookSubscriptionStatus.kt +++ b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/record/WorkbookSubscriptionStatus.kt @@ -1,7 +1,7 @@ package com.few.api.repo.dao.subscription.record data class WorkbookSubscriptionStatus( - val id: Long, - val subHistory: Boolean, + val workbookId: Long, + val isActiveSub: Boolean, val day: Int ) \ No newline at end of file From 19f380a5449097b6db7224ca71f8c18d08b20ed8 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 23:53:59 +0900 Subject: [PATCH 13/15] =?UTF-8?q?refactor:=20selectAllWorkbookSubscription?= =?UTF-8?q?Status=20->=20selectTopWorkbookSubscriptionStatus=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../few/api/repo/dao/subscription/SubscriptionDao.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt index 1afedfe58..d30ab4d12 100644 --- a/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt +++ b/api-repo/src/main/kotlin/com/few/api/repo/dao/subscription/SubscriptionDao.kt @@ -43,16 +43,18 @@ class SubscriptionDao( .execute() } - fun selectAllWorkbookSubscriptionStatus(query: SelectAllWorkbookSubscriptionStatusQueryNotConsiderDeletedAt): List { + fun selectTopWorkbookSubscriptionStatus(query: SelectAllWorkbookSubscriptionStatusQueryNotConsiderDeletedAt): WorkbookSubscriptionStatus? { return dslContext.select( - SUBSCRIPTION.ID.`as`(WorkbookSubscriptionStatus::id.name), - SUBSCRIPTION.DELETED_AT.isNotNull.`as`(WorkbookSubscriptionStatus::subHistory.name), + SUBSCRIPTION.TARGET_WORKBOOK_ID.`as`(WorkbookSubscriptionStatus::workbookId.name), + SUBSCRIPTION.DELETED_AT.isNull.`as`(WorkbookSubscriptionStatus::isActiveSub.name), SUBSCRIPTION.PROGRESS.add(1).`as`(WorkbookSubscriptionStatus::day.name) ) .from(SUBSCRIPTION) .where(SUBSCRIPTION.MEMBER_ID.eq(query.memberId)) .and(SUBSCRIPTION.TARGET_WORKBOOK_ID.eq(query.workbookId)) - .fetchInto(WorkbookSubscriptionStatus::class.java) + .orderBy(SUBSCRIPTION.CREATED_AT.desc()) + .limit(1) + .fetchOneInto(WorkbookSubscriptionStatus::class.java) } fun updateDeletedAtInAllSubscription(command: UpdateDeletedAtInAllSubscriptionCommand) { From 79e63acbaa2e45345d196a1734950ba080126244 Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Mon, 1 Jul 2024 23:54:38 +0900 Subject: [PATCH 14/15] =?UTF-8?q?refactor:=20SubscribeWorkbookUseCase=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85/=EC=9E=AC=EA=B5=AC=EB=8F=85=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecase/SubscribeWorkbookUseCase.kt | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt b/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt index e9297667d..25d35ce1c 100644 --- a/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt +++ b/api/src/main/kotlin/com/few/api/domain/subscription/usecase/SubscribeWorkbookUseCase.kt @@ -21,7 +21,6 @@ class SubscribeWorkbookUseCase( private val applicationEventPublisher: ApplicationEventPublisher ) { - // todo 이미 가입된 경우 @Transactional fun execute(useCaseIn: SubscribeWorkbookUseCaseIn) { // TODO: request sending email @@ -36,33 +35,31 @@ class SubscribeWorkbookUseCase( workbookId = subTargetWorkbookId ) - /** 구독 히스토리가 있는지 확인 */ - SelectAllWorkbookSubscriptionStatusQueryNotConsiderDeletedAt(memberId = memberId, workbookId = subTargetWorkbookId).let { query -> - subscriptionDao.selectAllWorkbookSubscriptionStatus(query).let { subscriptionStatusList -> - /** 이미 구독한 경우가 있는 경우 */ - if (subscriptionStatusList.isNotEmpty()) { - subscriptionStatusList.stream().filter { status -> - status.id == query.workbookId - }.findAny().get().let { status -> - if (status.subHistory) { - CountWorkbookMappedArticlesQuery(subTargetWorkbookId).let { query -> - subscriptionDao.countWorkbookMappedArticles(query) - }?.let { lastDay -> - /** 이미 학습을 완료한 경우 */ - if (lastDay <= (status.day)) { - throw RuntimeException("이미 학습을 완료한 워크북입니다.") - } - /** 재구독 */ - subscriptionDao.reSubscribeWorkbookSubscription(command) - } - } - } - } else { - /** 구독한 경우가 없는 경우 */ - subscriptionDao.insertWorkbookSubscription(command) + val subscriptionStatus = subscriptionDao.selectTopWorkbookSubscriptionStatus( + SelectAllWorkbookSubscriptionStatusQueryNotConsiderDeletedAt(memberId = memberId, workbookId = subTargetWorkbookId) + ) + + when { + /** 구독한 히스토리가 없는 경우 */ + subscriptionStatus == null -> { + subscriptionDao.insertWorkbookSubscription(command) + } + + /** 이미 구독한 히스토리가 있고 구독이 취소된 경우 */ + !subscriptionStatus.isActiveSub -> { + val lastDay = subscriptionDao.countWorkbookMappedArticles(CountWorkbookMappedArticlesQuery(subTargetWorkbookId)) ?: throw RuntimeException("워크북 매핑된 아티클을 조회할 수 없습니다.") + if (lastDay <= subscriptionStatus.day) { + throw RuntimeException("이미 학습을 완료한 워크북입니다.") } - applicationEventPublisher.publishEvent(WorkbookSubscriptionEvent(workbookId = subTargetWorkbookId)) + /** 재구독 */ + subscriptionDao.reSubscribeWorkbookSubscription(command) + } + + /** 이미 구독한 히스토리가 있고 구독이 취소되지 않은 경우 */ + else -> { + throw RuntimeException("이미 구독한 워크북입니다.") } } + applicationEventPublisher.publishEvent(WorkbookSubscriptionEvent(workbookId = subTargetWorkbookId)) } } \ No newline at end of file From 28adc89705df199fe6037326e70f7641755bf5eb Mon Sep 17 00:00:00 2001 From: belljun3395 <195850@jnu.ac.kr> Date: Thu, 4 Jul 2024 22:46:39 +0900 Subject: [PATCH 15/15] =?UTF-8?q?feat:=20=EB=94=94=EC=8A=A4=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=ED=9B=85=20=EC=A0=84=EC=86=A1=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=20=EB=A1=9C=EA=B7=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/few/api/client/subscription/SubscriptionClient.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt b/api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt index b06c7aa6c..efd0529c8 100644 --- a/api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt +++ b/api/src/main/kotlin/com/few/api/client/subscription/SubscriptionClient.kt @@ -3,6 +3,7 @@ package com.few.api.client.subscription import com.few.api.client.config.properties.DiscordBodyProperty import com.few.api.client.config.properties.Embed import com.few.api.client.subscription.dto.WorkbookSubscriptionArgs +import org.apache.juli.logging.LogFactory import org.springframework.beans.factory.annotation.Value import org.springframework.http.HttpEntity import org.springframework.http.HttpMethod @@ -14,6 +15,8 @@ class SubscriptionClient( private val restTemplate: RestTemplate, @Value("\${webhook.discord}") private val discordWebhook: String ) { + private val log = LogFactory.getLog(SubscriptionClient::class.java) + fun announceWorkbookSubscription(args: WorkbookSubscriptionArgs) { args.let { DiscordBodyProperty( @@ -39,7 +42,9 @@ class SubscriptionClient( HttpMethod.POST, HttpEntity(body), String::class.java - ) + ).let { res -> + log.info("Discord webhook response: ${res.statusCode}") + } } } } \ No newline at end of file