From 741fddbd21ab831b18b3ba93c524454f44c0de2f Mon Sep 17 00:00:00 2001 From: blackswitch <50973746+jhkang1517@users.noreply.github.com> Date: Fri, 26 Jan 2024 21:58:25 +0900 Subject: [PATCH] =?UTF-8?q?MARA-30=20:=20=EC=8B=9D=EC=9E=AC=EB=A3=8C=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20CRUD=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#11)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 식재료(Ingredient) 껍데기 구현 * 식재료 생성 기능 구현 * 식재료 조회 기능 구현 * 식재료 업데이트 기능 구현 * 식재료 삭제 기능 구현 * 식재료 전체 조회 기능 구현 * ktlint 적용 * 식재료 상세 엔티티, 컨트롤러 껍데기 구현 * 식재료 상세 서비스 껍데기 구현 * 식재료 상세 Repository, RequestDTO 구현 * 식재료 상세 CRUD 구현 * 냉장고 ID 기준 식재료 상세 조회 껍데기 구현 * 식재료 상세 Request, Response DTO 통합 * ingredientDetailId var -> val 변경 * ingredientDetail request, response DTO 통합 * 냉장고 id별 식재료 상세 리스트 조회 기능 구현 * ktlint 적용 * ingredientDetailUpdateRequest 구현 * memo -> nullable , isDeleted -> not null 반영 * 조회 조건 isDeleted is false 추가 * /det -> /detail 명시화 * isDeleted 기본 값 false 설정 * request memo nullable 적용 및 entity isDeleted default value false 적용 --- .../domain/ingredient/IngredientDetail.kt | 45 +++++++++++++ .../ingredient/IngredientDetailController.kt | 44 ++++++++++++ .../domain/ingredient/IngredientDetailDto.kt | 48 +++++++++++++ .../ingredient/IngredientDetailRepository.kt | 13 ++++ .../ingredient/IngredientDetailService.kt | 67 +++++++++++++++++++ 5 files changed, 217 insertions(+) create mode 100644 src/main/kotlin/mara/server/domain/ingredient/IngredientDetail.kt create mode 100644 src/main/kotlin/mara/server/domain/ingredient/IngredientDetailController.kt create mode 100644 src/main/kotlin/mara/server/domain/ingredient/IngredientDetailDto.kt create mode 100644 src/main/kotlin/mara/server/domain/ingredient/IngredientDetailRepository.kt create mode 100644 src/main/kotlin/mara/server/domain/ingredient/IngredientDetailService.kt diff --git a/src/main/kotlin/mara/server/domain/ingredient/IngredientDetail.kt b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetail.kt new file mode 100644 index 0000000..8f1c6db --- /dev/null +++ b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetail.kt @@ -0,0 +1,45 @@ +package mara.server.domain.ingredient + +import jakarta.persistence.Entity +import jakarta.persistence.FetchType +import jakarta.persistence.GeneratedValue +import jakarta.persistence.GenerationType +import jakarta.persistence.Id +import jakarta.persistence.JoinColumn +import jakarta.persistence.ManyToOne +import mara.server.domain.refrigerator.Refrigerator +import java.time.LocalDateTime + +@Entity +class IngredientDetail( + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "refrigeratorId") + val refrigerator: Refrigerator, + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "ingredientId") + val ingredient: Ingredient, + var quantity: Int, + var location: String, + var memo: String?, + var addDate: LocalDateTime, + var expirationDate: LocalDateTime, + var isDeleted: Boolean = false +) { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + val ingredientDetailId: Long = 0L + + fun update(ingredientDetailUpdateRequest: IngredientDetailUpdateRequest) { + this.quantity = ingredientDetailUpdateRequest.quantity + this.location = ingredientDetailUpdateRequest.location + this.memo = ingredientDetailUpdateRequest.memo + this.addDate = ingredientDetailUpdateRequest.addDate + this.expirationDate = ingredientDetailUpdateRequest.expirationDate + this.isDeleted = ingredientDetailUpdateRequest.isDeleted + } + + fun delete() { + this.isDeleted = true + } +} diff --git a/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailController.kt b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailController.kt new file mode 100644 index 0000000..c2be7ee --- /dev/null +++ b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailController.kt @@ -0,0 +1,44 @@ +package mara.server.domain.ingredient + +import mara.server.common.CommonResponse +import mara.server.common.success +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.RestController + +@RestController +@RequestMapping("/ingrs/detail") +class IngredientDetailController( + private val ingredientDetailService: IngredientDetailService +) { + + @PostMapping + fun createIngredientDetail(@RequestBody ingredientDetailRequest: IngredientDetailRequest): CommonResponse { + return success(ingredientDetailService.createIngredientDetail(ingredientDetailRequest)) + } + + @GetMapping("/{id}") + fun getIngredientDetail(@PathVariable(name = "id") id: Long): CommonResponse { + return success(ingredientDetailService.getIngredientDetail(id)) + } + + @GetMapping("/refrig/{id}") + fun getIngredientDetailList(@PathVariable(name = "id") refrigeratorId: Long): CommonResponse> { + return success(ingredientDetailService.getIngredientDetailList(refrigeratorId)) + } + + @PutMapping("/{id}") + fun updateIngredientDetail(@PathVariable(name = "id") id: Long, @RequestBody ingredientDetailUpdateRequest: IngredientDetailUpdateRequest): CommonResponse { + return success(ingredientDetailService.updateIngredientDetail(id, ingredientDetailUpdateRequest)) + } + + @DeleteMapping("/{id}") + fun deleteIngredient(@PathVariable(name = "id") id: Long): CommonResponse { + return success(ingredientDetailService.deleteIngredientDetail(id)) + } +} diff --git a/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailDto.kt b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailDto.kt new file mode 100644 index 0000000..83d8814 --- /dev/null +++ b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailDto.kt @@ -0,0 +1,48 @@ +package mara.server.domain.ingredient + +import java.time.LocalDateTime + +data class IngredientDetailRequest( + var refrigeratorId: Long, + var ingredientId: Long, + val quantity: Int, + val location: String, + val memo: String?, + val addDate: LocalDateTime, + val expirationDate: LocalDateTime, + val isDeleted: Boolean = false +) + +data class IngredientDetailUpdateRequest( + val quantity: Int, + val location: String, + val memo: String?, + val addDate: LocalDateTime, + val expirationDate: LocalDateTime, + val isDeleted: Boolean = false +) + +data class IngredientDetailResponse( + val ingredientDetailId: Long, + val quantity: Int, + val location: String, + val memo: String?, + val addDate: LocalDateTime, + val expirationDate: LocalDateTime, + val isDeleted: Boolean +) { + + constructor(ingredientDetail: IngredientDetail) : this( + ingredientDetailId = ingredientDetail.ingredientDetailId, + quantity = ingredientDetail.quantity, + location = ingredientDetail.location, + memo = ingredientDetail.memo, + addDate = ingredientDetail.addDate, + expirationDate = ingredientDetail.expirationDate, + isDeleted = ingredientDetail.isDeleted + ) +} + +fun List.toIngredientResponseList(): List { + return this.map { IngredientDetailResponse(it) } +} diff --git a/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailRepository.kt b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailRepository.kt new file mode 100644 index 0000000..95dcc4a --- /dev/null +++ b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailRepository.kt @@ -0,0 +1,13 @@ +package mara.server.domain.ingredient + +import mara.server.domain.refrigerator.Refrigerator +import org.springframework.data.jpa.repository.JpaRepository +import org.springframework.stereotype.Repository +import java.util.Optional + +@Repository +interface IngredientDetailRepository : JpaRepository { + + fun findIngredientDetailByIngredientDetailIdAndIsDeletedIsFalse(ingredientDetailId: Long): Optional + fun findIngredientDetailsByRefrigeratorAndIsDeletedIsFalse(refrigerator: Refrigerator): Optional> +} diff --git a/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailService.kt b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailService.kt new file mode 100644 index 0000000..ac51c1b --- /dev/null +++ b/src/main/kotlin/mara/server/domain/ingredient/IngredientDetailService.kt @@ -0,0 +1,67 @@ +package mara.server.domain.ingredient + +import mara.server.domain.refrigerator.RefrigeratorRepository +import org.springframework.stereotype.Service + +@Service +class IngredientDetailService( + private val ingredientDetailRepository: IngredientDetailRepository, + private val refrigeratorRepository: RefrigeratorRepository, + private val ingredientRepository: IngredientRepository +) { + + fun createIngredientDetail(ingredientDetailRequest: IngredientDetailRequest): Long { + val refrigeratorId = ingredientDetailRequest.refrigeratorId + val refrigerator = refrigeratorRepository.findById(refrigeratorId) + .orElseThrow { NoSuchElementException("해당 냉장고가 존재하지 않습니다. ID: $refrigeratorId") } + + val ingredientId = ingredientDetailRequest.ingredientId + val ingredient = ingredientRepository.findById(ingredientId) + .orElseThrow { NoSuchElementException("해당 식재료가 존재하지 않습니다. ID: $ingredientId") } + + val ingredientDetail = IngredientDetail( + refrigerator = refrigerator, + ingredient = ingredient, + quantity = ingredientDetailRequest.quantity, + location = ingredientDetailRequest.location, + memo = ingredientDetailRequest.memo, + addDate = ingredientDetailRequest.addDate, + expirationDate = ingredientDetailRequest.expirationDate, + isDeleted = ingredientDetailRequest.isDeleted + ) + return ingredientDetailRepository.save(ingredientDetail).ingredientDetailId + } + + fun getIngredientDetail(id: Long): IngredientDetailResponse { + val ingredientDetail = ingredientDetailRepository.findIngredientDetailByIngredientDetailIdAndIsDeletedIsFalse(id) + .orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $id") } + return IngredientDetailResponse(ingredientDetail) + } + + fun getIngredientDetailList(refrigeratorId: Long): List { + val refrigerator = refrigeratorRepository.findById(refrigeratorId) + .orElseThrow { NoSuchElementException("해당 냉장고가 존재하지 않습니다. ID: $refrigeratorId") } + val ingredientDetailList = + ingredientDetailRepository.findIngredientDetailsByRefrigeratorAndIsDeletedIsFalse(refrigerator) + .orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $refrigeratorId") } + return ingredientDetailList.toIngredientResponseList() + } + + fun updateIngredientDetail( + id: Long, + ingredientDetailUpdateRequest: IngredientDetailUpdateRequest + ): IngredientDetailResponse { + val ingredientDetail = ingredientDetailRepository.findById(id) + .orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $id") } + ingredientDetail.update(ingredientDetailUpdateRequest) + return IngredientDetailResponse(ingredientDetailRepository.save(ingredientDetail)) + } + + fun deleteIngredientDetail(id: Long): String { + val ingredientDetail = ingredientDetailRepository.findById(id) + .orElseThrow { NoSuchElementException("해당 식재료 상세가 존재하지 않습니다. ID: $id") } + ingredientDetail.delete() + ingredientDetailRepository.save(ingredientDetail) + return "deleted" + } +}