-
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.
[Feature/445] 보틀 조회 V2 API 구현한다 (#452)
* feat: 보틀 조회 v2 api 구현 * feat: 스크립트 수정
- Loading branch information
Showing
10 changed files
with
289 additions
and
32 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
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
32 changes: 32 additions & 0 deletions
32
api/src/main/kotlin/com/nexters/bottles/api/bottle/controller/BottleControllerV2.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,32 @@ | ||
package com.nexters.bottles.api.bottle.controller | ||
|
||
import com.nexters.bottles.api.bottle.facade.BottleFacadeV2 | ||
import com.nexters.bottles.api.bottle.facade.dto.RandomBottleListResponse | ||
import com.nexters.bottles.api.bottle.facade.dto.SentBottleListResponse | ||
import com.nexters.bottles.api.global.interceptor.AuthRequired | ||
import com.nexters.bottles.api.global.resolver.AuthUserId | ||
import io.swagger.annotations.ApiOperation | ||
import org.springframework.web.bind.annotation.GetMapping | ||
import org.springframework.web.bind.annotation.RequestMapping | ||
import org.springframework.web.bind.annotation.RestController | ||
|
||
@RestController | ||
@RequestMapping("/api/v2/bottles") | ||
class BottleControllerV2( | ||
private val bottleFacadeV2: BottleFacadeV2 | ||
) { | ||
|
||
@ApiOperation("모래사장 - 랜덤으로 받은 보틀 목록 조회하기") | ||
@GetMapping("/random") | ||
@AuthRequired | ||
fun getRandomBottlesList(@AuthUserId userId: Long): RandomBottleListResponse { | ||
return bottleFacadeV2.getRandomBottles(userId) | ||
} | ||
|
||
@ApiOperation("호감 - 호감을 받은 보틀 목록 조회하기") | ||
@GetMapping("/sent") | ||
@AuthRequired | ||
fun getSentBottlesList(@AuthUserId userId: Long): SentBottleListResponse { | ||
return bottleFacadeV2.getSentBottles(userId) | ||
} | ||
} |
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
142 changes: 142 additions & 0 deletions
142
api/src/main/kotlin/com/nexters/bottles/api/bottle/facade/BottleFacadeV2.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,142 @@ | ||
package com.nexters.bottles.api.bottle.facade | ||
|
||
import com.nexters.bottles.api.bottle.event.dto.BottleMatchEventDto | ||
import com.nexters.bottles.api.bottle.facade.dto.RandomBottleDto | ||
import com.nexters.bottles.api.bottle.facade.dto.RandomBottleListResponse | ||
import com.nexters.bottles.api.bottle.facade.dto.SentBottleDto | ||
import com.nexters.bottles.api.bottle.facade.dto.SentBottleListResponse | ||
import com.nexters.bottles.api.bottle.util.getLastActivatedAtInKorean | ||
import com.nexters.bottles.api.user.component.event.dto.UserApplicationEventDto | ||
import com.nexters.bottles.app.bottle.domain.Bottle | ||
import com.nexters.bottles.app.bottle.domain.enum.BottleStatus | ||
import com.nexters.bottles.app.bottle.service.BottleService | ||
import com.nexters.bottles.app.user.domain.User | ||
import com.nexters.bottles.app.user.service.BlockContactListService | ||
import com.nexters.bottles.app.user.service.UserReportService | ||
import com.nexters.bottles.app.user.service.UserService | ||
import org.springframework.context.ApplicationEventPublisher | ||
import org.springframework.stereotype.Component | ||
import java.time.LocalDateTime | ||
import java.time.LocalTime | ||
|
||
@Component | ||
class BottleFacadeV2( | ||
private val bottleService: BottleService, | ||
private val userService: UserService, | ||
private val userReportService: UserReportService, | ||
private val blockContactListService: BlockContactListService, | ||
private val applicationEventPublisher: ApplicationEventPublisher, | ||
) { | ||
|
||
fun getRandomBottles(userId: Long): RandomBottleListResponse { | ||
val user = userService.findByIdAndNotDeleted(userId) | ||
val blockUserIds = blockContactListService.findAllByUserId(userId).map { it.userId }.toSet() // 내가 차단한 유저 | ||
val blockedMeUserIds = blockContactListService.findAllByPhoneNumber( | ||
user.phoneNumber ?: throw IllegalStateException("핸드폰 번호를 등록해주세요") | ||
).map { it.userId }.toSet() // 나를 차단한 유저 | ||
|
||
val matchingHour = 18 | ||
bottleService.matchRandomBottle(user, matchingHour, blockUserIds, blockedMeUserIds) | ||
?.also { | ||
applicationEventPublisher.publishEvent( | ||
BottleMatchEventDto( | ||
sourceUserId = it.sourceUser.id, | ||
targetUserId = it.targetUser.id, | ||
) | ||
) | ||
} | ||
|
||
val bottles = bottleService.getNewBottlesByBottleStatus(user, setOf(BottleStatus.RANDOM)) | ||
val randomBottles = bottles.map { toRandomBottleDto(it, userId) } | ||
|
||
return RandomBottleListResponse( | ||
randomBottles = randomBottles, | ||
nextBottleLeftHours = getNextBottleLeftHours(LocalDateTime.now()) | ||
).also { | ||
publishUserApplicationEvent(user) | ||
} | ||
} | ||
|
||
private fun getNextBottleLeftHours(now: LocalDateTime): Int { | ||
return if (now.toLocalTime() > LocalTime.of(18, 0)) { | ||
18 + (LocalTime.MAX.hour - now.hour) | ||
} else { | ||
LocalTime.of(18, 0).hour - now.hour | ||
} | ||
} | ||
|
||
private fun toRandomBottleDto(bottle: Bottle, userId: Long): RandomBottleDto { | ||
return RandomBottleDto( | ||
id = bottle.id, | ||
userId = bottle.findOtherUserId(userId = userId), | ||
userName = bottle.sourceUser.getMaskedName(), | ||
age = bottle.sourceUser.getKoreanAge(), | ||
mbti = bottle.sourceUser.userProfile?.profileSelect?.mbti, | ||
keyword = bottle.sourceUser.userProfile?.profileSelect?.keyword, | ||
userImageUrl = bottle.sourceUser.userProfile?.blurredImageUrl, | ||
expiredAt = bottle.expiredAt, | ||
lastActivatedAt = getLastActivatedAtInKorean( | ||
basedAt = bottle.sourceUser.lastActivatedAt, | ||
now = LocalDateTime.now() | ||
) | ||
) | ||
} | ||
|
||
fun getSentBottles(userId: Long): SentBottleListResponse { | ||
val user = userService.findByIdAndNotDeleted(userId) | ||
val bottles = bottleService.getNewBottlesByBottleStatus(user, setOf(BottleStatus.SENT)) | ||
|
||
if (bottles.isEmpty()) { | ||
return SentBottleListResponse( | ||
sentBottles = emptyList() | ||
).also { | ||
publishUserApplicationEvent(user) | ||
} | ||
} | ||
|
||
val blockUserIds = blockContactListService.findAllByUserId(userId).map { it.userId }.toSet() // 내가 차단한 유저 | ||
val blockedMeUserIds = blockContactListService.findAllByPhoneNumber( | ||
user.phoneNumber ?: throw IllegalStateException("핸드폰 번호를 등록해주세요") | ||
).map { it.userId }.toSet() // 나를 차단한 유저 | ||
val reportUserIds = userReportService.getReportRespondentList(userId) | ||
.map { it.respondentUserId } | ||
.toSet() | ||
|
||
val sentBottles = bottles.map { toSentBottleDto(it, userId) } | ||
.filter { it.userId !in reportUserIds } | ||
.filter { it.userId !in blockUserIds } | ||
.filter { it.userId !in blockedMeUserIds } | ||
|
||
return SentBottleListResponse( | ||
sentBottles = sentBottles | ||
).also { | ||
publishUserApplicationEvent(user) | ||
} | ||
} | ||
|
||
private fun toSentBottleDto(bottle: Bottle, userId: Long): SentBottleDto { | ||
return SentBottleDto( | ||
id = bottle.id, | ||
userId = bottle.findOtherUserId(userId = userId), | ||
userName = bottle.sourceUser.getMaskedName(), | ||
age = bottle.sourceUser.getKoreanAge(), | ||
mbti = bottle.sourceUser.userProfile?.profileSelect?.mbti, | ||
keyword = bottle.sourceUser.userProfile?.profileSelect?.keyword, | ||
userImageUrl = bottle.sourceUser.userProfile?.blurredImageUrl, | ||
expiredAt = bottle.expiredAt, | ||
lastActivatedAt = getLastActivatedAtInKorean( | ||
basedAt = bottle.sourceUser.lastActivatedAt, | ||
now = LocalDateTime.now() | ||
) | ||
) | ||
} | ||
|
||
private fun publishUserApplicationEvent(user: User) { | ||
applicationEventPublisher.publishEvent( | ||
UserApplicationEventDto( | ||
userId = user.id, | ||
basedAt = LocalDateTime.now(), | ||
) | ||
) | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
api/src/main/kotlin/com/nexters/bottles/api/bottle/facade/dto/RandomBottleListResponse.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,23 @@ | ||
package com.nexters.bottles.api.bottle.facade.dto | ||
|
||
import com.fasterxml.jackson.annotation.JsonFormat | ||
import java.time.LocalDateTime | ||
|
||
data class RandomBottleListResponse( | ||
val randomBottles: List<RandomBottleDto>, | ||
val nextBottleLeftHours: Int, | ||
) | ||
|
||
data class RandomBottleDto( | ||
val id: Long, | ||
val userId: Long, | ||
val userName: String?, | ||
val age: Int, | ||
val mbti: String?, | ||
val keyword: List<String>?, | ||
val userImageUrl: String?, | ||
val lastActivatedAt: String?, | ||
|
||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | ||
val expiredAt: LocalDateTime | ||
) |
22 changes: 22 additions & 0 deletions
22
api/src/main/kotlin/com/nexters/bottles/api/bottle/facade/dto/SentBottleListResponse.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,22 @@ | ||
package com.nexters.bottles.api.bottle.facade.dto | ||
|
||
import com.fasterxml.jackson.annotation.JsonFormat | ||
import java.time.LocalDateTime | ||
|
||
data class SentBottleListResponse( | ||
val sentBottles: List<SentBottleDto>, | ||
) | ||
|
||
data class SentBottleDto( | ||
val id: Long, | ||
val userId: Long, | ||
val userName: String?, | ||
val age: Int, | ||
val mbti: String?, | ||
val keyword: List<String>?, | ||
val userImageUrl: String?, | ||
val lastActivatedAt: String?, | ||
|
||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | ||
val expiredAt: LocalDateTime | ||
) |
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
Oops, something went wrong.