This repository has been archived by the owner on Sep 16, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* setting: 서브모듈 갱신과 jvmTarget 17로 명시 * feat(Events): Events 구현 * feat(ReminderService): 물주기 알림을 주는 ReminderService 구현 * feat(FirebaseConfig): FCM scope 추가 * refactor(FCMChannel): 페키지 이동
- Loading branch information
1 parent
d2f9622
commit acb9b2f
Showing
14 changed files
with
255 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
src/main/kotlin/gdsc/plantory/common/config/EventsConfiguration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package gdsc.plantory.common.config | ||
|
||
import gdsc.plantory.event.Events | ||
import org.springframework.beans.factory.InitializingBean | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.context.ApplicationContext | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
|
||
@Configuration | ||
class EventsConfiguration( | ||
@Autowired val applicationContext: ApplicationContext, | ||
) { | ||
|
||
@Bean | ||
fun eventsInitializer(): InitializingBean { | ||
return InitializingBean { Events.setPublisher(applicationContext) } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package gdsc.plantory.event | ||
|
||
import org.springframework.context.ApplicationEventPublisher | ||
import java.util.Objects | ||
|
||
class Events { | ||
companion object { | ||
private lateinit var publisher: ApplicationEventPublisher | ||
|
||
fun setPublisher(publisher: ApplicationEventPublisher) { | ||
Events.publisher = publisher | ||
} | ||
|
||
fun raise(event: Any) { | ||
if (Objects.nonNull(publisher)) { | ||
publisher.publishEvent(event) | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package gdsc.plantory.event | ||
|
||
enum class FCMChannel { | ||
WATER_ALERT, | ||
} |
7 changes: 7 additions & 0 deletions
7
src/main/kotlin/gdsc/plantory/event/notification/WaterCycleEvent.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package gdsc.plantory.event.notification | ||
|
||
data class WaterCycleEvent( | ||
val deviceToken: String, | ||
val title: String = "물을 줄 시간이에요!", | ||
val body: String = "반려 식물에게 물을 줄 시간이에요!", | ||
) |
66 changes: 66 additions & 0 deletions
66
src/main/kotlin/gdsc/plantory/event/notification/WaterCycleEventListener.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
package gdsc.plantory.event.notification | ||
|
||
import com.google.firebase.messaging.AndroidConfig | ||
import com.google.firebase.messaging.AndroidNotification | ||
import com.google.firebase.messaging.FirebaseMessaging | ||
import com.google.firebase.messaging.FirebaseMessagingException | ||
import com.google.firebase.messaging.Message | ||
import com.google.firebase.messaging.Notification | ||
import gdsc.plantory.event.FCMChannel | ||
import org.slf4j.LoggerFactory | ||
import org.springframework.scheduling.annotation.Async | ||
import org.springframework.stereotype.Component | ||
import org.springframework.transaction.event.TransactionPhase | ||
import org.springframework.transaction.event.TransactionalEventListener | ||
|
||
@Component | ||
class WaterCycleEventListener( | ||
val firebaseMessaging: FirebaseMessaging, | ||
) { | ||
|
||
companion object { | ||
private val log = LoggerFactory.getLogger(WaterCycleEventListener::class.java) | ||
} | ||
|
||
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) | ||
@Async | ||
fun sendFcmNotification(events: List<WaterCycleEvent>) { | ||
val messages: List<Message> = createMessages(events, FCMChannel.WATER_ALERT.name) | ||
|
||
try { | ||
firebaseMessaging.sendEach(messages) | ||
} catch (e: FirebaseMessagingException) { | ||
log.warn("fail send FCM message", e) | ||
} | ||
} | ||
|
||
private fun createMessages(events: List<WaterCycleEvent>, channelId: String): List<Message> { | ||
return events.map { event -> createMessage(event, channelId) }.toList() | ||
} | ||
|
||
private fun createMessage(event: WaterCycleEvent, channelId: String): Message { | ||
return Message.builder() | ||
.setNotification( | ||
Notification | ||
.builder() | ||
.setTitle(event.title) | ||
.setBody(event.body) | ||
.build() | ||
) | ||
.setAndroidConfig(createAndroidConfig(channelId)) | ||
.setToken(event.deviceToken) | ||
.build() | ||
} | ||
|
||
private fun createAndroidConfig(channelId: String): AndroidConfig? { | ||
return AndroidConfig.builder() | ||
.setNotification(createAndroidNotification(channelId)) | ||
.build() | ||
} | ||
|
||
private fun createAndroidNotification(channelId: String): AndroidNotification? { | ||
return AndroidNotification.builder() | ||
.setChannelId(channelId) | ||
.build() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
6 changes: 6 additions & 0 deletions
6
src/main/kotlin/gdsc/plantory/plant/presentation/dto/CompanionPlantWaterCycleDto.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
package gdsc.plantory.plant.presentation.dto | ||
|
||
class CompanionPlantWaterCycleDto( | ||
val deviceToken: String, | ||
val nickName: String, | ||
) |
35 changes: 35 additions & 0 deletions
35
src/main/kotlin/gdsc/plantory/plant/service/ReminderService.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package gdsc.plantory.plant.service | ||
|
||
import gdsc.plantory.event.Events | ||
import gdsc.plantory.event.notification.WaterCycleEvent | ||
import gdsc.plantory.plant.domain.CompanionPlantRepository | ||
import gdsc.plantory.plant.presentation.dto.CompanionPlantWaterCycleDto | ||
import org.springframework.scheduling.annotation.Scheduled | ||
import org.springframework.stereotype.Service | ||
import org.springframework.transaction.annotation.Transactional | ||
import java.time.LocalDate | ||
|
||
@Service | ||
@Transactional | ||
class ReminderService( | ||
private val companionPlantRepository: CompanionPlantRepository, | ||
) { | ||
|
||
@Scheduled(cron = "0 0 8 * * *") | ||
fun sendWaterNotification() { | ||
val companionPlants = companionPlantRepository.findAllByNextWaterDate(LocalDate.now()) | ||
val events: List<WaterCycleEvent> = buildWaterCycleEvents(companionPlants) | ||
Events.raise(events) | ||
} | ||
|
||
private fun buildWaterCycleEvents(companionPlants: List<CompanionPlantWaterCycleDto>) = | ||
companionPlants | ||
.map { | ||
WaterCycleEvent( | ||
it.deviceToken, | ||
"물을 줄 시간이에요!", | ||
"${it.nickName}에게 물을 줄 시간이에요!" | ||
) | ||
} | ||
.toList() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,3 +24,4 @@ companionPlant: | |
fcm: | ||
key: | ||
path: src/main/resources/config/google-services.json | ||
scope: prod |
Submodule config
updated
from 7897ed to dff959
64 changes: 64 additions & 0 deletions
64
src/test/kotlin/gdsc/plantory/plant/domain/CompanionPlantRepositoryTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package gdsc.plantory.plant.domain | ||
|
||
import gdsc.plantory.member.domain.Member | ||
import gdsc.plantory.member.domain.MemberRepository | ||
import gdsc.plantory.util.AcceptanceTest | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.assertj.core.groups.Tuple | ||
import org.junit.jupiter.api.DisplayName | ||
import org.junit.jupiter.api.Test | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import java.time.LocalDate | ||
|
||
@DisplayName("리포지토리 : CompanionPlant") | ||
class CompanionPlantRepositoryTest( | ||
@Autowired val companionPlantRepository: CompanionPlantRepository, | ||
@Autowired val memberRepository: MemberRepository, | ||
) : AcceptanceTest() { | ||
|
||
@Test | ||
fun `물주는 날짜가 된 반려식물의 별칭과 해당 유저의 deviceToken을 조회한다`() { | ||
// given | ||
val member = Member("shine") | ||
val savedMember = memberRepository.save(member) | ||
val memberId = savedMember.getId | ||
|
||
val nextWaterDate = LocalDate.of(2024, 1, 7) | ||
|
||
val companionPlant1 = createCompanionPlantByLastWaterDate(nextWaterDate, memberId) | ||
val companionPlant2 = createCompanionPlantByLastWaterDate(nextWaterDate.plusDays(1), memberId) | ||
val companionPlant3 = createCompanionPlantByLastWaterDate(nextWaterDate.minusDays(1), memberId) | ||
val companionPlant4 = createCompanionPlantByLastWaterDate(nextWaterDate, memberId) | ||
companionPlantRepository.saveAll( | ||
listOf( | ||
companionPlant1, | ||
companionPlant2, | ||
companionPlant3, | ||
companionPlant4 | ||
) | ||
) | ||
|
||
// when | ||
val results = companionPlantRepository.findAllByNextWaterDate(nextWaterDate) | ||
|
||
// then | ||
assertThat(results).hasSize(2) | ||
.extracting("deviceToken", "nickName") | ||
.containsExactlyInAnyOrder( | ||
Tuple.tuple("shine", "2024-01-07"), | ||
Tuple.tuple("shine", "2024-01-07") | ||
) | ||
} | ||
|
||
private fun createCompanionPlantByLastWaterDate(nextWaterDate: LocalDate, memberId: Long) = CompanionPlant( | ||
_imageUrl = "https://nongsaro.go.kr/cms_contents/301/13336_MF_ATTACH_05.jpg", | ||
_shortDescription = "덕구리난은 덕구리난과!", | ||
_nickname = nextWaterDate.toString(), | ||
birthDate = LocalDate.of(2024, 1, 1), | ||
nextWaterDate = nextWaterDate, | ||
lastWaterDate = LocalDate.of(2024, 1, 4), | ||
waterCycle = 3, | ||
plantInformationId = 1L, | ||
memberId = memberId, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters