Skip to content

Commit

Permalink
[feat #179] 미분류 링크 삭제(선택, 전체) API (#181)
Browse files Browse the repository at this point in the history
* feat : 미분류 링크 목록 삭제 API

* feat : 미분류 링크 목록 삭제 로직 구현

* feat : 미분류 카테고리 조회, 링크 벌크 삭제 쿼리 구

* refactor : 주석, 로그 제거
  • Loading branch information
dlswns2480 authored Nov 16, 2024
1 parent 789f087 commit 411e347
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import com.pokit.common.dto.SliceResponseDto
import com.pokit.common.wrapper.ResponseWrapper.wrapOk
import com.pokit.common.wrapper.ResponseWrapper.wrapSlice
import com.pokit.common.wrapper.ResponseWrapper.wrapUnit
import com.pokit.content.dto.request.ContentSearchParams
import com.pokit.content.dto.request.CreateContentRequest
import com.pokit.content.dto.request.UpdateContentRequest
import com.pokit.content.dto.request.toDto
import com.pokit.content.dto.response.*
import com.pokit.content.dto.request.*
import com.pokit.content.dto.response.BookMarkContentResponse
import com.pokit.content.dto.response.ContentResponse
import com.pokit.content.dto.response.ContentsResponse
import com.pokit.content.dto.response.toResponse
import com.pokit.content.exception.ContentErrorCode
import com.pokit.content.port.`in`.ContentUseCase
import io.swagger.v3.oas.annotations.Operation
Expand Down Expand Up @@ -169,5 +169,17 @@ class ContentController(
.wrapSlice()
.wrapOk()
}

@PutMapping("/uncategorized")
@Operation(summary = "미분류 링크 삭제 API")
@ErrorOperation(ContentErrorCode::class)
fun deleteUncategorizedContents(
@AuthenticationPrincipal user: PrincipalUser,
@RequestBody request: DeleteUncategorizedRequest
): ResponseEntity<Unit> {
return contentUseCase.deleteUncategorized(user.id, request.toDto())
.wrapUnit()
}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.pokit.content.dto.request

data class DeleteUncategorizedRequest(
val contentId: List<Long>
)

internal fun DeleteUncategorizedRequest.toDto() = this.contentId.map { it }


Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,9 @@ class CategoryAdapter(
override fun loadByIdAndOpenType(id: Long, openType: OpenType): Category? =
categoryRepository.findByIdAndOpenTypeAndDeleted(id, openType, false)?.toDomain()

override fun loadByNameAndUserId(categoryName: String, userId: Long): Category? {
return categoryRepository.findByNameAndUserId(categoryName, userId)
?.toDomain()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ interface CategoryRepository : JpaRepository<CategoryEntity, Long> {
fun findByUserIdAndDeleted(userId: Long, deleted: Boolean, pageable: Pageable): Slice<CategoryEntity>
fun findByIdAndUserIdAndDeleted(id: Long, userId: Long, deleted: Boolean): CategoryEntity?
fun countByUserIdAndDeleted(userId: Long, deleted: Boolean): Int
fun findByIdAndOpenTypeAndDeleted(id: Long, openType: OpenType, deleted:Boolean): CategoryEntity?
fun findByIdAndOpenTypeAndDeleted(id: Long, openType: OpenType, deleted: Boolean): CategoryEntity?
fun findByNameAndUserId(name: String, userId: Long): CategoryEntity?
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ class ContentAdapter(
return contentRepository.findByIdInWithUser(contetIds)
}

override fun deleteAllByIds(contentIds: List<Long>) {
contentRepository.deleteByContentIds(contentIds)
}

override fun loadByContentIds(contentIds: List<Long>): List<Content> =
contentRepository.findByIdIn(contentIds)
.map { it.toDomain() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ interface ContentRepository : JpaRepository<ContentEntity, Long>, ContentJdbcRep
fun countByCategoryIdAndDeleted(id: Long, deleted: Boolean): Int

@Modifying(clearAutomatically = true)
@Query("""
@Query(
"""
update ContentEntity c set c.deleted = true
where c.categoryId in
(select ct.id from CategoryEntity ct where ct.userId = :userId)
""")
"""
)
fun deleteByUserId(@Param("userId") userId: Long)

fun findByIdIn(ids: List<Long>): List<ContentEntity>
Expand All @@ -42,11 +44,22 @@ interface ContentRepository : JpaRepository<ContentEntity, Long>, ContentJdbcRep
)
fun countByUserId(userId: Long): Int

@Query("""
@Query(
"""
select new com.pokit.content.model.ContentWithUser(c.id, u.id, c.title, c.thumbNail) from ContentEntity c
join CategoryEntity ca on ca.id = c.categoryId
join UserEntity u on u.id = ca.userId
where c.id in :ids
""")
"""
)
fun findByIdInWithUser(ids: List<Long>): List<ContentWithUser>

@Modifying(clearAutomatically = true)
@Query(
"""
update ContentEntity c set c.deleted = true
where c.id in :contentIds
"""
)
fun deleteByContentIds(@Param("contentIds") contentIds: List<Long>)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ interface CategoryPort {
fun delete(category: Category)
fun countByUserId(userId: Long): Int
fun loadByIdAndOpenType(id: Long, openType: OpenType): Category?
fun loadByNameAndUserId(categoryName: String, userId: Long): Category?
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,6 @@ interface ContentUseCase {
fun getUnreadCount(userId: Long): Int

fun getBookmarkCount(userId: Long): Int

fun deleteUncategorized(userId: Long, contentIds: List<Long>)
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.pokit.content.port.out

import com.pokit.category.model.OpenType
import com.pokit.content.dto.response.ContentsResult
import com.pokit.content.dto.request.ContentSearchCondition
import com.pokit.content.dto.response.ContentsResult
import com.pokit.content.dto.response.SharedContentResult
import com.pokit.content.model.Content
import com.pokit.content.model.ContentWithUser
Expand Down Expand Up @@ -47,4 +47,5 @@ interface ContentPort {
fun duplicateContent(originCategoryId: Long, targetCategoryId: Long)

fun loadByContentIdsWithUser(contetIds: List<Long>): List<ContentWithUser>
fun deleteAllByIds(contentIds: List<Long>)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import com.pokit.bookmark.model.Bookmark
import com.pokit.bookmark.port.out.BookmarkPort
import com.pokit.category.exception.CategoryErrorCode
import com.pokit.category.model.Category
import com.pokit.category.model.CategoryStatus.UNCATEGORIZED
import com.pokit.category.model.OpenType
import com.pokit.category.port.out.CategoryPort
import com.pokit.category.port.service.loadCategoryOrThrow
import com.pokit.common.exception.AlreadyExistsException
import com.pokit.common.exception.ClientValidationException
import com.pokit.common.exception.NotFoundCustomException
import com.pokit.content.dto.request.ContentCommand
import com.pokit.content.dto.request.ContentSearchCondition
Expand Down Expand Up @@ -164,6 +166,21 @@ class ContentService(
override fun getBookmarkCount(userId: Long) =
contentCountPort.getBookmarkCount(userId)

@Transactional
override fun deleteUncategorized(userId: Long, contentIds: List<Long>) {
val category = (categoryPort.loadByNameAndUserId(UNCATEGORIZED.displayName, userId)
?: throw NotFoundCustomException(CategoryErrorCode.NOT_FOUND_UNCATEGORIZED))

val contents = contentPort.loadByContentIds(contentIds)
contents.forEach {
if (it.categoryId != category.categoryId) {
throw ClientValidationException(ContentErrorCode.NOT_UNCATEGORIZED_CONTENT)
}
}

contentPort.deleteAllByIds(contentIds)
}

private fun verifyContent(userId: Long, contentId: Long): Content {
return contentPort.loadByUserIdAndId(userId, contentId)
?: throw NotFoundCustomException(ContentErrorCode.NOT_FOUND_CONTENT)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ enum class CategoryErrorCode(
MAX_CATEGORY_LIMIT_EXCEEDED("최대 30개의 포킷을 생성할 수 있습니다. 포킷을 삭제한 뒤에 추가해주세요.", "CA_005"),
NOT_FOUND_UNCATEGORIZED_IMAGE("미분류 카테고리 이미지를 찾는데 실패했습니다.", "CA_006"),
SHARE_ALREADY_EXISTS_CATEGORY("직접 생성한 포킷은 공유받을 수 없습니다.\n 다른 유저의 포킷을 공유받아보세요.", "CA_007"),
NOT_FOUND_UNCATEGORIZED("사용자가 미분류 카테고리가 없습니다.(서버 에러)", "CA_008"),

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ enum class ContentErrorCode(
override val message: String,
override val code: String
) : ErrorCode {
NOT_FOUND_CONTENT("존재하지 않는 컨텐츠입니다.", "C_001")
NOT_FOUND_CONTENT("존재하지 않는 컨텐츠입니다.", "C_001"),
NOT_UNCATEGORIZED_CONTENT("해당 링크는 미분류 카테고리에 있지 않습니다.", "C_002"),
}

0 comments on commit 411e347

Please sign in to comment.