Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

main 배포 #123

Merged
merged 4 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.backgu.amaker.api.notification.config

import com.backgu.amaker.api.notification.dto.request.NotificationQueryRequest
import com.backgu.amaker.api.notification.dto.response.EventNotificationViewResponse
import com.backgu.amaker.common.http.response.ApiResult
import com.backgu.amaker.common.security.jwt.authentication.JwtAuthentication
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable

interface EventNotificationSwagger {
@Operation(summary = "이벤트 알림 조회", description = "이벤트 알림을 조회합니다.")
@ApiResponses(
value = [
ApiResponse(
responseCode = "200",
description = "이벤트 알림 리스트 성공",
),
],
)
fun getNotifications(
@AuthenticationPrincipal token: JwtAuthentication,
@PathVariable("workspace-id") workspaceId: Long,
@ModelAttribute notificationQueryRequest: NotificationQueryRequest,
): ResponseEntity<ApiResult<EventNotificationViewResponse>>
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package com.backgu.amaker.api.notification.config

import com.backgu.amaker.application.notification.service.NotificationQueryService
import com.backgu.amaker.infra.jpa.notification.repository.EventNotificationRepository
import com.backgu.amaker.infra.notification.kafka.config.NotificationKafkaProducerConfig
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import

@Configuration
@Import(NotificationKafkaProducerConfig::class)
class NotificationConfig
class NotificationConfig {
@Bean
fun notificationQueryService(notificationRepository: EventNotificationRepository): NotificationQueryService =
NotificationQueryService(notificationRepository)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package com.backgu.amaker.api.notification.controller

import com.backgu.amaker.api.notification.config.EventNotificationSwagger
import com.backgu.amaker.api.notification.dto.request.NotificationQueryRequest
import com.backgu.amaker.api.notification.dto.response.EventNotificationViewResponse
import com.backgu.amaker.api.notification.service.NotificationFacadeService
import com.backgu.amaker.common.http.ApiHandler
import com.backgu.amaker.common.http.response.ApiResult
import com.backgu.amaker.common.security.jwt.authentication.JwtAuthentication
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Sort
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ModelAttribute
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/api/v1/workspaces/{workspace-id}/notifications")
class EventNotificationController(
private val notificationFacadeService: NotificationFacadeService,
private val apiHandler: ApiHandler,
) : EventNotificationSwagger {
@GetMapping
override fun getNotifications(
@AuthenticationPrincipal token: JwtAuthentication,
@PathVariable("workspace-id") workspaceId: Long,
@ModelAttribute notificationQueryRequest: NotificationQueryRequest,
): ResponseEntity<ApiResult<EventNotificationViewResponse>> {
val pageable =
PageRequest.of(
notificationQueryRequest.page,
notificationQueryRequest.size,
Sort.by("id").ascending(),
)

return ResponseEntity.ok(
apiHandler.onSuccess(
EventNotificationViewResponse.of(
notificationFacadeService.getNotifications(
token.id,
workspaceId,
pageable,
),
),
),
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.backgu.amaker.api.notification.controller

import com.backgu.amaker.api.event.dto.response.ReplyEventDetailResponse
import com.backgu.amaker.common.http.response.ApiResult
import com.backgu.amaker.common.security.jwt.authentication.JwtAuthentication
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.responses.ApiResponses
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.ResponseEntity
import org.springframework.security.core.annotation.AuthenticationPrincipal
import org.springframework.web.bind.annotation.PathVariable

@Tag(name = "notification", description = "알림 API")
interface NotificationSwagger {
@Operation(summary = "알림 리스트 조회", description = "알림 내역들을 조회합니다.")
@ApiResponses(
value = [
ApiResponse(
responseCode = "200",
description = "알림내역 조회 성공",
),
],
)
fun getNotifications(
@AuthenticationPrincipal token: JwtAuthentication,
@PathVariable("workspace-id") workspaceId: Long,
): ResponseEntity<ApiResult<ReplyEventDetailResponse>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.backgu.amaker.api.notification.dto

import com.backgu.amaker.domain.notifiacation.EventNotification

data class EventNotificationDto(
val id: Long,
val title: String,
val content: String,
val userId: String,
val eventId: Long,
) {
companion object {
fun from(eventNotification: EventNotification): EventNotificationDto =
EventNotificationDto(
id = eventNotification.id,
title = eventNotification.title,
content = eventNotification.content,
userId = eventNotification.userId,
eventId = eventNotification.eventId,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.backgu.amaker.api.notification.dto

data class NotificationQueryDto(
val notificationId: Long,
val size: Int,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.backgu.amaker.api.notification.dto.request

import com.backgu.amaker.api.notification.dto.NotificationQueryDto
import io.swagger.v3.oas.annotations.media.Schema

data class NotificationQueryRequest(
@Schema(description = "읽어올 페이지 번호", example = "2", defaultValue = "0")
val page: Int = 0,
@Schema(description = "읽어올 응답의 개수", example = "100", defaultValue = "20")
val size: Int = 20,
) {
fun toDto(notificationId: Long): NotificationQueryDto =
NotificationQueryDto(
notificationId = notificationId,
size = size,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.backgu.amaker.api.notification.dto.response

import com.backgu.amaker.api.notification.dto.EventNotificationDto
import io.swagger.v3.oas.annotations.media.Schema

data class EventNotificationResponse(
@Schema(description = "이벤트 id", example = "1")
val id: Long,
@Schema(description = "이벤트 제목", example = "이벤트 제목")
val title: String,
@Schema(description = "이벤트 내용", example = "이벤트 내용")
val content: String,
@Schema(description = "유저 id", example = "2")
val userId: String,
@Schema(description = "이벤트 id", example = "2")
val eventId: Long,
) {
companion object {
fun of(eventNotification: EventNotificationDto) =
EventNotificationResponse(
id = eventNotification.id,
title = eventNotification.title,
content = eventNotification.content,
userId = eventNotification.userId,
eventId = eventNotification.eventId,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.backgu.amaker.api.notification.dto.response

import com.backgu.amaker.api.notification.dto.EventNotificationDto
import com.backgu.amaker.common.http.response.PageResponse
import org.springframework.data.domain.Page

class EventNotificationViewResponse(
override val content: List<EventNotificationResponse>,
override val pageNumber: Int,
override val pageSize: Int,
override val totalElements: Long,
override val totalPages: Int,
override val hasNext: Boolean,
override val hasPrevious: Boolean,
override val isFirst: Boolean,
override val isLast: Boolean,
) : PageResponse<EventNotificationResponse> {
companion object {
fun of(eventNotifications: Page<EventNotificationDto>): EventNotificationViewResponse {
val content = eventNotifications.content.map { EventNotificationResponse.of(it) }
return EventNotificationViewResponse(
content = content,
pageNumber = eventNotifications.number,
pageSize = eventNotifications.size,
totalElements = eventNotifications.totalElements,
totalPages = eventNotifications.totalPages,
hasNext = eventNotifications.hasNext(),
hasPrevious = eventNotifications.hasPrevious(),
isFirst = eventNotifications.isFirst,
isLast = eventNotifications.isLast,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.backgu.amaker.api.notification.service

import com.backgu.amaker.api.notification.dto.EventNotificationDto
import com.backgu.amaker.application.event.service.EventAssignedUserService
import com.backgu.amaker.application.event.service.ReactionCommentService
import com.backgu.amaker.application.event.service.ReactionEventService
import com.backgu.amaker.application.event.service.ReactionOptionService
import com.backgu.amaker.application.event.service.ReplyCommentService
import com.backgu.amaker.application.event.service.ReplyEventService
import com.backgu.amaker.application.notification.service.NotificationQueryService
import com.backgu.amaker.application.user.service.UserService
import com.backgu.amaker.application.workspace.WorkspaceUserService
import org.springframework.context.ApplicationEventPublisher
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional(readOnly = true)
class NotificationFacadeService(
private val userService: UserService,
private val replyEventService: ReplyEventService,
private val reactionEventService: ReactionEventService,
private val eventAssignedUserService: EventAssignedUserService,
private val replyCommentService: ReplyCommentService,
private val reactionCommentService: ReactionCommentService,
private val reactionOptionService: ReactionOptionService,
private val workspaceUserService: WorkspaceUserService,
private val notificationQueryService: NotificationQueryService,
private val eventPublisher: ApplicationEventPublisher,
) {
fun getNotifications(
userId: String,
workspaceId: Long,
pageable: Pageable,
): Page<EventNotificationDto> {
workspaceUserService.validateUserInWorkspace(userId, workspaceId)

return notificationQueryService.getNotification(userId, workspaceId, pageable).map { EventNotificationDto.from(it) }
}
}
43 changes: 0 additions & 43 deletions api/src/main/resources/logback-spring.xml

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import kotlin.test.Test

@DisplayName("EventFacadeService 테스트")
@Transactional
class EventCommentFacadeServiceTest : IntegrationTest() {
class NotificationFacadeServiceTest : IntegrationTest() {
@Autowired
lateinit var eventCommentFacadeService: EventCommentFacadeService

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class ReactionEvent(
updatedAt: LocalDateTime = LocalDateTime.now(),
) : Event(id, eventTitle, deadLine, notificationStartTime, notificationInterval, createdAt, updatedAt) {
companion object {
const val EVENT_TYPE = "REPLY"
const val EVENT_TYPE = "REACTION"
}

fun createReactionOption(contents: List<String>) =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.backgu.amaker.domain.notifiacation

class EventNotification(
val id: Long,
val title: String,
val content: String,
val userId: String,
val eventId: Long,
)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,5 @@ interface Notification : Serializable {
val keyPrefix: String
val keyValue: String

fun getNotificationKey(): String {
return "$keyPrefix:$keyValue"
}
fun getNotificationKey(): String = "$keyPrefix:$keyValue"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.backgu.amaker.application.notification.service

import com.backgu.amaker.domain.notifiacation.EventNotification
import com.backgu.amaker.infra.jpa.notification.repository.EventNotificationRepository
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
@Transactional(readOnly = true)
class NotificationQueryService(
private val eventNotificationRepository: EventNotificationRepository,
) {
fun getNotification(
userId: String,
workspaceId: Long,
page: Pageable,
): Page<EventNotification> = eventNotificationRepository.findByUserId(userId, workspaceId, page).map { it.toDomain() }
}
Loading
Loading