Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ„ :: (Meogo-42) post good #43

Merged
merged 3 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/kotlin/org/meogo/domain/bookmark/Bookmark.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.meogo.domain.bookmark

import org.meogo.domain.user.domain.User
import org.meogo.global.base.BaseUUIDEntity
import java.util.UUID
import javax.persistence.Entity
import javax.persistence.FetchType
import javax.persistence.JoinColumn
import javax.persistence.ManyToOne

@Entity
class Bookmark(
id: UUID? = null,

val schoolId: Int? = 0,
Comment on lines +11 to +15
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

schoolId μ†μ„±μ˜ 널 ν—ˆμš© 여뢀와 기본값을 μž¬κ³ ν•΄ λ³΄μ„Έμš”.

schoolIdκ°€ 널을 ν—ˆμš©ν•˜κ³  κΈ°λ³Έκ°’μœΌλ‘œ 0을 μ‚¬μš©ν•˜λŠ” 것이 μ˜λ„λœ 섀계인지 확인해 μ£Όμ„Έμš”. λ§Œμ•½ schoolIdκ°€ ν•„μˆ˜ ν•„λ“œλΌλ©΄, 널을 ν—ˆμš©ν•˜μ§€ μ•Šλ„λ‘ λ³€κ²½ν•˜κ³  의미 μžˆλŠ” 기본값을 μ„€μ •ν•˜κ±°λ‚˜ κΈ°λ³Έκ°’ 없이 ν•„μˆ˜ νŒŒλΌλ―Έν„°λ‘œ λ§Œλ“œλŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 변경을 κ³ λ €ν•΄ λ³΄μ„Έμš”:

-    val schoolId: Int? = 0,
+    val schoolId: Int,

λ˜λŠ” 의미 μžˆλŠ” 기본값이 μ—†λ‹€λ©΄:

-    val schoolId: Int? = 0,
+    val schoolId: Int,

그리고 μƒμ„±μžμ—μ„œ schoolIdλ₯Ό ν•„μˆ˜ νŒŒλΌλ―Έν„°λ‘œ 받도둝 λ³€κ²½ν•˜μ„Έμš”.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Entity
class Bookmark(
id: UUID? = null,
val schoolId: Int? = 0,
@Entity
class Bookmark(
id: UUID? = null,
val schoolId: Int,


@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
val user: User
) : BaseUUIDEntity(id)
13 changes: 13 additions & 0 deletions src/main/kotlin/org/meogo/domain/bookmark/BookmarkRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.meogo.domain.bookmark

import org.meogo.domain.user.domain.User
import org.springframework.data.jpa.repository.JpaRepository
import java.util.UUID

interface BookmarkRepository : JpaRepository<Bookmark, UUID> {
fun findAllBySchoolId(schoolId: Int): List<Bookmark>?

fun existsBySchoolIdAndUser(schoolId: Int, user: User): Boolean

fun deleteBySchoolIdAndUser(schoolId: Int, user: User)
}
42 changes: 42 additions & 0 deletions src/main/kotlin/org/meogo/domain/bookmark/BookmarkService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package org.meogo.domain.bookmark

import org.meogo.domain.post.domain.PostRepository
import org.meogo.domain.user.exception.UserNotFoundException
import org.meogo.domain.user.facade.UserFacade
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class BookmarkService(
private val bookmarkRepository: BookmarkRepository,
private val userFacade: UserFacade,
private val postRepository: PostRepository
) {
Comment on lines +9 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

μ‚¬μš©λ˜μ§€ μ•ŠλŠ” μ˜μ‘΄μ„± 제거 ν•„μš”

PostRepositoryκ°€ μ£Όμž…λ˜μ—ˆμ§€λ§Œ 클래슀 λ‚΄μ—μ„œ μ‚¬μš©λ˜μ§€ μ•Šκ³  μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” λΆˆν•„μš”ν•œ μ˜μ‘΄μ„±μ„ μ•ΌκΈ°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€:

 @Service
 class BookmarkService(
     private val bookmarkRepository: BookmarkRepository,
-    private val userFacade: UserFacade,
-    private val postRepository: PostRepository
+    private val userFacade: UserFacade
 ) {

λ§Œμ•½ PostRepositoryκ°€ ν–₯ν›„ μ‚¬μš©λ  μ˜ˆμ •μ΄λΌλ©΄, 주석을 μΆ”κ°€ν•˜μ—¬ κ·Έ μ˜λ„λ₯Ό λͺ…ν™•νžˆ ν•΄μ£Όμ„Έμš”.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Service
class BookmarkService(
private val bookmarkRepository: BookmarkRepository,
private val userFacade: UserFacade,
private val postRepository: PostRepository
) {
@Service
class BookmarkService(
private val bookmarkRepository: BookmarkRepository,
private val userFacade: UserFacade
) {


@Transactional
fun execute(schoolId: Int) {
val user = userFacade.currentUser() ?: throw UserNotFoundException

bookmarkRepository.save(
Bookmark(
schoolId = schoolId,
user = user
)
)
}
Comment on lines +16 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

쀑볡 뢁마크 처리 둜직 μΆ”κ°€ ν•„μš”

ν˜„μž¬ κ΅¬ν˜„μ€ λ™μΌν•œ schoolId와 μ‚¬μš©μžμ— λŒ€ν•œ 쀑볡 뢁마크λ₯Ό ν—ˆμš©ν•©λ‹ˆλ‹€. μ΄λŠ” 데이터 쀑볡을 μ•ΌκΈ°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

뢁마크 생성 전에 이미 μ‘΄μž¬ν•˜λŠ”μ§€ ν™•μΈν•˜λŠ” λ‘œμ§μ„ μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄:

@Transactional
fun execute(schoolId: Int) {
    val user = userFacade.currentUser() ?: throw UserNotFoundException
    
    if (!bookmarkRepository.existsBySchoolIdAndUser(schoolId, user)) {
        bookmarkRepository.save(
            Bookmark(
                schoolId = schoolId,
                user = user
            )
        )
    } else {
        // 이미 μ‘΄μž¬ν•˜λŠ” λΆλ§ˆν¬μ— λŒ€ν•œ 처리 (예: μ˜ˆμ™Έ λ°œμƒ λ˜λŠ” λ¬΄μ‹œ)
    }
}

μ΄λ ‡κ²Œ ν•˜λ©΄ 쀑볡 뢁마크λ₯Ό λ°©μ§€ν•˜κ³  데이터 일관성을 μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


fun queryBookmarkedPost(schoolId: Int): Int {
val posts = bookmarkRepository.findAllBySchoolId(schoolId)
return posts?.size ?: 0
}
Comment on lines +28 to +31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

λ©”μ„œλ“œ 이름 λ³€κ²½ 및 쿼리 μ΅œμ ν™” ν•„μš”

ν˜„μž¬ λ©”μ„œλ“œ 이름 queryBookmarkedPostλŠ” 뢁마크된 κ²Œμ‹œλ¬Όμ„ μ‘°νšŒν•˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μ΄μ§€λ§Œ, μ‹€μ œλ‘œλŠ” 뢁마크 수λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. λ˜ν•œ, λͺ¨λ“  뢁마크λ₯Ό μ‘°νšŒν•œ ν›„ 크기λ₯Ό κ³„μ‚°ν•˜λŠ” 것은 λΉ„νš¨μœ¨μ μΌ 수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 κ°œμ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

  1. λ©”μ„œλ“œ 이름을 countBookmarksBySchoolId둜 λ³€κ²½ν•˜μ—¬ μ˜λ„λ₯Ό λͺ…ν™•νžˆ ν•©λ‹ˆλ‹€.
  2. 쿼리λ₯Ό μ΅œμ ν™”ν•˜μ—¬ 직접 개수λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ ν•©λ‹ˆλ‹€.
fun countBookmarksBySchoolId(schoolId: Int): Int {
    return bookmarkRepository.countBySchoolId(schoolId)
}

BookmarkRepository에 countBySchoolId λ©”μ„œλ“œλ₯Ό μΆ”κ°€ν•˜κ³ , 이λ₯Ό 톡해 λ°μ΄ν„°λ² μ΄μŠ€ λ ˆλ²¨μ—μ„œ 효율적으둜 개수λ₯Ό 계산할 수 μžˆμŠ΅λ‹ˆλ‹€.


fun queryIsBookmarked(schoolId: Int): Boolean {
val user = userFacade.currentUser() ?: throw UserNotFoundException
return bookmarkRepository.existsBySchoolIdAndUser(schoolId, user)
}
Comment on lines +33 to +36
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

μ˜ˆμ™Έ 처리 일관성 κ°œμ„  ν•„μš”

UserNotFoundException을 λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œ 직접 μ²˜λ¦¬ν•˜λŠ” 것은 일관성 μ—†λŠ” μ˜ˆμ™Έ 처리λ₯Ό μ•ΌκΈ°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ˜ˆμ™Έ 처리λ₯Ό μ„œλΉ„μŠ€ 레벨 μƒμœ„μ—μ„œ ν†΅μΌμ μœΌλ‘œ μ²˜λ¦¬ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄:

fun queryIsBookmarked(schoolId: Int): Boolean {
    val user = userFacade.currentUser()
    return bookmarkRepository.existsBySchoolIdAndUser(schoolId, user)
}

그리고 UserFacadeμ—μ„œ currentUser()κ°€ null을 λ°˜ν™˜ν•˜μ§€ μ•Šκ³  항상 UserNotFoundException을 λ˜μ§€λ„λ‘ μˆ˜μ •ν•˜μ„Έμš”. μ΄λ ‡κ²Œ ν•˜λ©΄ λͺ¨λ“  λ©”μ„œλ“œμ—μ„œ μΌκ΄€λœ λ°©μ‹μœΌλ‘œ μ‚¬μš©μž 쑴재 μ—¬λΆ€λ₯Ό μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


fun deleteBookmark(schoolId: Int) {
val user = userFacade.currentUser() ?: throw UserNotFoundException
bookmarkRepository.deleteBySchoolIdAndUser(schoolId, user)
}
Comment on lines +38 to +41
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

νŠΈλžœμž­μ…˜ 처리 및 μ˜ˆμ™Έ 상황 κ³ λ € ν•„μš”

deleteBookmark λ©”μ„œλ“œμ— λͺ‡ 가지 κ°œμ„ μ΄ ν•„μš”ν•©λ‹ˆλ‹€:

  1. @Transactional μ–΄λ…Έν…Œμ΄μ…˜μ΄ λˆ„λ½λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
  2. μ‚­μ œν•˜λ €λŠ” λΆλ§ˆν¬κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ— λŒ€ν•œ μ²˜λ¦¬κ°€ μ—†μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€:

@Transactional
fun deleteBookmark(schoolId: Int) {
    val user = userFacade.currentUser()
    val deleted = bookmarkRepository.deleteBySchoolIdAndUser(schoolId, user)
    if (deleted == 0) {
        // λΆλ§ˆν¬κ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ— λŒ€ν•œ 처리
        // 예: throw BookmarkNotFoundException(schoolId, user.id)
    }
}

μ΄λ ‡κ²Œ ν•˜λ©΄ νŠΈλžœμž­μ…˜ μ²˜λ¦¬κ°€ 보μž₯되고, μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” 뢁마크λ₯Ό μ‚­μ œν•˜λ €λŠ” μ‹œλ„λ₯Ό 적절히 μ²˜λ¦¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

}
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
package org.meogo.domain.good
package org.meogo.domain.good.domain

import org.meogo.domain.post.domain.Post
import org.meogo.domain.user.domain.User
import org.meogo.global.base.BaseUUIDEntity
import java.util.UUID
import javax.persistence.Entity
import javax.persistence.FetchType
import javax.persistence.JoinColumn
import javax.persistence.ManyToOne
import org.meogo.domain.post.domain.Post
import org.meogo.domain.user.domain.User
import org.meogo.global.base.BaseUUIDEntity

@Entity
class Bookmark (
class Good(
id: UUID? = null,


@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id", nullable = true)
val post: Post? = null,


@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
val user: User

) : BaseUUIDEntity(id)
) : BaseUUIDEntity(id)
10 changes: 10 additions & 0 deletions src/main/kotlin/org/meogo/domain/good/domain/GoodRepository.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.meogo.domain.good.domain

import org.meogo.domain.post.domain.Post
import org.meogo.domain.user.domain.User
import org.springframework.data.jpa.repository.JpaRepository
import java.util.UUID

interface GoodRepository : JpaRepository<Good, UUID> {
fun findByUserAndPost(user: User, post: Post): Good
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

findByUserAndPost λ©”μ„œλ“œμ˜ λ°˜ν™˜ νƒ€μž…κ³Ό 이름을 μž¬κ³ ν•΄ λ³΄μ„Έμš”.

ν˜„μž¬ λ©”μ„œλ“œ μ •μ˜μ—λŠ” 두 가지 잠재적인 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€:

  1. λ°˜ν™˜ νƒ€μž…μ΄ non-nullable Goodμž…λ‹ˆλ‹€. λ§Œμ•½ μΌμΉ˜ν•˜λŠ” μ—”ν‹°ν‹°κ°€ 없을 경우 μ΄λŠ” μ˜ˆμ™Έλ₯Ό λ°œμƒμ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.
  2. λ©”μ„œλ“œ 이름이 단일 μ—”ν‹°ν‹°λ₯Ό λ°˜ν™˜ν•  κ²ƒμž„μ„ μ•”μ‹œν•˜μ§€λ§Œ, μ‹€μ œλ‘œλŠ” μ‚¬μš©μžμ™€ κ²Œμ‹œλ¬Ό 쑰합에 λŒ€ν•΄ μ—¬λŸ¬ "μ’‹μ•„μš”"κ°€ μ‘΄μž¬ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•˜λŠ” 것을 κ³ λ €ν•΄λ³΄μ„Έμš”:

-fun findByUserAndPost(user: User, post: Post): Good
+fun findByUserAndPost(user: User, post: Post): Good?

λ˜λŠ” μ—¬λŸ¬ μ—”ν‹°ν‹°λ₯Ό λ°˜ν™˜ν•˜λ„λ‘ λ³€κ²½:

-fun findByUserAndPost(user: User, post: Post): Good
+fun findAllByUserAndPost(user: User, post: Post): List<Good>

μ„ νƒν•œ μ ‘κ·Ό 방식에 따라 μ„œλΉ„μŠ€ λ ˆμ΄μ–΄μ—μ„œ 적절히 μ²˜λ¦¬ν•΄μ•Ό ν•©λ‹ˆλ‹€.

Committable suggestion was skipped due to low confidence.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.meogo.domain.good.presentation

import lombok.RequiredArgsConstructor
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Lombok μ–΄λ…Έν…Œμ΄μ…˜ 제거 ν•„μš”

Kotlinμ—μ„œλŠ” Lombok이 ν•„μš”ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. @RequiredArgsConstructor μ–΄λ…Έν…Œμ΄μ…˜κ³Ό importλ₯Ό μ œκ±°ν•΄μ£Όμ„Έμš”. Kotlin은 이미 μ£Ό μƒμ„±μžμ—μ„œ ν”„λ‘œνΌν‹°λ₯Ό μ„ μ–Έν•  λ•Œ μžλ™μœΌλ‘œ μƒμ„±μž λ§€κ°œλ³€μˆ˜λ₯Ό λ§Œλ“€μ–΄μ€λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•΄μ£Όμ„Έμš”:

-import lombok.RequiredArgsConstructor
-
 import org.meogo.domain.good.service.GoodService
 import org.springframework.http.HttpStatus
 import org.springframework.web.bind.annotation.DeleteMapping
@@ -10,7 +9,6 @@ import org.springframework.web.bind.annotation.RequestParam
 import org.springframework.web.bind.annotation.ResponseStatus
 import org.springframework.web.bind.annotation.RestController

-@RequiredArgsConstructor
 @RestController
 @RequestMapping("/good")
 class GoodController(

Also applies to: 13-13

import org.meogo.domain.good.service.GoodService
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestController

@RequiredArgsConstructor
@RestController
@RequestMapping("/good")
class GoodController(
private val goodService: GoodService
) {
@ResponseStatus(HttpStatus.CREATED)
@PostMapping
fun addGood(@RequestParam(name = "post_id")postId: Long) =
goodService.addGood(postId)
Comment on lines +19 to +22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

addGood λ©”μ„œλ“œ κ°œμ„  μ œμ•ˆ

addGood λ©”μ„œλ“œμ˜ κ΅¬ν˜„μ€ λŒ€μ²΄λ‘œ μ˜¬λ°”λ₯΄μ§€λ§Œ, λ‹€μŒκ³Ό 같은 κ°œμ„ μ‚¬ν•­μ„ μ œμ•ˆν•©λ‹ˆλ‹€:

  1. @RequestParam μ–΄λ…Έν…Œμ΄μ…˜μ˜ 곡백을 일관성 있게 μˆ˜μ •ν•΄μ£Όμ„Έμš”.
  2. λ©”μ„œλ“œ 이름을 더 ꡬ체적으둜 λ³€κ²½ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€ (예: addGoodToPost).
  3. 였λ₯˜ 처리 λ‘œμ§μ„ μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•΄λ³΄μ„Έμš”:

@ResponseStatus(HttpStatus.CREATED)
@PostMapping
fun addGoodToPost(@RequestParam(name = "post_id") postId: Long): ResponseEntity<Any> {
    return try {
        goodService.addGood(postId)
        ResponseEntity.status(HttpStatus.CREATED).build()
    } catch (e: Exception) {
        ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Failed to add good: ${e.message}")
    }
}


@ResponseStatus(HttpStatus.NO_CONTENT)
@DeleteMapping
fun deleteGood(@RequestParam(name = "post_id")postId: Long) =
goodService.deleteGood(postId)
Comment on lines +24 to +27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ› οΈ Refactor suggestion

deleteGood λ©”μ„œλ“œ κ°œμ„  μ œμ•ˆ

deleteGood λ©”μ„œλ“œλ„ addGood λ©”μ„œλ“œμ™€ μœ μ‚¬ν•œ κ°œμ„ μ΄ ν•„μš”ν•©λ‹ˆλ‹€:

  1. @RequestParam μ–΄λ…Έν…Œμ΄μ…˜μ˜ 곡백을 일관성 있게 μˆ˜μ •ν•΄μ£Όμ„Έμš”.
  2. λ©”μ„œλ“œ 이름을 더 ꡬ체적으둜 λ³€κ²½ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€ (예: removeGoodFromPost).
  3. 였λ₯˜ 처리 λ‘œμ§μ„ μΆ”κ°€ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•΄λ³΄μ„Έμš”:

@DeleteMapping
fun removeGoodFromPost(@RequestParam(name = "post_id") postId: Long): ResponseEntity<Any> {
    return try {
        goodService.deleteGood(postId)
        ResponseEntity.noContent().build()
    } catch (e: Exception) {
        ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Failed to remove good: ${e.message}")
    }
}

μ΄λ ‡κ²Œ μˆ˜μ •ν•˜λ©΄ @ResponseStatus μ–΄λ…Έν…Œμ΄μ…˜μ΄ ν•„μš” μ—†μ–΄μ§€λ―€λ‘œ μ œκ±°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

}
41 changes: 41 additions & 0 deletions src/main/kotlin/org/meogo/domain/good/service/GoodService.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.meogo.domain.good.service

import org.meogo.domain.good.domain.Good
import org.meogo.domain.good.domain.GoodRepository
import org.meogo.domain.post.domain.PostRepository
import org.meogo.domain.user.exception.UserNotFoundException
import org.meogo.domain.user.facade.UserFacade
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

@Service
class GoodService(
private val goodRepository: GoodRepository,
private val userFacade: UserFacade,
private val postRepository: PostRepository
) {

@Transactional
fun addGood(postId: Long) {
val user = userFacade.currentUser() ?: throw UserNotFoundException
val post = postRepository.findById(postId)

post.addGood()
goodRepository.save(
Good(
post = post,
user = user
)
)
}
Comment on lines +18 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

addGood λ©”μ„œλ“œμ— λͺ‡ 가지 κ°œμ„ μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

λ©”μ„œλ“œμ˜ κΈ°λ³Έ κ΅¬μ‘°λŠ” μ’‹μ§€λ§Œ, λ‹€μŒ 사항듀을 κ°œμ„ ν•˜λ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€:

  1. κ²Œμ‹œλ¬Όμ„ 찾지 λͺ»ν–ˆμ„ λ•Œμ˜ μ˜ˆμ™Έ μ²˜λ¦¬κ°€ ν•„μš”ν•©λ‹ˆλ‹€.
  2. μ‚¬μš©μžκ°€ 같은 κ²Œμ‹œλ¬Όμ— μ—¬λŸ¬ 번 "μ’‹μ•„μš”"λ₯Ό λˆ„λ₯΄λŠ” 것을 λ°©μ§€ν•˜λŠ” 둜직이 ν•„μš”ν•©λ‹ˆλ‹€.
  3. μ‚¬μš©μžλ₯Ό 찾지 λͺ»ν–ˆμ„ λ•Œ λ˜μ§€λŠ” μ˜ˆμ™Έκ°€ μ˜¬λ°”λ₯΄κ²Œ μΈμŠ€ν„΄μŠ€ν™”λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μ½”λ“œλ₯Ό μˆ˜μ •ν•΄ λ³΄μ„Έμš”:

 @Transactional
 fun addGood(postId: Long) {
-    val user = userFacade.currentUser() ?: throw UserNotFoundException
-    val post = postRepository.findById(postId)
+    val user = userFacade.currentUser() ?: throw UserNotFoundException()
+    val post = postRepository.findById(postId).orElseThrow { PostNotFoundException(postId) }
+
+    if (goodRepository.existsByUserAndPost(user, post)) {
+        throw AlreadyGoodException(postId)
+    }

     post.addGood()
     goodRepository.save(
         Good(
             post = post,
             user = user
         )
     )
 }

이 변경사항듀은 μ˜ˆμ™Έ 처리λ₯Ό κ°œμ„ ν•˜κ³ , 쀑볡 "μ’‹μ•„μš”"λ₯Ό λ°©μ§€ν•©λ‹ˆλ‹€. PostNotFoundExceptionκ³Ό AlreadyGoodException은 λ³„λ„λ‘œ μ •μ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Transactional
fun addGood(postId: Long) {
val user = userFacade.currentUser() ?: throw UserNotFoundException
val post = postRepository.findById(postId)
post.addGood()
goodRepository.save(
Good(
post = post,
user = user
)
)
}
@Transactional
fun addGood(postId: Long) {
val user = userFacade.currentUser() ?: throw UserNotFoundException()
val post = postRepository.findById(postId).orElseThrow { PostNotFoundException(postId) }
if (goodRepository.existsByUserAndPost(user, post)) {
throw AlreadyGoodException(postId)
}
post.addGood()
goodRepository.save(
Good(
post = post,
user = user
)
)
}


@Transactional
fun deleteGood(postId: Long) {
val user = userFacade.currentUser() ?: throw UserNotFoundException
val post = postRepository.findById(postId)
val good = goodRepository.findByUserAndPost(user, post)

post.deleteGood()
goodRepository.delete(good)
}
Comment on lines +32 to +40
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

deleteGood λ©”μ„œλ“œλ„ κ°œμ„ μ΄ ν•„μš”ν•©λ‹ˆλ‹€.

이 λ©”μ„œλ“œλ„ addGoodκ³Ό μœ μ‚¬ν•œ λ¬Έμ œμ λ“€μ΄ μžˆμŠ΅λ‹ˆλ‹€:

  1. κ²Œμ‹œλ¬Όμ„ 찾지 λͺ»ν–ˆμ„ λ•Œμ˜ μ˜ˆμ™Έ μ²˜λ¦¬κ°€ ν•„μš”ν•©λ‹ˆλ‹€.
  2. Good μ—”ν‹°ν‹°κ°€ μ‘΄μž¬ν•˜μ§€ μ•Šμ„ κ²½μš°μ— λŒ€ν•œ μ²˜λ¦¬κ°€ ν•„μš”ν•©λ‹ˆλ‹€.
  3. μ‚¬μš©μžλ₯Ό 찾지 λͺ»ν–ˆμ„ λ•Œ λ˜μ§€λŠ” μ˜ˆμ™Έκ°€ μ˜¬λ°”λ₯΄κ²Œ μΈμŠ€ν„΄μŠ€ν™”λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μ½”λ“œλ₯Ό μˆ˜μ •ν•΄ λ³΄μ„Έμš”:

 @Transactional
 fun deleteGood(postId: Long) {
-    val user = userFacade.currentUser() ?: throw UserNotFoundException
-    val post = postRepository.findById(postId)
-    val good = goodRepository.findByUserAndPost(user, post)
+    val user = userFacade.currentUser() ?: throw UserNotFoundException()
+    val post = postRepository.findById(postId).orElseThrow { PostNotFoundException(postId) }
+    val good = goodRepository.findByUserAndPost(user, post) ?: throw GoodNotFoundException(postId)

     post.deleteGood()
     goodRepository.delete(good)
 }

이 변경사항듀은 μ˜ˆμ™Έ 처리λ₯Ό κ°œμ„ ν•˜κ³ , μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” "μ’‹μ•„μš”"λ₯Ό μ‚­μ œν•˜λ €λŠ” μ‹œλ„λ₯Ό λ°©μ§€ν•©λ‹ˆλ‹€. PostNotFoundExceptionκ³Ό GoodNotFoundException은 λ³„λ„λ‘œ μ •μ˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.

πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Transactional
fun deleteGood(postId: Long) {
val user = userFacade.currentUser() ?: throw UserNotFoundException
val post = postRepository.findById(postId)
val good = goodRepository.findByUserAndPost(user, post)
post.deleteGood()
goodRepository.delete(good)
}
@Transactional
fun deleteGood(postId: Long) {
val user = userFacade.currentUser() ?: throw UserNotFoundException()
val post = postRepository.findById(postId).orElseThrow { PostNotFoundException(postId) }
val good = goodRepository.findByUserAndPost(user, post) ?: throw GoodNotFoundException(postId)
post.deleteGood()
goodRepository.delete(good)
}

}
4 changes: 4 additions & 0 deletions src/main/kotlin/org/meogo/domain/post/domain/Post.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,9 @@ class Post(
this.good += 1
}

fun deleteGood() {
this.good -= 1
}
Comment on lines +65 to +67
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

음수 κ°’ 체크 μΆ”κ°€ ν•„μš”

deleteGood() λ©”μ„œλ“œμ—μ„œ good 속성이 0 μ΄ν•˜λ‘œ 내렀가지 μ•Šλ„λ‘ μ²΄ν¬ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. μ΄λŠ” 잘λͺ»λœ μƒνƒœλ₯Ό λ°©μ§€ν•˜λŠ” 데 도움이 λ©λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 μˆ˜μ •ν•˜λŠ” 것을 κ³ λ €ν•΄λ³΄μ„Έμš”:

 fun deleteGood() {
-    this.good -= 1
+    if (this.good > 0) {
+        this.good -= 1
+    }
 }
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fun deleteGood() {
this.good -= 1
}
fun deleteGood() {
if (this.good > 0) {
this.good -= 1
}
}


fun format(date: LocalDateTime) = date.format(DateTimeFormatter.ofPattern("yy.MM.dd HH:mm"))!!
}
Loading