Skip to content

Commit

Permalink
MARA-54 : 화면설계서 기반 식자재 추가 API 개발, 리팩토링 (#23)
Browse files Browse the repository at this point in the history
* 식자재 보관 위치 Enum 상수 IngredientLocation 추가

* 식자재, 식자재 상세 @transactional 추가

* 카테고리별 식자재 이미지, 이름 조회 기능 개발

* 남은 소비기한 기준 식재료 상세 개수 조회 기능 개발

* refactoring : 불필요한 userId 요청 제거, getCurrentLoginUser 사용으로 변경

* 식자재 상세 소비기한 임박 순 조회 기능 구현

* deleted 상수화 관리 (임시)

* getIngredientDetail 리팩토링

* Pageable 적용

* IngredientGroupResponse 반환 형태 변경

* 변수명 변경

* findIngredientDetailByIngredientDetailId -> 삭제
  • Loading branch information
jhkang1517 authored Feb 8, 2024
1 parent 21ca08d commit b6fa680
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ class IngredientController(
return success(ingredientService.getIngredientList())
}

@GetMapping("/category")
fun getIngredientGroupListByCategory(): CommonResponse<List<IngredientGroupResponse>> {
return success(ingredientService.getIngredientListByCategory())
}

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

import jakarta.persistence.Entity
import jakarta.persistence.EnumType
import jakarta.persistence.Enumerated
import jakarta.persistence.FetchType
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
Expand All @@ -21,7 +23,9 @@ class IngredientDetail(
val ingredient: Ingredient,
var name: String,
var quantity: Int,
var location: String,

@Enumerated(EnumType.STRING)
var location: IngredientLocation,
var memo: String?,
var addDate: LocalDateTime,
var expirationDate: LocalDateTime,
Expand All @@ -45,3 +49,8 @@ class IngredientDetail(
this.isDeleted = true
}
}

enum class IngredientLocation() {
FREEZING,
REFRIGERATION
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package mara.server.domain.ingredient

import mara.server.common.CommonResponse
import mara.server.common.success
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.domain.Sort
import org.springframework.data.web.PageableDefault
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController

@RestController
Expand All @@ -32,8 +37,26 @@ class IngredientDetailController(
return success(ingredientDetailService.getIngredientDetailList(refrigeratorId))
}

@GetMapping("/count")
fun getIngredientDetailCount(@RequestParam("day") days: Long): CommonResponse<Long> {
return success(ingredientDetailService.getIngredientDetailCount(days))
}

@GetMapping("/recent")
fun getIngredientDetailRecent(
@PageableDefault(
size = 4, sort = ["expirationDate"], direction = Sort.Direction.ASC
)
pageable: Pageable,
): CommonResponse<Page<IngredientDetailResponse>> {
return success(ingredientDetailService.getIngredientDetailRecent(pageable))
}

@PutMapping("/{id}")
fun updateIngredientDetail(@PathVariable(name = "id") id: Long, @RequestBody ingredientDetailUpdateRequest: IngredientDetailUpdateRequest): CommonResponse<IngredientDetailResponse> {
fun updateIngredientDetail(
@PathVariable(name = "id") id: Long,
@RequestBody ingredientDetailUpdateRequest: IngredientDetailUpdateRequest
): CommonResponse<IngredientDetailResponse> {
return success(ingredientDetailService.updateIngredientDetail(id, ingredientDetailUpdateRequest))
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package mara.server.domain.ingredient

import org.springframework.data.domain.Page
import java.time.LocalDateTime

data class IngredientDetailRequest(
var refrigeratorId: Long,
var ingredientId: Long,
val name: String,
val quantity: Int,
val location: String,
val location: IngredientLocation,
val memo: String?,
val addDate: LocalDateTime,
val expirationDate: LocalDateTime,
Expand All @@ -17,7 +18,7 @@ data class IngredientDetailRequest(
data class IngredientDetailUpdateRequest(
val name: String,
val quantity: Int,
val location: String,
val location: IngredientLocation,
val memo: String?,
val addDate: LocalDateTime,
val expirationDate: LocalDateTime,
Expand All @@ -28,7 +29,7 @@ data class IngredientDetailResponse(
val ingredientDetailId: Long,
val name: String,
val quantity: Int,
val location: String,
val location: IngredientLocation,
val memo: String?,
val addDate: LocalDateTime,
val expirationDate: LocalDateTime,
Expand All @@ -47,6 +48,10 @@ data class IngredientDetailResponse(
)
}

fun List<IngredientDetail>.toIngredientResponseList(): List<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
@@ -1,13 +1,23 @@
package mara.server.domain.ingredient

import mara.server.domain.refrigerator.Refrigerator
import org.springframework.data.domain.Page
import org.springframework.data.domain.Pageable
import org.springframework.data.jpa.repository.JpaRepository
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 findIngredientDetailByIngredientDetailIdAndIsDeletedIsFalse(ingredientDetailId: Long): Optional<IngredientDetail>
fun findIngredientDetailsByRefrigeratorAndIsDeletedIsFalse(refrigerator: Refrigerator): Optional<List<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

@Query("SELECT i from IngredientDetail i where i.refrigerator in (?1)")
fun findByRefrigerators(@Param("refrigerators")refrigerators: List<Refrigerator>, pageable: Pageable): Page<IngredientDetail>
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
package mara.server.domain.ingredient

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
import org.springframework.transaction.annotation.Transactional
import java.time.LocalDateTime

@Service
class IngredientDetailService(
private val ingredientDetailRepository: IngredientDetailRepository,
private val refrigeratorRepository: RefrigeratorRepository,
private val ingredientRepository: IngredientRepository
private val ingredientRepository: IngredientRepository,
private val userService: UserService
) {
private val deleted = "deleted"

@Transactional
fun createIngredientDetail(ingredientDetailRequest: IngredientDetailRequest): Long {
val refrigeratorId = ingredientDetailRequest.refrigeratorId
val refrigerator = refrigeratorRepository.findById(refrigeratorId)
Expand All @@ -34,7 +42,7 @@ class IngredientDetailService(
}

fun getIngredientDetail(id: Long): IngredientDetailResponse {
val ingredientDetail = ingredientDetailRepository.findIngredientDetailByIngredientDetailIdAndIsDeletedIsFalse(id)
val ingredientDetail = ingredientDetailRepository.findById(id)
.orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $id") }
return IngredientDetailResponse(ingredientDetail)
}
Expand All @@ -45,9 +53,30 @@ class IngredientDetailService(
val ingredientDetailList =
ingredientDetailRepository.findIngredientDetailsByRefrigeratorAndIsDeletedIsFalse(refrigerator)
.orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $refrigeratorId") }
return ingredientDetailList.toIngredientResponseList()
return ingredientDetailList.toIngredientDetailResponseList()
}

fun getIngredientDetailCount(days: Long): Long {
val user = userService.getCurrentLoginUser()
val refrigeratorList = refrigeratorRepository.findRefrigeratorsByUser(user)
val expirationDate = LocalDateTime.now().plusDays(days)

return ingredientDetailRepository.findIngredientDetailCountByRefrigeratorAndExpirationDate(
refrigeratorList,
expirationDate
)
}

fun getIngredientDetailRecent(pageable: Pageable): Page<IngredientDetailResponse> {
val user = userService.getCurrentLoginUser()
val refrigeratorList = refrigeratorRepository.findRefrigeratorsByUser(user)
val ingredientDetailRecentList =
ingredientDetailRepository.findByRefrigerators(refrigeratorList, pageable)

return ingredientDetailRecentList.toIngredientDetailResponseListPage()
}

@Transactional
fun updateIngredientDetail(
id: Long,
ingredientDetailUpdateRequest: IngredientDetailUpdateRequest
Expand All @@ -58,11 +87,12 @@ class IngredientDetailService(
return IngredientDetailResponse(ingredientDetailRepository.save(ingredientDetail))
}

@Transactional
fun deleteIngredientDetail(id: Long): String {
val ingredientDetail = ingredientDetailRepository.findById(id)
.orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $id") }
ingredientDetail.delete()
ingredientDetailRepository.save(ingredientDetail)
return "deleted"
return deleted
}
}
26 changes: 26 additions & 0 deletions src/main/kotlin/mara/server/domain/ingredient/IngredientDto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,32 @@ data class IngredientResponse(
)
}

data class IngredientGroupResponse(
val category: String,
val ingredientGroupList: List<IngredientGroup>
) {
constructor(ingredientList: List<Ingredient>) : this(
category = ingredientList.firstOrNull()?.category ?: "",
ingredientGroupList = ingredientList.map { IngredientGroup(it) }
)
}

data class IngredientGroup(
val id: Long,
val name: String,
val iconImage: String
) {
constructor(ingredient: Ingredient) : this(
id = ingredient.ingredientId,
name = ingredient.name,
iconImage = ingredient.iconImage
)
}

fun List<Ingredient>.toIngredientResponseList(): List<IngredientResponse> {
return this.map { IngredientResponse(it) }
}

fun List<Ingredient>.toIngredientCategoryGroupResponseList(): List<IngredientGroupResponse> {
return this.groupBy { it.category }.values.map { IngredientGroupResponse(it) }
}
20 changes: 16 additions & 4 deletions src/main/kotlin/mara/server/domain/ingredient/IngredientService.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package mara.server.domain.ingredient

import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class IngredientService(
private val ingredientRepository: IngredientRepository
private val ingredientRepository: IngredientRepository,
) {
private val deleted = "deleted"

@Transactional
fun createIngredient(ingredientRequest: IngredientRequest): Long {
val ingredient = Ingredient(
category = ingredientRequest.category,
Expand All @@ -18,7 +21,8 @@ class IngredientService(
}

fun getIngredient(id: Long): IngredientResponse {
val ingredient = ingredientRepository.findById(id).orElseThrow { NoSuchElementException("해당 식재료가 존재하지 않습니다. ID: $id") }
val ingredient =
ingredientRepository.findById(id).orElseThrow { NoSuchElementException("해당 식재료가 존재하지 않습니다. ID: $id") }
return IngredientResponse(ingredient)
}

Expand All @@ -27,14 +31,22 @@ class IngredientService(
return ingredientList.toIngredientResponseList()
}

fun getIngredientListByCategory(): List<IngredientGroupResponse> {
val ingredientList = ingredientRepository.findAll()
return ingredientList.toIngredientCategoryGroupResponseList()
}

@Transactional
fun updateIngredient(id: Long, ingredientRequest: IngredientRequest): IngredientResponse {
val ingredient = ingredientRepository.findById(id).orElseThrow { NoSuchElementException("해당 식재료가 존재하지 않습니다. ID: $id") }
val ingredient =
ingredientRepository.findById(id).orElseThrow { NoSuchElementException("해당 식재료가 존재하지 않습니다. ID: $id") }
ingredient.update(ingredientRequest)
return IngredientResponse(ingredientRepository.save(ingredient))
}

@Transactional
fun deleteIngredient(id: Long): String {
ingredientRepository.deleteById(id)
return "deleted"
return deleted
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Refrigerator(
@Column(name = "refrigerator_id", nullable = false)
val refrigeratorId: Long = 0L

fun update(refrigeratorUpdateRequest: RefrigeratorUpdateRequest) {
this.name = refrigeratorUpdateRequest.name
fun update(refrigeratorRequest: RefrigeratorRequest) {
this.name = refrigeratorRequest.name
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ class RefrigeratorController(
@PutMapping("/{id}")
fun updateRefrigerator(
@PathVariable(name = "id") id: Long,
@RequestBody refrigeratorUpdateRequest: RefrigeratorUpdateRequest
@RequestBody refrigeratorRequest: RefrigeratorRequest
): CommonResponse<RefrigeratorResponse> {
return success(refrigeratorService.updateRefrigerator(id, refrigeratorUpdateRequest))
return success(refrigeratorService.updateRefrigerator(id, refrigeratorRequest))
}

@DeleteMapping("/{id}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
package mara.server.domain.refrigerator

data class RefrigeratorRequest(
var name: String,
val userId: Long
)

data class RefrigeratorUpdateRequest(
var name: String
)

Expand Down
Loading

0 comments on commit b6fa680

Please sign in to comment.