diff --git a/src/main/java/project/flipnote/bookmark/repository/BookmarkRepository.java b/src/main/java/project/flipnote/bookmark/repository/BookmarkRepository.java index 265bb96..bad19d7 100644 --- a/src/main/java/project/flipnote/bookmark/repository/BookmarkRepository.java +++ b/src/main/java/project/flipnote/bookmark/repository/BookmarkRepository.java @@ -21,4 +21,6 @@ public interface BookmarkRepository extends JpaRepository { List findAllByTargetTypeAndUserIdAndTargetIdIn( BookmarkTargetType targetType, Long userId, Set targetIds ); + + int deleteByTargetTypeAndTargetId(BookmarkTargetType targetType, Long targetId); } diff --git a/src/main/java/project/flipnote/bookmark/service/BookmarkWriter.java b/src/main/java/project/flipnote/bookmark/service/BookmarkWriter.java new file mode 100644 index 0000000..c0bcd97 --- /dev/null +++ b/src/main/java/project/flipnote/bookmark/service/BookmarkWriter.java @@ -0,0 +1,24 @@ +package project.flipnote.bookmark.service; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import project.flipnote.bookmark.entity.BookmarkTargetType; +import project.flipnote.bookmark.repository.BookmarkRepository; + +@Service +@RequiredArgsConstructor +public class BookmarkWriter { + private final BookmarkRepository bookmarkRepository; + + /** + * 즐겨찾기를 삭제합니다. + * + * @param targetType 즐겨찾기 삭제할 대상의 타입 + * @param targetId 즐겨찾기 삭제할 대상의 ID + * @author 윤정환 + */ + public void delete(BookmarkTargetType targetType, Long targetId) { + bookmarkRepository.deleteByTargetTypeAndTargetId(targetType, targetId); + } +} diff --git a/src/main/java/project/flipnote/cardset/controller/GroupCardSetController.java b/src/main/java/project/flipnote/cardset/controller/GroupCardSetController.java index 2af768d..6925b11 100644 --- a/src/main/java/project/flipnote/cardset/controller/GroupCardSetController.java +++ b/src/main/java/project/flipnote/cardset/controller/GroupCardSetController.java @@ -3,6 +3,7 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; @@ -22,6 +23,7 @@ import project.flipnote.cardset.model.CreateCardSetRequest; import project.flipnote.cardset.model.CreateCardSetResponse; import project.flipnote.cardset.service.CardSetService; +import project.flipnote.common.model.response.IdResponse; import project.flipnote.common.model.response.PagingResponse; import project.flipnote.common.security.dto.AuthPrinciple; @@ -75,4 +77,15 @@ public ResponseEntity> getCardSets( return ResponseEntity.ok(res); } + + @DeleteMapping("/{cardSetId}") + public ResponseEntity deleteCardSet( + @PathVariable("groupId") Long groupId, + @PathVariable("cardSetId") Long cardSetId, + @AuthenticationPrincipal AuthPrinciple authPrinciple + ) { + IdResponse res = cardSetService.deleteCardSet(authPrinciple.userId(), groupId, cardSetId); + + return ResponseEntity.ok(res); + } } diff --git a/src/main/java/project/flipnote/cardset/entity/CardSetContent.java b/src/main/java/project/flipnote/cardset/entity/CardSetContent.java new file mode 100644 index 0000000..b2674f2 --- /dev/null +++ b/src/main/java/project/flipnote/cardset/entity/CardSetContent.java @@ -0,0 +1,38 @@ +package project.flipnote.cardset.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import project.flipnote.common.entity.BaseEntity; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "cardset_contents") +@Entity +public class CardSetContent extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "cardset_id", nullable = false) + private Long cardSetId; + + @Lob + @Column(nullable = false) + private String content; + + @Builder + private CardSetContent(Long cardSetId, String content) { + this.cardSetId = cardSetId; + this.content = content; + } +} diff --git a/src/main/java/project/flipnote/cardset/entity/CardSetIncremental.java b/src/main/java/project/flipnote/cardset/entity/CardSetIncremental.java new file mode 100644 index 0000000..0a7586d --- /dev/null +++ b/src/main/java/project/flipnote/cardset/entity/CardSetIncremental.java @@ -0,0 +1,42 @@ +package project.flipnote.cardset.entity; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import project.flipnote.common.entity.BaseEntity; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "cardset_incrementals") +@Entity +public class CardSetIncremental extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "cardset_id", nullable = false) + private Long cardSetId; + + @Lob + @Column(name = "incremental_value", nullable = false) + private byte[] incrementalValue; + + @Column(name = "is_flushed") + private boolean flushed; + + @Builder + private CardSetIncremental(Long cardSetId, byte[] incrementalValue, boolean flushed) { + this.cardSetId = cardSetId; + this.incrementalValue = incrementalValue; + this.flushed = flushed; + } +} diff --git a/src/main/java/project/flipnote/cardset/repository/CardSetContentRepository.java b/src/main/java/project/flipnote/cardset/repository/CardSetContentRepository.java new file mode 100644 index 0000000..6acc2a5 --- /dev/null +++ b/src/main/java/project/flipnote/cardset/repository/CardSetContentRepository.java @@ -0,0 +1,9 @@ +package project.flipnote.cardset.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import project.flipnote.cardset.entity.CardSetContent; + +public interface CardSetContentRepository extends JpaRepository { + void deleteByCardSetId(Long cardSetId); +} diff --git a/src/main/java/project/flipnote/cardset/repository/CardSetIncrementalRepository.java b/src/main/java/project/flipnote/cardset/repository/CardSetIncrementalRepository.java new file mode 100644 index 0000000..3064465 --- /dev/null +++ b/src/main/java/project/flipnote/cardset/repository/CardSetIncrementalRepository.java @@ -0,0 +1,9 @@ +package project.flipnote.cardset.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import project.flipnote.cardset.entity.CardSetIncremental; + +public interface CardSetIncrementalRepository extends JpaRepository { + void deleteByCardSetId(Long cardSetId); +} diff --git a/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java b/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java index 0236772..ea16c5b 100644 --- a/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java +++ b/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java @@ -9,4 +9,6 @@ public interface CardSetManagerRepository extends JpaRepository { boolean existsByUser_IdAndCardSet_Id(Long userId, Long cardSetId); + + int deleteByCardSet_Id(Long cardSetId); } diff --git a/src/main/java/project/flipnote/cardset/service/CardSetService.java b/src/main/java/project/flipnote/cardset/service/CardSetService.java index 67cff14..6df1e27 100644 --- a/src/main/java/project/flipnote/cardset/service/CardSetService.java +++ b/src/main/java/project/flipnote/cardset/service/CardSetService.java @@ -12,7 +12,7 @@ import lombok.extern.slf4j.Slf4j; import project.flipnote.bookmark.entity.BookmarkTargetType; import project.flipnote.bookmark.service.BookmarkReader; -import project.flipnote.bookmark.service.BookmarkService; +import project.flipnote.bookmark.service.BookmarkWriter; import project.flipnote.cardset.entity.CardSet; import project.flipnote.cardset.entity.CardSetManager; import project.flipnote.cardset.entity.CardSetMetadata; @@ -25,10 +25,13 @@ import project.flipnote.cardset.model.CardSetUpdateRequest; import project.flipnote.cardset.model.CreateCardSetRequest; import project.flipnote.cardset.model.CreateCardSetResponse; +import project.flipnote.cardset.repository.CardSetContentRepository; +import project.flipnote.cardset.repository.CardSetIncrementalRepository; import project.flipnote.cardset.repository.CardSetManagerRepository; import project.flipnote.cardset.repository.CardSetMetadataRepository; import project.flipnote.cardset.repository.CardSetRepository; import project.flipnote.common.exception.BizException; +import project.flipnote.common.model.response.IdResponse; import project.flipnote.common.model.response.PagingResponse; import project.flipnote.common.security.dto.AuthPrinciple; import project.flipnote.group.entity.Category; @@ -44,6 +47,7 @@ import project.flipnote.image.service.ImageService; import project.flipnote.like.entity.LikeTargetType; import project.flipnote.like.service.LikeReader; +import project.flipnote.like.service.LikeWriter; import project.flipnote.user.entity.UserProfile; import project.flipnote.user.entity.UserStatus; import project.flipnote.user.exception.UserErrorCode; @@ -67,6 +71,10 @@ public class CardSetService { private final GroupService groupService; private final LikeReader likeReader; private final BookmarkReader bookmarkReader; + private final LikeWriter likeWriter; + private final BookmarkWriter bookmarkWriter; + private final CardSetContentRepository cardSetContentRepository; + private final CardSetIncrementalRepository cardSetIncrementalRepository; @Value("${image.default.cardSet}") private String defaultCardSetImage; @@ -357,4 +365,40 @@ public PagingResponse getCardSets(long groupId, CardSetS return PagingResponse.from(res); } + + @Transactional + public IdResponse deleteCardSet(Long userId, Long groupId, Long cardSetId) { + CardSet cardSet = cardSetPolicyService.findByIdAndGroupIdOrThrow(groupId, cardSetId); + + cardSetPolicyService.validateCardSetEditable(userId, cardSetId); + + // 카드셋 관리자 + cardSetManagerRepository.deleteByCardSet_Id(cardSetId); + + // 카드셋 내용 + cardSetContentRepository.deleteByCardSetId(cardSetId); + + // 카드셋 증분값 + cardSetIncrementalRepository.deleteByCardSetId(cardSetId); + + // 카드셋 스냅샷 + + // 카드셋 메타데이터 + cardSetMetadataRepository.deleteById(cardSetId); + + // 이미지 + imageRefService.findByTypeAndReferenceId(REFERENCE_TYPE, cardSetId) + .ifPresent(imageRef -> imageRefService.deleteByReferenceAndId(REFERENCE_TYPE, imageRef.getId())); + + // 카드셋 + cardSetRepository.delete(cardSet); + + // 좋아요 + likeWriter.delete(LikeTargetType.CARD_SET, cardSetId); + + // 즐겨찾기 + bookmarkWriter.delete(BookmarkTargetType.CARD_SET, cardSetId); + + return IdResponse.from(cardSetId); + } } diff --git a/src/main/java/project/flipnote/like/repository/LikeRepository.java b/src/main/java/project/flipnote/like/repository/LikeRepository.java index df31276..bc61ca5 100644 --- a/src/main/java/project/flipnote/like/repository/LikeRepository.java +++ b/src/main/java/project/flipnote/like/repository/LikeRepository.java @@ -15,4 +15,6 @@ public interface LikeRepository extends JpaRepository { Optional findByTargetTypeAndTargetIdAndUserId(LikeTargetType targetType, Long targetId, Long userId); Page findByTargetTypeAndUserId(LikeTargetType targetType, Long userId, Pageable pageable); + + int deleteByTargetTypeAndTargetId(LikeTargetType targetType, Long targetId); } diff --git a/src/main/java/project/flipnote/like/service/LikeWriter.java b/src/main/java/project/flipnote/like/service/LikeWriter.java new file mode 100644 index 0000000..d50b27a --- /dev/null +++ b/src/main/java/project/flipnote/like/service/LikeWriter.java @@ -0,0 +1,24 @@ +package project.flipnote.like.service; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import project.flipnote.like.entity.LikeTargetType; +import project.flipnote.like.repository.LikeRepository; + +@RequiredArgsConstructor +@Service +public class LikeWriter { + private final LikeRepository likeRepository; + + /** + * 좋아요를 삭제합니다. + * + * @param targetType 좋아요 삭제 대상의 타입 + * @param targetId 좋아요 삭제 대상의 ID + * @author 윤정환 + */ + public void delete(LikeTargetType targetType, Long targetId) { + likeRepository.deleteByTargetTypeAndTargetId(targetType, targetId); + } +}