Skip to content

Commit

Permalink
Api-v0.0.3-4
Browse files Browse the repository at this point in the history
  • Loading branch information
kdomo authored Jul 6, 2023
2 parents d529445 + 9926caa commit 71186af
Show file tree
Hide file tree
Showing 31 changed files with 445 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.depromeet.whatnow.api.image.controller

import com.depromeet.whatnow.api.image.dto.ImageCommentElement
import com.depromeet.whatnow.api.image.dto.ImageUrlResponse
import com.depromeet.whatnow.api.image.usecase.GetPresignedUrlUseCase
import com.depromeet.whatnow.api.image.usecase.ImageCommentReadUseCase
import com.depromeet.whatnow.api.image.usecase.ImageUploadSuccessUseCase
import com.depromeet.whatnow.common.vo.CoordinateVo
import com.depromeet.whatnow.config.s3.ImageFileExtension
Expand All @@ -25,6 +27,7 @@ import javax.validation.Valid
class ImageController(
val getPresignedUrlUseCase: GetPresignedUrlUseCase,
val successUseCase: ImageUploadSuccessUseCase,
val imageCommentReadUseCase: ImageCommentReadUseCase,
) {
@Operation(summary = "약속 이미지 업로드 Presigned URL 발급")
@GetMapping("/images/promises/{promiseId}")
Expand Down Expand Up @@ -60,4 +63,10 @@ class ImageController(
fun userUploadImageSuccess(@PathVariable imageKey: String) {
successUseCase.userUploadImageSuccess(imageKey)
}

@Operation(summary = "이미지 코멘트를 이넘으로 확인합니다. 주의!! 스웨거 이넘 예시 값과 실제 요청했을 때 값이 달라요 실제 요청값 기준으로 해주세요")
@GetMapping("/images/comments")
fun getImageCommentType(): List<ImageCommentElement> {
return imageCommentReadUseCase.execute()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.depromeet.whatnow.api.image.dto

import com.depromeet.whatnow.domains.image.domain.PromiseImageCommentType
import com.depromeet.whatnow.domains.promiseuser.domain.PromiseUserType

data class ImageCommentElement(
val promiseUserType: PromiseUserType,
val comments: List<PromiseImageCommentType>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.depromeet.whatnow.api.image.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.api.image.dto.ImageCommentElement
import com.depromeet.whatnow.domains.image.domain.PromiseImageCommentType

@UseCase
class ImageCommentReadUseCase {
fun execute(): List<ImageCommentElement> {
return PromiseImageCommentType.values().groupBy {
p ->
p.promiseUserType
}.map {
(k, value) ->
ImageCommentElement(k, value)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.depromeet.whatnow.api.promise.dto

import com.depromeet.whatnow.api.interaction.dto.InteractionDto
import com.depromeet.whatnow.domains.promiseuser.domain.PromiseUserType
import com.depromeet.whatnow.domains.user.domain.User

Expand All @@ -8,13 +9,12 @@ data class PromiseUserInfoVo(
val nickname: String,
val isDefaultImg: Boolean,
val promiseUserType: PromiseUserType,
// TODO : Interaction 리스트 ( ex. POOP : 1, MUSIC : 2, ... )
// val interactions: List<Interaction>
val interactions: List<InteractionDto>,
) {
// interaction 기능 추가시 함께 추가할게요.
companion object {
fun of(user: User, promiseUserType: PromiseUserType): PromiseUserInfoVo {
return PromiseUserInfoVo(user.profileImg, user.nickname, user.isDefaultImg, promiseUserType)
fun of(user: User, promiseUserType: PromiseUserType, interactionDtoList: List<InteractionDto>): PromiseUserInfoVo {
val list = interactionDtoList.sortedByDescending { interactionDto -> interactionDto.count }
return PromiseUserInfoVo(user.profileImg, user.nickname, user.isDefaultImg, promiseUserType, list)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.depromeet.whatnow.api.promise.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.api.interaction.dto.InteractionDto
import com.depromeet.whatnow.api.promise.dto.LocationCapture
import com.depromeet.whatnow.api.promise.dto.PromiseDetailDto
import com.depromeet.whatnow.api.promise.dto.PromiseFindDto
import com.depromeet.whatnow.api.promise.dto.PromiseUserInfoVo
import com.depromeet.whatnow.common.vo.UserInfoVo
import com.depromeet.whatnow.config.security.SecurityUtils
import com.depromeet.whatnow.domains.interaction.adapter.InteractionAdapter
import com.depromeet.whatnow.domains.promise.adaptor.PromiseAdaptor
import com.depromeet.whatnow.domains.promise.domain.Promise
import com.depromeet.whatnow.domains.promise.domain.PromiseType
Expand All @@ -23,6 +25,7 @@ class PromiseReadUseCase(
val promiseUserAdaptor: PromiseUserAdaptor,
val userAdapter: UserAdapter,
val userRepository: UserRepository,
val interactionAdapter: InteractionAdapter,
) {
/**
* method desc: 유저가 참여한 약속들을 약속 종류(BEFORE, PAST)에 따라 분리해서 조회
Expand Down Expand Up @@ -115,7 +118,15 @@ class PromiseReadUseCase(
val promiseUsers = promiseUsersByPromiseId.filter { it.promiseId == promise.id }
val promiseUserInfoVos = promiseUsers.mapNotNull { promiseUser ->
val user = users.find { it.id == promiseUser.userId }
user?.let { PromiseUserInfoVo.of(it, promiseUser.promiseUserType!!) }

// 유저의 Interaction 정보를 조회 (인터렉션 개수 순으로 내림차순 정렬)
val interactions =
interactionAdapter.queryAllInteraction(promiseUser.promiseId, promiseUser.userId)
.map { InteractionDto.from(it) }
.sortedByDescending { interactionDto -> interactionDto.count }
user?.let {
PromiseUserInfoVo.of(it, promiseUser.promiseUserType!!, interactions)
}
}

val timeOverLocations = promiseUsers.mapNotNull { promiseUser ->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.depromeet.whatnow.api.image.controller

import com.depromeet.whatnow.api.image.usecase.GetPresignedUrlUseCase
import com.depromeet.whatnow.api.image.usecase.ImageCommentReadUseCase
import com.depromeet.whatnow.api.image.usecase.ImageUploadSuccessUseCase
import com.depromeet.whatnow.common.vo.CoordinateVo
import com.depromeet.whatnow.config.s3.ImageFileExtension
Expand Down Expand Up @@ -28,6 +29,9 @@ class PromiseImageControllerTest {
@MockBean
lateinit var successUseCase: ImageUploadSuccessUseCase

@MockBean
lateinit var imageCommentReadUseCase: ImageCommentReadUseCase

@Autowired
lateinit var mockMvc: MockMvc

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.depromeet.whatnow.api.promise.usecase

import com.depromeet.whatnow.domains.interaction.adapter.InteractionAdapter
import com.depromeet.whatnow.domains.interaction.domain.Interaction
import com.depromeet.whatnow.domains.interaction.domain.InteractionType
import com.depromeet.whatnow.domains.promise.adaptor.PromiseAdaptor
import com.depromeet.whatnow.domains.promise.domain.Promise
import com.depromeet.whatnow.domains.promise.domain.PromiseType
Expand Down Expand Up @@ -41,6 +44,9 @@ class PromiseReadUseCaseTest {
@Mock
private lateinit var userRepository: UserRepository

@Mock
private lateinit var interactionAdapter: InteractionAdapter

@InjectMocks
private lateinit var promiseReadUseCase: PromiseReadUseCase

Expand All @@ -52,6 +58,7 @@ class PromiseReadUseCaseTest {
promiseUserAdaptor = promiseUserAdaptor,
promiseAdaptor = promiseAdaptor,
userAdapter = userAdapter,
interactionAdapter = interactionAdapter,
)
val securityContext = SecurityContextHolder.createEmptyContext()
val authentication = UsernamePasswordAuthenticationToken("1", null, setOf(SimpleGrantedAuthority("ROLE_USER")))
Expand Down Expand Up @@ -92,10 +99,17 @@ class PromiseReadUseCaseTest {
id = 2,
),
)
val interactions = listOf(
Interaction(InteractionType.HEART, 1, 1, 242),
Interaction(InteractionType.MUSIC, 1, 1, 1234),
Interaction(InteractionType.POOP, 1, 1, 12),
Interaction(InteractionType.STEP, 1, 1, 2934),
)

Mockito.`when`(promiseUserAdaptor.findByUserId(userId)).thenReturn(promiseUsers)
Mockito.`when`(promiseAdaptor.queryPromises(listOf(1, 2))).thenReturn(promises)
Mockito.`when`(userAdapter.queryUsers(listOf(1))).thenReturn(users)
Mockito.`when`(interactionAdapter.queryAllInteraction(1, 1)).thenReturn(interactions)

// When
val result = promiseReadUseCase.findPromiseDetailByStatus(PromiseType.BEFORE)
Expand All @@ -110,5 +124,8 @@ class PromiseReadUseCaseTest {
Assertions.assertEquals("Promise 2", result[1].title)
Assertions.assertEquals(promiseTime2, result[1].date)
Assertions.assertEquals(1, result[1].promiseUsers.size)

Assertions.assertEquals(2934, result[0].promiseUsers[0].interactions[0].count)
Assertions.assertEquals(1234, result[0].promiseUsers[0].interactions[1].count)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.depromeet.whatnow.api.promiseuser.usecase

import com.depromeet.whatnow.common.vo.CoordinateVo
import com.depromeet.whatnow.domains.promiseuser.adaptor.PromiseUserAdaptor
import com.depromeet.whatnow.domains.promiseuser.domain.PromiseUser
import com.depromeet.whatnow.domains.promiseuser.service.PromiseUserDomainService
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations

class PromiseUserDomainServiceTest {
@Mock
private lateinit var promiseUserAdaptor: PromiseUserAdaptor

private lateinit var promiseUserDomainService: PromiseUserDomainService

@BeforeEach
fun setUp() {
MockitoAnnotations.openMocks(this)
promiseUserDomainService = PromiseUserDomainService(promiseUserAdaptor = promiseUserAdaptor)
}

@Test
fun `500미터 안에 인접해 있으면 도착했다 정의`() {
val a = PromiseUser(userLocation = CoordinateVo(35.866334, 127.146223), promiseId = 1L, userId = 1L)
val b = CoordinateVo(35.866355, 127.146230)
// 실제 거리 : 2.41878882096224 m
// when and return
val arrived = promiseUserDomainService.isArrived(a, b)
assertEquals(true, arrived)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ const val PROD = "prod"
const val DEV = "dev"
const val LOCAL = "local"
const val WITHDRAW_PREFIX = "withdraw"
const val RADIUS_WAIT_CONFIRM = 200

const val IMAGE_DOMAIN = "https://image.whatnow.kr"
const val ASSERT_IMAGE_DOMAIN = "https://image.whatnow.kr/assert"

const val REDIS_EXPIRE_EVENT_PATTERN = "__keyevent@*__:expired"

val SWAGGER_PATTERNS = arrayOf(
"/swagger-resources/**",
Expand Down
1 change: 1 addition & 0 deletions Whatnow-Domain/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ dependencies {
api("org.springframework.boot:spring-boot-starter-data-jpa")
api("org.springframework.boot:spring-boot-starter-data-redis")
api("com.mysql:mysql-connector-j")
implementation("com.google.geometry:s2-geometry:2.0.0")
implementation(project(":Whatnow-Infrastructure"))
implementation(project(":Whatnow-Common"))
api("com.h2database:h2")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.depromeet.whatnow.config

import com.depromeet.whatnow.consts.REDIS_EXPIRE_EVENT_PATTERN
import com.depromeet.whatnow.domains.promiseactive.listener.RedisExpireEventRedisMessageListener
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.listener.PatternTopic
import org.springframework.data.redis.listener.RedisMessageListenerContainer

@Configuration
class RedisMessageListenerConfig {
@Bean
fun redisMessageListenerContainer(
redisConnectionFactory: RedisConnectionFactory,
redisExpireEventRedisMessageListener: RedisExpireEventRedisMessageListener,
): RedisMessageListenerContainer {
val redisMessageListenerContainer = RedisMessageListenerContainer()
redisMessageListenerContainer.setConnectionFactory(redisConnectionFactory)
redisMessageListenerContainer.addMessageListener(redisExpireEventRedisMessageListener, PatternTopic(REDIS_EXPIRE_EVENT_PATTERN))
return redisMessageListenerContainer
}
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
package com.depromeet.whatnow.domains.image.domain

import com.depromeet.whatnow.consts.ASSERT_IMAGE_DOMAIN
import com.depromeet.whatnow.domains.promiseuser.domain.PromiseUserType
import com.fasterxml.jackson.annotation.JsonFormat

enum class PromiseImageCommentType(val value: String, val promiseUserType: PromiseUserType?) {
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
enum class PromiseImageCommentType(
val promiseUserType: PromiseUserType,
val kr: String,
val code: String,
val image: String,
val imageSmall: String,
) {
// Can LATE
RUNNING("달려가는 중️", PromiseUserType.LATE),
GASPING("헐레벌떡", PromiseUserType.LATE),
LEAVE_SOME("남겨놔!", PromiseUserType.LATE),
WAIT_A_BIT("조금만 기다려", PromiseUserType.LATE),
SORRY_LATE("늦어서 미안해", PromiseUserType.LATE),
RUNNING(PromiseUserType.LATE, "달려가는 중️", "RUNNING", "$ASSERT_IMAGE_DOMAIN/comments/RUNNING.svg", "$ASSERT_IMAGE_DOMAIN/comments/RUNNING_SMALL.svg"),
GASPING(PromiseUserType.LATE, "헐레벌떡", "GASPING", "$ASSERT_IMAGE_DOMAIN/comments/GASPING.svg", "$ASSERT_IMAGE_DOMAIN/comments/GASPING_SMALL.svg"),
LEAVE_SOME(PromiseUserType.LATE, "남겨놔!", "LEAVE_SOME", "$ASSERT_IMAGE_DOMAIN/comments/LEAVE_SOME.svg", "$ASSERT_IMAGE_DOMAIN/comments/LEAVE_SOME_SMALL.svg"),
WAIT_A_BIT(PromiseUserType.LATE, "조금만 기다려", "WAIT_A_BIT", "$ASSERT_IMAGE_DOMAIN/comments/WAIT_A_BIT.svg", "$ASSERT_IMAGE_DOMAIN/comments/WAIT_A_BIT_SMALL.svg"),
SORRY_LATE(PromiseUserType.LATE, "늦어서 미안해", "SORRY_LATE", "$ASSERT_IMAGE_DOMAIN/comments/SORRY_LATE.svg", "$ASSERT_IMAGE_DOMAIN/comments/SORRY_LATE_SMALL.svg"),

// Can WAIT
WHAT_ARE_YOU_DOING("뭐해 심심해", PromiseUserType.WAIT),
WHAT_TIME_IS_IT_NOW("지금이 몇시야!", PromiseUserType.WAIT),
DID_YOU_COME("왔나..?", PromiseUserType.WAIT),
I_LL_EAT_FIRST("먼저 먹을게~", PromiseUserType.WAIT),
WHERE_ARE_YOU("너 어디야?", PromiseUserType.WAIT),
WHAT_ARE_YOU_DOING(PromiseUserType.WAIT, "뭐해 심심해", "WHAT_ARE_YOU_DOING", "$ASSERT_IMAGE_DOMAIN/comments/WHAT_ARE_YOU_DOING.svg", "$ASSERT_IMAGE_DOMAIN/comments/WHAT_ARE_YOU_DOING_SMALL.svg"),
WHAT_TIME_IS_IT_NOW(PromiseUserType.WAIT, "지금이 몇시야!", "WHAT_TIME_IS_IT_NOW", "$ASSERT_IMAGE_DOMAIN/comments/WHAT_TIME_IS_IT_NOW.svg", "$ASSERT_IMAGE_DOMAIN/comments/WHAT_TIME_IS_IT_NOW_SMALL.svg"),
DID_YOU_COME(PromiseUserType.WAIT, "왔나..?", "DID_YOU_COME", "$ASSERT_IMAGE_DOMAIN/comments/DID_YOU_COME.svg", "$ASSERT_IMAGE_DOMAIN/comments/DID_YOU_COME_SMALL.svg"),
I_LL_EAT_FIRST(PromiseUserType.WAIT, "먼저 먹을게~", "I_LL_EAT_FIRST", "$ASSERT_IMAGE_DOMAIN/comments/I_LL_EAT_FIRST.svg", "$ASSERT_IMAGE_DOMAIN/comments/I_LL_EAT_FIRST_SMALL.svg"),
WHERE_ARE_YOU(PromiseUserType.WAIT, "너 어디야?", "WHERE_ARE_YOU", "$ASSERT_IMAGE_DOMAIN/comments/WHERE_ARE_YOU.svg", "$ASSERT_IMAGE_DOMAIN/comments/WHERE_ARE_YOU_SMALL.svg"),
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
package com.depromeet.whatnow.domains.progresshistory.domain

import com.depromeet.whatnow.consts.ASSERT_IMAGE_DOMAIN
import com.fasterxml.jackson.annotation.JsonFormat

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
enum class PromiseProgress(
val progressGroup: PromiseProgressGroup,
val kr: String,
val code: String,
val image: String,
) {
SHOWER(PromiseProgressGroup.PREPARING, "씻는 중", "SHOWER"),
LEAVE_SOON(PromiseProgressGroup.PREPARING, "곧 나가", "LEAVE_SOON"),
BED(PromiseProgressGroup.PREPARING, "아직 침대", "BED"),
WALKING(PromiseProgressGroup.MOVING, "걸어가는 중", "WALKING"),
RUNNING(PromiseProgressGroup.MOVING, "뛰고 있어", "RUNNING"),
BOARDING(PromiseProgressGroup.MOVING, "탑승 중", "BOARDING"),
SORRY(PromiseProgressGroup.LATE, "미안해", "SORRY"),
TEAR(PromiseProgressGroup.LATE, "눈물 줄줄", "TEAR"),
URGENCY(PromiseProgressGroup.LATE, "급하다!!", "URGENCY"),
AFTER_SOON(PromiseProgressGroup.EXPECTED_TIME, "곧 도착", "AFTER_SOON"),
AFTER_5(PromiseProgressGroup.EXPECTED_TIME, "5분 뒤 도착", "AFTER_5"),
AFTER_10(PromiseProgressGroup.EXPECTED_TIME, "10분 뒤 도착", "AFTER_10"),
DEFAULT(PromiseProgressGroup.DEFAULT, "기본", "DEFAULT"),
SHOWER(PromiseProgressGroup.PREPARING, "씻는 중", "SHOWER", "$ASSERT_IMAGE_DOMAIN/progresses/SHOWER.svg"),
LEAVE_SOON(PromiseProgressGroup.PREPARING, "곧 나가", "LEAVE_SOON", "$ASSERT_IMAGE_DOMAIN/progresses/LEAVE_SOON.svg"),
BED(PromiseProgressGroup.PREPARING, "아직 침대", "BED", "$ASSERT_IMAGE_DOMAIN/progresses/BED.svg"),
WALKING(PromiseProgressGroup.MOVING, "걸어가는 중", "WALKING", "$ASSERT_IMAGE_DOMAIN/progresses/WALKING.svg"),
RUNNING(PromiseProgressGroup.MOVING, "뛰고 있어", "RUNNING", "$ASSERT_IMAGE_DOMAIN/progresses/RUNNING.svg"),
BOARDING(PromiseProgressGroup.MOVING, "탑승 중", "BOARDING", "$ASSERT_IMAGE_DOMAIN/progresses/BOARDING.svg"),
SORRY(PromiseProgressGroup.LATE, "미안해", "SORRY", "$ASSERT_IMAGE_DOMAIN/progresses/SORRY.svg"),
TEAR(PromiseProgressGroup.LATE, "눈물 줄줄", "TEAR", "$ASSERT_IMAGE_DOMAIN/progresses/TEAR.svg"),
URGENCY(PromiseProgressGroup.LATE, "급하다!!", "URGENCY", "$ASSERT_IMAGE_DOMAIN/progresses/URGENCY.svg"),
AFTER_SOON(PromiseProgressGroup.EXPECTED_TIME, "곧 도착", "AFTER_SOON", "$ASSERT_IMAGE_DOMAIN/progresses/AFTER_SOON.svg"),
AFTER_5(PromiseProgressGroup.EXPECTED_TIME, "5분 뒤 도착", "AFTER_5", "$ASSERT_IMAGE_DOMAIN/progresses/AFTER_5.svg"),
AFTER_10(PromiseProgressGroup.EXPECTED_TIME, "10분 뒤 도착", "AFTER_10", "$ASSERT_IMAGE_DOMAIN/progresses/AFTER_10.svg"),
DEFAULT(PromiseProgressGroup.DEFAULT, "기본", "DEFAULT", "$ASSERT_IMAGE_DOMAIN/progresses/DEFAULT.svg"),
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import javax.transaction.Transactional
class PromiseDomainService(
val promiseAdaptor: PromiseAdaptor,
) {

fun registerPromise(
endTime: LocalDateTime,
title: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.depromeet.whatnow.domains.promiseactive.adapter

import com.depromeet.whatnow.annotation.Adapter
import com.depromeet.whatnow.domains.promiseactive.domain.PromiseActiveRedisEntity
import com.depromeet.whatnow.domains.promiseactive.repository.PromiseActiveRepository

@Adapter
class PromiseActiveAdapter(
val promiseActiveRepository: PromiseActiveRepository,
) {
fun save(promiseActiveRedisEntity: PromiseActiveRedisEntity): PromiseActiveRedisEntity {
return promiseActiveRepository.save(promiseActiveRedisEntity)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.depromeet.whatnow.domains.promiseactive.domain

import org.springframework.data.annotation.Id
import org.springframework.data.redis.core.RedisHash
import org.springframework.data.redis.core.TimeToLive

@RedisHash(value = "promiseActive")
class PromiseActiveRedisEntity(
@Id
var key: String,

@TimeToLive // TTL
var ttl: Long,
)
Loading

0 comments on commit 71186af

Please sign in to comment.