Skip to content

Commit

Permalink
[feat #98] 알림 조회, 삭제 api (#99)
Browse files Browse the repository at this point in the history
* remove : AlertSender 제거

* feat : 알림 도메인, 엔티티

* feat : 알림 조회, 삭제 api

* feat : 알림 유스케이스 구현

* feat : 알림 포트 구현

* feat : 알림에러코드, 응답 dto

* feat : LocalDateTime Supplier 빈 설정

* feat : 알림 도메인 기본값 추가

* feat : 알림 서비스 테스트
  • Loading branch information
dlswns2480 authored Aug 17, 2024
1 parent db2fd1b commit d67c2a3
Show file tree
Hide file tree
Showing 16 changed files with 277 additions and 91 deletions.
45 changes: 45 additions & 0 deletions adapters/in-web/src/main/kotlin/com/pokit/alert/AlertController.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.pokit.alert

import com.pokit.alert.dto.response.AlertsResponse
import com.pokit.alert.port.`in`.AlertUseCase
import com.pokit.auth.model.PrincipalUser
import com.pokit.common.dto.SliceResponseDto
import com.pokit.common.wrapper.ResponseWrapper.wrapOk
import com.pokit.common.wrapper.ResponseWrapper.wrapSlice
import com.pokit.common.wrapper.ResponseWrapper.wrapUnit
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort
import org.springframework.data.web.PageableDefault
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.*

@RestController
@RequestMapping("/api/v1/alert")
class AlertController(
private val alertUseCase: AlertUseCase
) {
@GetMapping
fun getAlerts(
@AuthenticationPrincipal user: PrincipalUser,
@PageableDefault(
page = 0,
size = 10,
sort = ["createdAt"],
direction = Sort.Direction.DESC
) pageable: Pageable
): ResponseEntity<SliceResponseDto<AlertsResponse>> {
return alertUseCase.getAlerts(user.id, pageable)
.wrapSlice()
.wrapOk()
}

@PutMapping("/{alertId}")
fun deleteAlert(
@AuthenticationPrincipal user: PrincipalUser,
@PathVariable("alertId") alertId: Long
): ResponseEntity<Unit> {
return alertUseCase.delete(user.id, alertId)
.wrapUnit()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.pokit.out.persistence.alert.impl

import com.pokit.alert.model.Alert
import com.pokit.alert.port.out.AlertPort
import com.pokit.out.persistence.alert.persist.AlertRepository
import com.pokit.out.persistence.alert.persist.toDomain
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Slice
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Repository

@Repository
class AlertAdapter(
private val alertRepository: AlertRepository
) : AlertPort {
override fun loadAllByUserId(userId: Long, pageable: Pageable): Slice<Alert> {
return alertRepository.findAllByUserIdAndDeleted(userId, false, pageable)
.map { it.toDomain() }
}

override fun loadByIdAndUserId(id: Long, userId: Long): Alert? {
return alertRepository.findByIdAndUserId(id, userId)
?.toDomain()
}

override fun delete(alert: Alert) {
alertRepository.findByIdOrNull(alert.id)
?.delete()
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.pokit.out.persistence.alert.persist

import com.pokit.alert.model.Alert
import com.pokit.content.model.ContentInfo
import com.pokit.out.persistence.BaseEntity
import jakarta.persistence.*

Expand All @@ -25,28 +24,29 @@ class AlertEntity(
@Column(name = "title")
val title: String,

@Column(name = "body")
val body: String,

@Column(name = "is_deleted")
val deleted: Boolean = false

var deleted: Boolean = false
) : BaseEntity() {

fun delete() {
this.deleted = true
}

companion object {
fun of(alert: Alert) = AlertEntity(
userId = alert.userId,
contentId = alert.content.contentId,
contentThumbNail = alert.content.contentThumbNail,
contentId = alert.contentId,
contentThumbNail = alert.contentThumbNail,
title = alert.title,
body = alert.body,
)
}
}

fun AlertEntity.toDomain() = Alert(
id = this.id,
userId = this.userId,
content = ContentInfo(this.contentId, this.contentThumbNail),
contentId = this.contentId,
contentThumbNail = this.contentThumbNail,
title = this.title,
body = this.body,
createdAt = this.createdAt
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.pokit.out.persistence.alert.persist

import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Slice
import org.springframework.data.jpa.repository.JpaRepository

interface AlertRepository : JpaRepository<AlertEntity, Long> {
fun findAllByUserIdAndDeleted(userId: Long, deleted: Boolean, pageable: Pageable): Slice<AlertEntity>

fun findByIdAndUserId(id: Long, userId: Long): AlertEntity?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.pokit.alert

import com.pokit.alert.model.Alert
import java.time.LocalDateTime

class AlertFixure {
companion object {
fun getAlert(userId: Long, title: String, createdAt: LocalDateTime) = Alert(
userId = userId,
contentId = 1L,
contentThumbNail = "www.imageThumbnail.com",
title = title,
createdAt = createdAt
)
}
}

This file was deleted.

42 changes: 0 additions & 42 deletions adapters/out-web/src/main/kotlin/com/pokit/alert/impl/FcmSender.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.pokit.alert.port.`in`

import com.pokit.alert.dto.response.AlertsResponse
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Slice

interface AlertUseCase {
fun getAlerts(userId: Long, pageable: Pageable): Slice<AlertsResponse>

fun delete(userId: Long, alertId: Long)
}
13 changes: 13 additions & 0 deletions application/src/main/kotlin/com/pokit/alert/port/out/AlertPort.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.pokit.alert.port.out

import com.pokit.alert.model.Alert
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Slice

interface AlertPort {
fun loadAllByUserId(userId: Long, pageable: Pageable): Slice<Alert>

fun loadByIdAndUserId(id: Long, userId: Long): Alert?

fun delete(alert: Alert)
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.pokit.alert.port.service

import com.pokit.alert.dto.response.AlertsResponse
import com.pokit.alert.dto.response.toAlertsResponse
import com.pokit.alert.exception.AlertErrorCode
import com.pokit.alert.port.`in`.AlertUseCase
import com.pokit.alert.port.out.AlertPort
import com.pokit.common.exception.NotFoundCustomException
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Slice
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime
import java.time.temporal.ChronoUnit
import java.util.function.Supplier
import kotlin.math.abs

@Service
@Transactional(readOnly = true)
class AlertService(
private val now: Supplier<LocalDateTime>,
private val alertPort: AlertPort
) : AlertUseCase {
override fun getAlerts(userId: Long, pageable: Pageable): Slice<AlertsResponse> {
val nowDay = now.get().toLocalDate()

return alertPort.loadAllByUserId(userId, pageable)
.map {
val dayDifference = ChronoUnit.DAYS.between(nowDay, it.createdAt.toLocalDate())
it.toAlertsResponse(abs(dayDifference.toInt()))
}
}

@Transactional
override fun delete(userId: Long, alertId: Long) {
val alert = alertPort.loadByIdAndUserId(alertId, userId)
?: throw NotFoundCustomException(AlertErrorCode.NOT_FOUND_ALERT)
alertPort.delete(alert)
}
}
15 changes: 15 additions & 0 deletions application/src/main/kotlin/com/pokit/config/TimeConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.pokit.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.time.LocalDateTime
import java.util.function.Supplier

@Configuration
class TimeConfig {

@Bean("nowTimeSupplier")
fun nowTimeSupplier(): Supplier<LocalDateTime> {
return Supplier { LocalDateTime.now() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.pokit.alert.port.service

import com.pokit.alert.AlertFixure
import com.pokit.alert.port.out.AlertPort
import com.pokit.user.UserFixture
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe
import io.mockk.every
import io.mockk.mockk
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.SliceImpl
import java.time.LocalDateTime
import java.util.function.Supplier

class AlertServiceTest : BehaviorSpec({
val alertPort = mockk<AlertPort>()
val now = mockk<Supplier<LocalDateTime>>()

val alertService = AlertService(now, alertPort)

Given("알림 관련 요청이 들어올 때") {
val nowTime = LocalDateTime.of(2024, 8, 15, 15, 30)
val user = UserFixture.getUser()
val pageable = PageRequest.of(0, 10)
val alert1 = AlertFixure.getAlert(user.id, "title1", nowTime.minusDays(1))
val alert2 = AlertFixure.getAlert(user.id, "title2", nowTime)
val alerts = SliceImpl(mutableListOf(alert1, alert2), pageable, false)
every { now.get() } returns nowTime
every { alertPort.loadAllByUserId(user.id, pageable) } returns alerts

When("조회 시") {
val result = alertService.getAlerts(user.id, pageable)
val alertList = result.content
Then("해당 유저의 알림 목록이 조회된다.") {
alertList[0].title shouldBe alert1.title
alertList[1].title shouldBe alert2.title
alertList[0].createdAt shouldBe "1일 전"
alertList[1].createdAt shouldBe "오늘"
}
}
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.pokit.alert.dto.response

import com.pokit.alert.model.Alert
import com.pokit.alert.model.AlertDefault

data class AlertsResponse(
val id: Long,
val userId: Long,
val contentId: Long,
val thumbNail: String,
val title: String,
val body: String = AlertDefault.body,
val createdAt: String
)

fun Alert.toAlertsResponse(dayDifference: Int) = AlertsResponse(
id = this.id,
userId = this.userId,
contentId = this.id,
thumbNail = this.contentThumbNail,
title = this.title,
createdAt = if (dayDifference == 0) "오늘" else "${dayDifference}일 전"
)
10 changes: 10 additions & 0 deletions domain/src/main/kotlin/com/pokit/alert/exception/AlertErrorCode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.pokit.alert.exception

import com.pokit.common.exception.ErrorCode

enum class AlertErrorCode(
override val message: String,
override val code: String
) : ErrorCode {
NOT_FOUND_ALERT("존재하지 않는 알림입니다.", "AL_001")
}
Loading

0 comments on commit d67c2a3

Please sign in to comment.