Skip to content

Commit

Permalink
MARA-55 : 화면설계서 기반 냉장고, 친구 추가 API 개발, 리팩토링 (#25)
Browse files Browse the repository at this point in the history
* FriendshipService @transactional 적용

* UserNameResponse -> UserFriendResponse 이름 변경

* 친구 삭제 기능 FriendshipDeleteRequest -> List<FriendshipDeleteRequest> 변경

* 친구 수 조회 기능 구현

* FriendRefrigerator Controller 껍데기 구현

* 자신의 냉장고 리스트 조회 기능 구현

* 냉장고 생성 기능 리팩토링 (로그인 한 사용자의 냉장고만 생성 가능하도록 변경)

* 친구 냉장고 최신 근황 조회 기능 단순 구현

* 친구 냉장고 최근 근황 조회 기능 개선

* 친구 냉장고 최근 근황 조회 기능 오류 해결

* Pageable 적용

* ktlintFormat 적용

* 리뷰 사항 반영

1. FriendRefrigeratorDto 삭제

2. userPageable, ingredientPageable 적용
동일 Pageable 객체 사용으로 인해 @qualifier 적용

3. for (friendship: Friendship in friendshipList) -> friendshipList.forEach { friendshipRepository.delete(it) } 변경

* ktlintFormat 적용

* @PageableDefault 제거
  • Loading branch information
jhkang1517 authored Feb 16, 2024
1 parent 6e26469 commit d6c0e81
Show file tree
Hide file tree
Showing 16 changed files with 181 additions and 30 deletions.
20 changes: 20 additions & 0 deletions src/main/kotlin/mara/server/config/pageable/PageableConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package mara.server.config.pageable

import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.data.domain.PageRequest
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort

@Configuration
class PageableConfig {

@Bean
@Qualifier("userPageable")
fun userPageable(): Pageable = PageRequest.of(0, 5, Sort.Direction.DESC, "ingredientAddDate")

@Bean
@Qualifier("ingredientPageable")
fun ingredientPageable(): Pageable = PageRequest.of(0, 4, Sort.Direction.DESC, "addDate")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package mara.server.domain.friend

import mara.server.common.CommonResponse
import mara.server.common.success
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/friend-refrigs")
class FriendRefrigeratorController(
private val friendRefrigeratorService: FriendRefrigeratorService
) {

@GetMapping("/recent")
fun getRecentFriendRefrigeratorList(
@Qualifier("userPageable")
userPageable: Pageable,
@Qualifier("ingredientPageable")
ingredientPageable: Pageable,
): CommonResponse<Page<FriendRefrigeratorResponse>> {
return success(friendRefrigeratorService.getRecentFriendRefrigeratorList(userPageable, ingredientPageable))
}
}
28 changes: 28 additions & 0 deletions src/main/kotlin/mara/server/domain/friend/FriendRefrigeratorDto.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package mara.server.domain.friend

import mara.server.domain.ingredient.Ingredient
import mara.server.domain.refrigerator.Refrigerator
import mara.server.domain.user.User
import org.springframework.data.domain.Page

data class FriendRefrigeratorResponse(
val nickname: String,
val refrigeratorId: Long,
val friendRefrigeratorIngredientGroupList: Page<FriendRefrigeratorIngredient>
) {
constructor(user: User, refrigerator: Refrigerator, ingredientList: Page<Ingredient>) : this(
nickname = user.nickName,
refrigeratorId = refrigerator.refrigeratorId,
friendRefrigeratorIngredientGroupList = ingredientList.map { FriendRefrigeratorIngredient(it) }
)
}

data class FriendRefrigeratorIngredient(
val name: String,
val iconImage: String,
) {
constructor(ingredient: Ingredient) : this(
name = ingredient.name,
iconImage = ingredient.iconImage
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package mara.server.domain.friend

import mara.server.domain.ingredient.IngredientDetailRepository
import mara.server.domain.refrigerator.RefrigeratorRepository
import mara.server.domain.user.UserService
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.stereotype.Service

@Service
class FriendRefrigeratorService(
private val userService: UserService,
private val friendshipRepository: FriendshipRepository,
private val refrigeratorRepository: RefrigeratorRepository,
private val ingredientDetailRepository: IngredientDetailRepository
) {

fun getRecentFriendRefrigeratorList(userPageable: Pageable, ingredientPageable: Pageable): Page<FriendRefrigeratorResponse> {
val currentLoginUser = userService.getCurrentLoginUser()
val friendshipList = friendshipRepository.findAllByFromUser(currentLoginUser)
.orElseThrow { NoSuchElementException("친구 관계가 존재하지 않습니다.") }

val userList = friendshipList.map { it.toUser }
val refrigeratorList = refrigeratorRepository.findRefrigeratorByUserIn(userList, userPageable)

val friendRefrigeratorResponseList = refrigeratorList.map { refrig ->
val ingredientDetailList = ingredientDetailRepository
.findByRefrigeratorAndIsDeletedIsFalse(refrig, ingredientPageable)
val ingredientList = ingredientDetailList.map { it.ingredient }
FriendRefrigeratorResponse(refrig.user, refrig, ingredientList)
}

return friendRefrigeratorResponseList
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package mara.server.domain.friend

import mara.server.common.CommonResponse
import mara.server.common.success
import mara.server.domain.user.UserNameResponse
import mara.server.domain.user.UserFriendResponse
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
Expand All @@ -21,12 +21,17 @@ class FriendshipController(
}

@GetMapping
fun getFriendshipList(): CommonResponse<List<UserNameResponse>> {
fun getFriendshipList(): CommonResponse<List<UserFriendResponse>> {
return success(friendshipService.getFriendshipList())
}

@GetMapping("/count")
fun getFriendshipCount(): CommonResponse<Long> {
return success(friendshipService.getFriendshipCount())
}

@PostMapping("/delete")
fun deleteFriendship(@RequestBody friendshipDeleteRequest: FriendshipDeleteRequest): CommonResponse<String> {
return success(friendshipService.deleteFriendship(friendshipDeleteRequest))
fun deleteFriendship(@RequestBody friendshipDeleteRequestList: List<FriendshipDeleteRequest>): CommonResponse<String> {
return success(friendshipService.deleteFriendship(friendshipDeleteRequestList))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ interface FriendshipRepository : JpaRepository<Friendship, Long> {
user: User
): Optional<List<Friendship>>

fun countByFromUser(
user: User
): Long

@Query("select f from Friendship f where (f.fromUser = ?1 and f.toUser = ?2) or (f.fromUser = ?2 and f.toUser = ?1)")
fun findAllByFromUserAndToUser(
fromUser: User,
Expand Down
33 changes: 21 additions & 12 deletions src/main/kotlin/mara/server/domain/friend/FriendshipService.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package mara.server.domain.friend

import mara.server.domain.user.User
import mara.server.domain.user.UserNameResponse
import mara.server.domain.user.UserFriendResponse
import mara.server.domain.user.UserRepository
import mara.server.domain.user.UserService
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class FriendshipService(
Expand All @@ -16,6 +17,7 @@ class FriendshipService(
private val ok = "ok"
private val deleted = "deleted"

@Transactional
fun createFriendship(friendshipRequest: FriendshipRequest): String {
val currentUserId = userService.getCurrentLoginUser().userId
val fromUser = userRepository.findById(currentUserId)
Expand All @@ -29,31 +31,38 @@ class FriendshipService(
return ok
}

fun getFriendshipList(): List<UserNameResponse> {
fun getFriendshipList(): List<UserFriendResponse> {
val currentLoginUser = userService.getCurrentLoginUser()
val friendshipList = friendshipRepository.findAllByFromUser(currentLoginUser)
.orElseThrow { NoSuchElementException("친구 관계가 존재하지 않습니다.") }

val userNameList: List<UserNameResponse> = friendshipList.map { friendship ->
val userFriendResponseList: List<UserFriendResponse> = friendshipList.map { friendship ->
val userId = friendship.toUser.userId
val user =
userRepository.findById(userId).orElseThrow { NoSuchElementException("해당 유저가 존재하지 않습니다. ID: $userId") }
UserNameResponse(user)
UserFriendResponse(user)
}

return userNameList
return userFriendResponseList
}

fun deleteFriendship(friendshipDeleteRequest: FriendshipDeleteRequest): String {
fun getFriendshipCount(): Long {
val currentLoginUser = userService.getCurrentLoginUser()
val targetUser = userRepository.findById(friendshipDeleteRequest.friendId)
.orElseThrow { NoSuchElementException("해당 유저가 존재하지 않습니다. ID: ${friendshipDeleteRequest.friendId}") }
return friendshipRepository.countByFromUser(currentLoginUser)
}

val friendshipList = friendshipRepository.findAllByFromUserAndToUser(currentLoginUser, targetUser)
.orElseThrow { NoSuchElementException("친구 관계가 존재하지 않습니다.") }
@Transactional
fun deleteFriendship(friendshipDeleteRequestList: List<FriendshipDeleteRequest>): String {
val currentLoginUser = userService.getCurrentLoginUser()

for (friendshipDeleteRequest in friendshipDeleteRequestList) {
val targetUser = userRepository.findById(friendshipDeleteRequest.friendId)
.orElseThrow { NoSuchElementException("해당 유저가 존재하지 않습니다. ID: ${friendshipDeleteRequest.friendId}") }

val friendshipList = friendshipRepository.findAllByFromUserAndToUser(currentLoginUser, targetUser)
.orElseThrow { NoSuchElementException("친구 관계가 존재하지 않습니다.") }

for (friendship: Friendship in friendshipList) {
friendshipRepository.delete(friendship)
friendshipList.forEach { friendshipRepository.delete(it) }
}

return deleted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,14 @@ class IngredientDetailController(
}

@GetMapping("/refrig/{id}")
fun getIngredientDetailList(@PathVariable(name = "id") refrigeratorId: Long): CommonResponse<List<IngredientDetailResponse>> {
return success(ingredientDetailService.getIngredientDetailList(refrigeratorId))
fun getIngredientDetailList(
@PageableDefault(
size = 5
)
pageable: Pageable,
@PathVariable(name = "id") refrigeratorId: Long
): CommonResponse<Page<IngredientDetailResponse>> {
return success(ingredientDetailService.getIngredientDetailList(refrigeratorId, pageable))
}

@GetMapping("/count")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ data class IngredientDetailResponse(
)
}

fun List<IngredientDetail>.toIngredientDetailResponseList(): List<IngredientDetailResponse> {
return this.map { IngredientDetailResponse(it) }
}

fun Page<IngredientDetail>.toIngredientDetailResponseListPage(): Page<IngredientDetailResponse> {
return this.map { IngredientDetailResponse(it) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository
import java.time.LocalDateTime
import java.util.Optional

@Repository
interface IngredientDetailRepository : JpaRepository<IngredientDetail, Long> {

fun findIngredientDetailsByRefrigeratorAndIsDeletedIsFalse(refrigerator: Refrigerator): Optional<List<IngredientDetail>>
fun findByRefrigeratorAndIsDeletedIsFalse(refrigerator: Refrigerator, pageable: Pageable): Page<IngredientDetail>

@Query("SELECT count(i) from IngredientDetail i where i.refrigerator in (?1) and i.expirationDate between now() and ?2")
fun findIngredientDetailCountByRefrigeratorAndExpirationDate(refrigerator: List<Refrigerator>, expirationDay: LocalDateTime): Long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class IngredientDetailService(
expirationDate = ingredientDetailRequest.expirationDate,
isDeleted = ingredientDetailRequest.isDeleted
)

// 식재료 추가 일자 update
refrigerator.ingredientAddDate = LocalDateTime.now()
refrigeratorRepository.save(refrigerator)

return ingredientDetailRepository.save(ingredientDetail).ingredientDetailId
}

Expand All @@ -47,13 +52,12 @@ class IngredientDetailService(
return IngredientDetailResponse(ingredientDetail)
}

fun getIngredientDetailList(refrigeratorId: Long): List<IngredientDetailResponse> {
fun getIngredientDetailList(refrigeratorId: Long, pageable: Pageable): Page<IngredientDetailResponse> {
val refrigerator = refrigeratorRepository.findById(refrigeratorId)
.orElseThrow { NoSuchElementException("해당 냉장고가 존재하지 않습니다. ID: $refrigeratorId") }
val ingredientDetailList =
ingredientDetailRepository.findIngredientDetailsByRefrigeratorAndIsDeletedIsFalse(refrigerator)
.orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $refrigeratorId") }
return ingredientDetailList.toIngredientDetailResponseList()
ingredientDetailRepository.findByRefrigeratorAndIsDeletedIsFalse(refrigerator, pageable)
return ingredientDetailList.toIngredientDetailResponseListPage()
}

fun getIngredientDetailCount(days: Long): Long {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import jakarta.persistence.Id
import jakarta.persistence.JoinColumn
import jakarta.persistence.ManyToOne
import mara.server.domain.user.User
import java.time.LocalDateTime

@Entity
class Refrigerator(
var name: String,
var ingredientAddDate: LocalDateTime?,
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userId")
val user: User,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ class RefrigeratorController(
return success(refrigeratorService.getRefrigeratorList((userId)))
}

@GetMapping("/my")
fun getMyRefrigeratorList(): CommonResponse<List<RefrigeratorResponse>> {
return success(refrigeratorService.getMyRefrigeratorList())
}

@PutMapping("/{id}")
fun updateRefrigerator(
@PathVariable(name = "id") id: Long,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package mara.server.domain.refrigerator

import mara.server.domain.user.User
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository

@Repository
interface RefrigeratorRepository : JpaRepository<Refrigerator, Long> {
fun findRefrigeratorsByUser(user: User): List<Refrigerator>

fun findRefrigeratorByUserIn(user: List<User>, pageable: Pageable): Page<Refrigerator>
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ class RefrigeratorService(
val user = userService.getCurrentLoginUser()
val refrigerator = Refrigerator(
name = refrigeratorRequest.name,
user = user
user = user,
ingredientAddDate = null
)
return refrigeratorRepository.save(refrigerator).refrigeratorId
}
Expand All @@ -31,6 +32,12 @@ class RefrigeratorService(
return refrigeratorList.toRefrigeratorResponseList()
}

fun getMyRefrigeratorList(): List<RefrigeratorResponse> {
val user = userService.getCurrentLoginUser()
val refrigeratorList = refrigeratorRepository.findRefrigeratorsByUser(user)
return refrigeratorList.toRefrigeratorResponseList()
}

fun updateRefrigerator(id: Long, refrigeratorRequest: RefrigeratorRequest): RefrigeratorResponse {
val refrigerator =
refrigeratorRepository.findById(id).orElseThrow { NoSuchElementException("해당 냉장고가 존재하지 않습니다. ID: $id") }
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/mara/server/domain/user/UserDto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class UserInviteCodeResponse(
)
}

class UserNameResponse(
class UserFriendResponse(
val userId: Long,
val nickName: String
) {
Expand Down

0 comments on commit d6c0e81

Please sign in to comment.