diff --git a/src/main/java/project/flipnote/cardset/controller/docs/GroupCardSetControllerDocs.java b/src/main/java/project/flipnote/cardset/controller/docs/GroupCardSetControllerDocs.java index 0b450cc4..5919b406 100644 --- a/src/main/java/project/flipnote/cardset/controller/docs/GroupCardSetControllerDocs.java +++ b/src/main/java/project/flipnote/cardset/controller/docs/GroupCardSetControllerDocs.java @@ -6,9 +6,13 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; import project.flipnote.cardset.model.CardSetDetailResponse; +import project.flipnote.cardset.model.CardSetSearchRequest; +import project.flipnote.cardset.model.CardSetSummaryResponse; import project.flipnote.cardset.model.CardSetUpdateRequest; import project.flipnote.cardset.model.CreateCardSetRequest; import project.flipnote.cardset.model.CreateCardSetResponse; +import project.flipnote.common.model.response.IdResponse; +import project.flipnote.common.model.response.PagingResponse; import project.flipnote.common.security.dto.AuthPrinciple; @Tag(name = "CardSet", description = "CardSet API") @@ -29,4 +33,10 @@ ResponseEntity updateCardSet( CardSetUpdateRequest req, AuthPrinciple authPrinciple ); + + @Operation(summary = "그룹별 카드셋 조회", security = {@SecurityRequirement(name = "access-token")}) + ResponseEntity> getCardSets(Long groupId, CardSetSearchRequest req); + + @Operation(summary = "카드셋 삭제", security = {@SecurityRequirement(name = "access-token")}) + ResponseEntity deleteCardSet(Long groupId, Long cardSetId, AuthPrinciple authPrinciple); } diff --git a/src/main/java/project/flipnote/cardset/entity/CardSet.java b/src/main/java/project/flipnote/cardset/entity/CardSet.java index d147b9b0..eaa7c605 100644 --- a/src/main/java/project/flipnote/cardset/entity/CardSet.java +++ b/src/main/java/project/flipnote/cardset/entity/CardSet.java @@ -32,6 +32,9 @@ public class CardSet extends BaseEntity { @Column(nullable = false, length = 50) private String name; + @Column(nullable = false) + private Long author; + @ManyToOne @JoinColumn(name = "group_id", nullable = false) private Group group; @@ -48,9 +51,17 @@ public class CardSet extends BaseEntity { private String imageUrl; @Builder - private CardSet(String name, Group group, Boolean publicVisible, Category category, String hashtag, - String imageUrl) { + private CardSet( + String name, + Long author, + Group group, + Boolean publicVisible, + Category category, + String hashtag, + String imageUrl + ) { this.name = name; + this.author = author; this.group = group; this.publicVisible = publicVisible; this.category = category; diff --git a/src/main/java/project/flipnote/cardset/model/CardSetUpdateRequest.java b/src/main/java/project/flipnote/cardset/model/CardSetUpdateRequest.java index c2b3d36b..f1fb833a 100644 --- a/src/main/java/project/flipnote/cardset/model/CardSetUpdateRequest.java +++ b/src/main/java/project/flipnote/cardset/model/CardSetUpdateRequest.java @@ -1,11 +1,11 @@ package project.flipnote.cardset.model; import java.util.List; - -import org.hibernate.validator.constraints.URL; +import java.util.Set; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import project.flipnote.group.entity.Category; @@ -25,6 +25,9 @@ public record CardSetUpdateRequest( @NotNull List hashtag, + @NotEmpty @Size(min = 1) + Set managers, + Long imageRefId ) { diff --git a/src/main/java/project/flipnote/cardset/model/CreateCardSetRequest.java b/src/main/java/project/flipnote/cardset/model/CreateCardSetRequest.java index 6eab3bcf..e7dec7c2 100644 --- a/src/main/java/project/flipnote/cardset/model/CreateCardSetRequest.java +++ b/src/main/java/project/flipnote/cardset/model/CreateCardSetRequest.java @@ -1,10 +1,10 @@ package project.flipnote.cardset.model; import java.util.List; - -import org.hibernate.validator.constraints.URL; +import java.util.Set; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import project.flipnote.group.entity.Category; @@ -24,6 +24,9 @@ public record CreateCardSetRequest( @NotNull List hashtag, + @NotEmpty @Size(min = 1) + Set managers, + Long imageRefId ) { } diff --git a/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java b/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java index ea16c5b5..2b537eb8 100644 --- a/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java +++ b/src/main/java/project/flipnote/cardset/repository/CardSetManagerRepository.java @@ -1,6 +1,9 @@ package project.flipnote.cardset.repository; +import java.util.Set; + import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import project.flipnote.cardset.entity.CardSetManager; @@ -11,4 +14,9 @@ public interface CardSetManagerRepository extends JpaRepository findUserIdsByCardSetId(Long cardSetId); + + int deleteByCardSet_IdAndUser_IdIn(Long cardSetId, Set userIds); } diff --git a/src/main/java/project/flipnote/cardset/service/CardSetManagerWriter.java b/src/main/java/project/flipnote/cardset/service/CardSetManagerWriter.java new file mode 100644 index 00000000..9ed431ea --- /dev/null +++ b/src/main/java/project/flipnote/cardset/service/CardSetManagerWriter.java @@ -0,0 +1,83 @@ +package project.flipnote.cardset.service; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.springframework.stereotype.Service; + +import lombok.RequiredArgsConstructor; +import project.flipnote.cardset.entity.CardSet; +import project.flipnote.cardset.entity.CardSetManager; +import project.flipnote.cardset.repository.CardSetManagerRepository; +import project.flipnote.user.repository.UserProfileRepository; + +@RequiredArgsConstructor +@Service +public class CardSetManagerWriter { + + private final CardSetManagerRepository cardSetManagerRepository; + private final UserProfileRepository userProfileRepository; + + /** + * 카드셋에 매니저들을 할당 + * 카드셋 생성시 생성자는 항상 매니저로 포함됨 + * + * @param cardSet 매니저를 할당할 카드셋 + * @param managerIds 요청된 매니저 ID 목록 + * @author 윤정환 + */ + public void assignManagers(CardSet cardSet, Set managerIds) { + Set finalManagerIds = includeAuthor(cardSet.getAuthor(), managerIds); + + List managers = finalManagerIds.stream() + .map(id -> CardSetManager.builder() + .cardSet(cardSet) + .user(userProfileRepository.getReferenceById(id)) + .build()) + .toList(); + + cardSetManagerRepository.saveAll(managers); + } + + /** + * 카드셋의 매니저를 수정 + * 차집합을 이용해 삭제/추가할 매니저만 처리 + * + * @param cardSet 매니저를 수정할 카드셋 + * @param newManagerIds 새로운 매니저 ID 목록 + * @author 윤정환 + */ + public void updateManagers(CardSet cardSet, Set newManagerIds) { + Set currentManagerIds = cardSetManagerRepository.findUserIdsByCardSetId(cardSet.getId()); + + Set toDelete = difference(currentManagerIds, newManagerIds); + Set toAdd = difference(newManagerIds, currentManagerIds); + + if (!toDelete.isEmpty()) { + cardSetManagerRepository.deleteByCardSet_IdAndUser_IdIn(cardSet.getId(), toDelete); + } + + if (!toAdd.isEmpty()) { + List managers = toAdd.stream() + .map(id -> CardSetManager.builder() + .cardSet(cardSet) + .user(userProfileRepository.getReferenceById(id)) + .build()) + .toList(); + cardSetManagerRepository.saveAll(managers); + } + } + + private Set includeAuthor(Long authorId, Set managerIds) { + Set result = new HashSet<>(managerIds); + result.add(authorId); + return result; + } + + private Set difference(Set a, Set b) { + Set result = new HashSet<>(a); + result.removeAll(b); + return result; + } +} diff --git a/src/main/java/project/flipnote/cardset/service/CardSetService.java b/src/main/java/project/flipnote/cardset/service/CardSetService.java index 6df1e271..9e2ef4b6 100644 --- a/src/main/java/project/flipnote/cardset/service/CardSetService.java +++ b/src/main/java/project/flipnote/cardset/service/CardSetService.java @@ -14,7 +14,6 @@ import project.flipnote.bookmark.service.BookmarkReader; import project.flipnote.bookmark.service.BookmarkWriter; import project.flipnote.cardset.entity.CardSet; -import project.flipnote.cardset.entity.CardSetManager; import project.flipnote.cardset.entity.CardSetMetadata; import project.flipnote.cardset.exception.CardSetErrorCode; import project.flipnote.cardset.model.CardSetDetailResponse; @@ -64,6 +63,7 @@ public class CardSetService { private final GroupRepository groupRepository; private final GroupMemberRepository groupMemberRepository; private final CardSetManagerRepository cardSetManagerRepository; + private final CardSetManagerWriter cardSetManagerWriter; private final CardSetPolicyService cardSetPolicyService; private final CardSetMetadataRepository cardSetMetadataRepository; private final ImageService imageService; @@ -121,6 +121,7 @@ public CreateCardSetResponse createCardSet(Long groupId, AuthPrinciple authPrinc CardSet cardSet = CardSet.builder() .name(req.name()) + .author(user.getId()) .group(group) .publicVisible(req.publicVisible()) .category(req.category()) @@ -140,13 +141,7 @@ public CreateCardSetResponse createCardSet(Long groupId, AuthPrinciple authPrinc .build(); cardSetMetadataRepository.save(metadata); - //카드셋 매니저도 저장 - CardSetManager cardSetManager = CardSetManager.builder() - .user(user) - .cardSet(cardSet) - .build(); - - cardSetManagerRepository.save(cardSetManager); + cardSetManagerWriter.assignManagers(cardSet, req.managers()); return CreateCardSetResponse.from(cardSet.getId()); } @@ -216,6 +211,8 @@ public CardSetDetailResponse updateCardSet(Long userId, Long groupId, Long cardS cardSetRepository.saveAndFlush(cardSet); + cardSetManagerWriter.updateManagers(cardSet, req.managers()); + boolean liked = likeReader.isLiked(userId, LikeTargetType.CARD_SET, cardSetId); boolean bookmarked = bookmarkReader.isBookmarked(userId, BookmarkTargetType.CARD_SET, cardSetId);