diff --git a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt index 7afc77b..a8998c9 100644 --- a/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt +++ b/community-application/src/main/kotlin/gloddy/article/port/in/ArticleCommandUseCase.kt @@ -6,5 +6,5 @@ import gloddy.article.port.`in`.dto.read.ArticleCreateResponse interface ArticleCommandUseCase { fun create(userId: Long, command: ArticleCreateRequest): ArticleCreateResponse fun delete(userId: Long, articleId: Long) - fun like(userId: Long, articleId: Long) + fun upsertLike(userId: Long, articleId: Long) } \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt index 155a266..4e2fcee 100644 --- a/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt +++ b/community-application/src/main/kotlin/gloddy/article/port/out/ArticleCommandPersistencePort.kt @@ -1,8 +1,10 @@ package gloddy.article.port.out import gloddy.article.Article +import gloddy.article.ArticleLike interface ArticleCommandPersistencePort { fun save(article: Article) : Article fun delete(id: Long) + fun upsertLike(articleLike: ArticleLike, article: Article) } \ No newline at end of file diff --git a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt index ddfec45..c14c2fe 100644 --- a/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt +++ b/community-application/src/main/kotlin/gloddy/article/service/ArticleCommandService.kt @@ -20,10 +20,10 @@ class ArticleCommandService( private val articleQueryPersistencePort: ArticleQueryPersistencePort, private val articleCommandPersistencePort: ArticleCommandPersistencePort, private val articleLikeCommandPersistencePort: ArticleLikeCommandPersistencePort, - private val articleLikeQueryPersistencePort: ArticleLikeQueryPersistencePort + private val articleLikeQueryPersistencePort: ArticleLikeQueryPersistencePort, ) : ArticleCommandUseCase { - override fun create(userId: Long, command: ArticleCreateRequest) : ArticleCreateResponse { + override fun create(userId: Long, command: ArticleCreateRequest): ArticleCreateResponse { val category = categoryQueryPersistencePort.findById(CategoryId(command.categoryId)) @@ -43,17 +43,21 @@ class ArticleCommandService( articleCommandPersistencePort.delete(article.id!!.value) } - override fun like(userId: Long, articleId: Long) { - + override fun upsertLike(userId: Long, articleId: Long) { val article = articleQueryPersistencePort.findById(articleId) - articleLikeQueryPersistencePort.findByUserIdAndArticleOrNull(userId, article) - ?.run { articleLikeCommandPersistencePort.delete(this) } - ?: articleLikeCommandPersistencePort.save( - ArticleLike( + ?.run { + articleCommandPersistencePort.upsertLike( + articleLike = this, + article = article.unlike() + ) + } + ?: articleCommandPersistencePort.upsertLike( + articleLike = ArticleLike( userId = UserId(userId), article = article - ) + ), + article = article.like() ) } } \ No newline at end of file diff --git a/community-domain/src/main/kotlin/gloddy/article/Article.kt b/community-domain/src/main/kotlin/gloddy/article/Article.kt index 137524e..f7c9391 100644 --- a/community-domain/src/main/kotlin/gloddy/article/Article.kt +++ b/community-domain/src/main/kotlin/gloddy/article/Article.kt @@ -8,12 +8,12 @@ import gloddy.core.UserId data class Article( val userId: UserId, - var category: Category, - var title: String, - var content: String, - var image: ArticleImage, - var commentCount: Int = 0, - var likeCount: Int = 0, + val category: Category, + val title: String, + val content: String, + val image: ArticleImage, + val commentCount: Int = 0, + val likeCount: Int = 0, val id: ArticleId? = null, ) { constructor( @@ -37,4 +37,14 @@ data class Article( throw ArticleNoAuthorizationException() } } + + fun like(): Article = + this.copy( + likeCount = this.likeCount + 1 + ) + + fun unlike(): Article = + this.copy( + likeCount = this.likeCount - 1 + ) } \ No newline at end of file diff --git a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt index cb52cd5..4898a6f 100644 --- a/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt +++ b/community-in-api/src/main/kotlin/gloddy/controller/article/ArticleCommandController.kt @@ -36,7 +36,7 @@ class ArticleCommandController( @PostMapping("/articles/{articleId}/like") override fun like(@RequestHeader("USER_ID") userId: Long, @PathVariable("articleId") articleId: Long) : ResponseEntity> { - articleCommandUseCase.like(userId, articleId) + articleCommandUseCase.upsertLike(userId, articleId) return ApiResponseEntityWrapper().noContent() } } \ No newline at end of file diff --git a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt index bdaca04..0251b83 100644 --- a/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt +++ b/community-infrastructure/src/main/kotlin/gloddy/persistence/article/adapter/ArticleCommandPersistenceAdapter.kt @@ -1,10 +1,12 @@ package gloddy.persistence.article.adapter import gloddy.article.Article +import gloddy.article.ArticleLike import gloddy.article.exception.ArticleNotFoundException import gloddy.article.port.out.ArticleCommandPersistencePort import gloddy.persistence.article.ArticleJpaEntity import gloddy.persistence.article.repository.ArticleJpaRepository +import gloddy.persistence.article.repository.ArticleLikeJpaRepository import gloddy.persistence.util.mapper.toDomain import gloddy.persistence.util.mapper.toEntity import org.springframework.data.repository.findByIdOrNull @@ -14,7 +16,8 @@ import org.springframework.transaction.annotation.Transactional @Component @Transactional class ArticleCommandPersistenceAdapter( - private val articleJpaRepository: ArticleJpaRepository + private val articleJpaRepository: ArticleJpaRepository, + private val articleLikeJpaRepository: ArticleLikeJpaRepository ) : ArticleCommandPersistencePort { override fun save(article: Article): Article { @@ -26,6 +29,18 @@ class ArticleCommandPersistenceAdapter( articleJpaEntity.changeDeletedToTrue() } + override fun upsertLike(articleLike: ArticleLike, article: Article) { + save(article) + articleLike + .run { + if (articleLike.id == null) { + articleLikeJpaRepository.save(this.toEntity()) + } else { + articleLikeJpaRepository.delete(this.toEntity()) + } + } + } + fun find(id: Long): ArticleJpaEntity { return articleJpaRepository.findByIdOrNull(id) ?: throw ArticleNotFoundException() }