From 97624af8d144e7ad4d570a8e0b7d4cff2b25d1df Mon Sep 17 00:00:00 2001 From: pizzazoa Date: Wed, 22 Jul 2026 23:53:15 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EC=83=88=EB=A1=9D=EC=9D=B4=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=EB=90=98=EB=8A=94=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=EC=97=90=20canSuggestBirdId=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 당장 필요없어 보여도 기획이 어떻게 달라질지 몰라 일단 추가한 것도 있음 --- .../api/BirdIdSuggestionController.java | 2 +- .../collection/api/CollectionController.java | 1 + .../api/CollectionLikeController.java | 2 +- .../GetCollectionEditDataResponse.java | 3 + .../response/GetLikedCollectionsResponse.java | 5 +- .../GetNearbyCollectionsResponse.java | 3 + .../GetPendingCollectionsResponse.java | 5 +- .../dto/response/MyCollectionsResponse.java | 5 +- .../response/UpdateCollectionResponse.java | 5 +- .../BirdIdSuggestionQueryService.java | 3 +- .../CollectionLikeQueryService.java | 2 +- .../application/CollectionQueryService.java | 3 +- .../mapper/CollectionLikeWebMapper.java | 3 +- .../mapper/CollectionWebMapper.java | 3 + .../api/dto/response/UserProfileResponse.java | 5 +- .../profile/mapper/UserProfileMapper.java | 3 +- .../BirdIdSuggestionQueryServiceTest.java | 4 + .../CollectionQueryServiceTest.java | 45 ++++++++++ .../CollectionSuggestionFlagMapperTest.java | 86 +++++++++++++++++++ 19 files changed, 176 insertions(+), 12 deletions(-) create mode 100644 src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/BirdIdSuggestionController.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/BirdIdSuggestionController.java index 2d26f8c6..f2e7637f 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/BirdIdSuggestionController.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/BirdIdSuggestionController.java @@ -31,7 +31,7 @@ public class BirdIdSuggestionController { @PermitAll @Operation( summary = "동정 의견을 기다리는 컬렉션 목록 조회", - description = "bird_id 미확정 PUBLIC 컬렉션 목록을 조회", + description = "bird_id가 미확정이고 동정 의견을 받는 PUBLIC 컬렉션 목록을 조회", responses = @ApiResponse( responseCode = "200", description = "조회 성공", content = @Content(schema = @Schema(implementation = GetPendingCollectionsResponse.class)) diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionController.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionController.java index 667b2091..e84e1dc7 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionController.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionController.java @@ -245,6 +245,7 @@ public GetCollectionDetailResponse getCollectionDetail( - commentCount - createdAt - discoveredDate + - canSuggestBirdId """, responses = { @ApiResponse( diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionLikeController.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionLikeController.java index 9b3d2eb3..954866e7 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionLikeController.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/CollectionLikeController.java @@ -77,7 +77,7 @@ public LikeStatusResponse getLikeStatus( security = @SecurityRequirement(name = "bearerAuth"), description = "내가 좋아요한 컬렉션 목록을 조회합니다.", responses = { - @ApiResponse(responseCode = "200", description = "좋아요한 컬렉션 ID 목록 조회 성공", + @ApiResponse(responseCode = "200", description = "좋아요한 컬렉션 목록 조회 성공", content = @Content(schema = @Schema(implementation = GetLikedCollectionsResponse.class))), @ApiResponse(responseCode = "401", description = "사용자 인증 실패", content = @Content), @ApiResponse(responseCode = "404", description = "사용자가 존재하지 않음", content = @Content) diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java index 8b567046..0053fab1 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java @@ -37,6 +37,9 @@ public class GetCollectionEditDataResponse { @Schema(description = "birdId가 null일 때 동정 의견을 받을지 여부", example = "true") private Boolean birdIdSuggestionEnabled; + @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true") + private Boolean canSuggestBirdId; + @Schema(description = "이미지 ID", example = "300") private Long imageId; diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetLikedCollectionsResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetLikedCollectionsResponse.java index 6dfbb653..9bdf2eff 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetLikedCollectionsResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetLikedCollectionsResponse.java @@ -12,6 +12,9 @@ public record GetLikedCollectionsResponse( @Schema(name = "GetLikedCollectionsResponse.Item") public record Item( @Schema(description = "컬렉션 ID", example = "1") - Long collectionId + Long collectionId, + + @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true") + Boolean canSuggestBirdId ) {} } diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetNearbyCollectionsResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetNearbyCollectionsResponse.java index 347f17b8..37d01e7c 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetNearbyCollectionsResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetNearbyCollectionsResponse.java @@ -53,6 +53,9 @@ public static class Item { @Schema(description = "내가 좋아요 눌렀는지 여부", example = "true") private Boolean isLiked; + @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true") + private Boolean canSuggestBirdId; + @Schema(description = "컬렉션 소유자 정보") private UserInfo user; } diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetPendingCollectionsResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetPendingCollectionsResponse.java index 08bee4e3..4932080c 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetPendingCollectionsResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetPendingCollectionsResponse.java @@ -32,6 +32,9 @@ public record Item( String thumbnailProfileImageUrl, @Schema(description = "동정 의견 요청 시각", example = "2025-07-20T00:23:58.164815", requiredMode = Schema.RequiredMode.REQUIRED) - LocalDateTime birdIdSuggestionRequestedAt + LocalDateTime birdIdSuggestionRequestedAt, + + @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true", requiredMode = Schema.RequiredMode.REQUIRED) + Boolean canSuggestBirdId ) {} } diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/MyCollectionsResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/MyCollectionsResponse.java index 3d4d98ad..4101bdec 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/MyCollectionsResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/MyCollectionsResponse.java @@ -35,6 +35,9 @@ public record Item( LocalDateTime createdAt, @Schema(description = "새 발견 일시", example = "2025-01-15") - LocalDate discoveredDate + LocalDate discoveredDate, + + @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true") + Boolean canSuggestBirdId ) { } } \ No newline at end of file diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java index 16daacb3..1dadd00e 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java @@ -37,5 +37,8 @@ public record UpdateCollectionResponse( AccessLevelType accessLevel, @Schema(description = "birdId가 null일 때 동정 의견을 받을지 여부", example = "true") - Boolean birdIdSuggestionEnabled + Boolean birdIdSuggestionEnabled, + + @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true") + Boolean canSuggestBirdId ) {} diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryService.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryService.java index fbb95765..ef4d1ebc 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryService.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryService.java @@ -70,7 +70,8 @@ public GetPendingCollectionsResponse getPendingCollections() { thumbnailProfileImageUrls.get(c.getUser().getId()), startedAt != null ? OffsetDateTimeLocalizer.toSeoulLocalDateTime(startedAt) - : null + : null, + c.canReceiveBirdIdSuggestions() ); }) .toList(); diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionLikeQueryService.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionLikeQueryService.java index 0529d686..019f6635 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionLikeQueryService.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionLikeQueryService.java @@ -44,7 +44,7 @@ public LikeStatusResponse getLikeStatusResponse(Long userId, Long collectionId) } /** - * 사용자가 좋아요한 컬렉션 ID 목록 조회 + * 사용자가 좋아요한 컬렉션 목록 조회 */ public GetLikedCollectionsResponse getLikedCollectionIdsResponse(Long userId) { userRepository.findById(userId) diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryService.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryService.java index caee9867..57f320d6 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryService.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryService.java @@ -121,7 +121,8 @@ public MyCollectionsResponse getMyCollections(Long userId) { likeCount, commentCount, OffsetDateTimeLocalizer.toSeoulLocalDateTime(c.getCreatedAt()), - c.getDiscoveredDate() + c.getDiscoveredDate(), + c.canReceiveBirdIdSuggestions() ); }) .toList(); diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionLikeWebMapper.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionLikeWebMapper.java index 393b597f..e25e4199 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionLikeWebMapper.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionLikeWebMapper.java @@ -16,7 +16,7 @@ ) public interface CollectionLikeWebMapper { - // 좋아요한 컬렉션 ID 목록 조회 + // 좋아요한 컬렉션 목록 조회 default GetLikedCollectionsResponse toGetLikedCollectionsResponse(List collections) { if (collections == null || collections.isEmpty()) { return new GetLikedCollectionsResponse(List.of()); @@ -29,6 +29,7 @@ default GetLikedCollectionsResponse toGetLikedCollectionsResponse(List toLikedCollectionItems(List collections); @Mapping(target = "collectionId", source = "id") + @Mapping(target = "canSuggestBirdId", expression = "java(collection.canReceiveBirdIdSuggestions())") GetLikedCollectionsResponse.Item toLikedCollectionItem(UserBirdCollection collection); // 컬렉션을 좋아요한 사용자 목록 조회 diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java index 490ce138..7ddcca66 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java @@ -38,6 +38,7 @@ public interface CollectionWebMapper { GetCollectionEditDataCommand toGetCollectionDataCommand(Long userId, Long collectionId); @Mapping(target = "birdId", source = "bird.id") + @Mapping(target = "canSuggestBirdId", expression = "java(collection.canReceiveBirdIdSuggestions())") GetCollectionEditDataResponse toGetCollectionEditDataResponse(UserBirdCollection collection); @Mapping(target = "userId", source = "userId") @@ -45,6 +46,7 @@ public interface CollectionWebMapper { @Mapping(target = "birdId", source = "collection.bird.id") @Mapping(target = "collectionId", source = "collection.id") + @Mapping(target = "canSuggestBirdId", expression = "java(collection.canReceiveBirdIdSuggestions())") UpdateCollectionResponse toUpdateCollectionResponse(UserBirdCollection collection, String imageUrl); @Mapping(target = "bird.birdId", source = "collection", qualifiedByName = "getBirdId") @@ -74,6 +76,7 @@ public interface CollectionWebMapper { @Mapping(target = "likeCount", source = "likeCount") @Mapping(target = "commentCount", source = "commentCount") @Mapping(target = "isLiked", source = "isLiked") + @Mapping(target = "canSuggestBirdId", expression = "java(collection.canReceiveBirdIdSuggestions())") @Mapping(target = "user.userId", source = "collection.user.id") @Mapping(target = "user.nickname", source = "collection.user.nickname") @Mapping(target = "user.profileImageUrl", source = "userProfileImageUrl") diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/profile/api/dto/response/UserProfileResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/profile/api/dto/response/UserProfileResponse.java index 146931d9..61cb4036 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/profile/api/dto/response/UserProfileResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/profile/api/dto/response/UserProfileResponse.java @@ -54,6 +54,9 @@ public record CollectionItem( LocalDate discoveredDate, @Schema(description = "컬렉션을 업로드한 날짜", example = "2025-05-17", requiredMode = Schema.RequiredMode.REQUIRED) - LocalDate uploadedDate + LocalDate uploadedDate, + + @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true", requiredMode = Schema.RequiredMode.REQUIRED) + Boolean canSuggestBirdId ) {} } diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/profile/mapper/UserProfileMapper.java b/src/main/java/org/devkor/apu/saerok_server/domain/profile/mapper/UserProfileMapper.java index 2f88907b..c4124822 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/profile/mapper/UserProfileMapper.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/profile/mapper/UserProfileMapper.java @@ -55,7 +55,8 @@ default List toCollectionItems( thumbnailUrlMap.get(c.getId()), c.getNote(), c.getDiscoveredDate(), - OffsetDateTimeLocalizer.toSeoulLocalDate(c.getCreatedAt()) + OffsetDateTimeLocalizer.toSeoulLocalDate(c.getCreatedAt()), + c.canReceiveBirdIdSuggestions() )) .collect(Collectors.toList()); } diff --git a/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryServiceTest.java b/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryServiceTest.java index 406f1222..bbb81606 100644 --- a/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryServiceTest.java +++ b/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/BirdIdSuggestionQueryServiceTest.java @@ -3,6 +3,7 @@ import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetBirdIdSuggestionsResponse; import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetPendingCollectionsResponse; import org.devkor.apu.saerok_server.domain.collection.application.helper.CollectionImageUrlService; +import org.devkor.apu.saerok_server.domain.collection.core.entity.AccessLevelType; import org.devkor.apu.saerok_server.domain.collection.core.entity.UserBirdCollection; import org.devkor.apu.saerok_server.domain.collection.core.repository.BirdIdSuggestionRepository; import org.devkor.apu.saerok_server.domain.collection.core.repository.CollectionRepository; @@ -69,6 +70,7 @@ private static UserBirdCollection coll(long id, User owner, String note) { setField(c, "id", id); setField(c, "user", owner); setField(c, "note", note); + c.setAccessLevel(AccessLevelType.PUBLIC); // birdIdSuggestionRequestedAt 필드는 제거되었으므로 더 이상 세팅하지 않음 return c; } @@ -123,12 +125,14 @@ void success() { assertThat(first.imageUrl()).isEqualTo("http://cdn/img/thumb/key1.jpg"); assertThat(first.profileImageUrl()).isEqualTo("http://cdn/profile/1/profile.jpg"); assertThat(first.thumbnailProfileImageUrl()).isEqualTo("http://cdn/profile/1/thumbnail.webp"); + assertThat(first.canSuggestBirdId()).isTrue(); GetPendingCollectionsResponse.Item second = res.items().get(1); assertThat(second.collectionId()).isEqualTo(2L); assertThat(second.imageUrl()).isNull(); assertThat(second.profileImageUrl()).isEqualTo("http://cdn/profile/default/default-1.png"); assertThat(second.thumbnailProfileImageUrl()).isEqualTo("http://cdn/profile/default/thumbnail-1.webp"); + assertThat(second.canSuggestBirdId()).isTrue(); // 히스토리 조회가 호출됐는지까지 확인 verify(birdIdRequestHistoryRepository).findOpenStartedAtMapByCollectionIds(List.of(1L, 2L)); diff --git a/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryServiceTest.java b/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryServiceTest.java index 7e4aaec2..03f6cc30 100644 --- a/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryServiceTest.java +++ b/src/test/java/org/devkor/apu/saerok_server/domain/collection/application/CollectionQueryServiceTest.java @@ -1,10 +1,12 @@ package org.devkor.apu.saerok_server.domain.collection.application; import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetCollectionDetailResponse; +import org.devkor.apu.saerok_server.domain.collection.api.dto.response.MyCollectionsResponse; import org.devkor.apu.saerok_server.domain.collection.application.helper.CollectionImageUrlService; import org.devkor.apu.saerok_server.domain.collection.core.entity.AccessLevelType; import org.devkor.apu.saerok_server.domain.collection.core.entity.UserBirdCollection; import org.devkor.apu.saerok_server.domain.collection.core.repository.*; +import org.devkor.apu.saerok_server.domain.collection.core.util.PointFactory; import org.devkor.apu.saerok_server.domain.collection.mapper.CollectionWebMapper; import org.devkor.apu.saerok_server.domain.user.core.entity.User; import org.devkor.apu.saerok_server.domain.user.core.repository.UserRepository; @@ -22,9 +24,12 @@ import org.mockito.junit.jupiter.MockitoExtension; import java.lang.reflect.Field; +import java.time.LocalDate; +import java.time.OffsetDateTime; import java.util.*; import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.verifyNoInteractions; @@ -212,4 +217,44 @@ void getCollectionDetail_userNotFound() { assertThrows(NotFoundException.class, () -> collectionQueryService.getCollectionDetailResponse(badUserId, collectionId)); } + + @Test + @DisplayName("내 컬렉션 목록에 동정 의견 가능 여부를 포함한다") + void getMyCollections_includesCanSuggestBirdId() throws IllegalAccessException { + Long userId = 1L; + User owner = new User(); + userIdField.set(owner, userId); + + UserBirdCollection enabled = UserBirdCollection.builder() + .user(owner) + .discoveredDate(LocalDate.of(2026, 7, 22)) + .location(PointFactory.create(37.5, 127.0)) + .accessLevel(AccessLevelType.PUBLIC) + .birdIdSuggestionEnabled(true) + .build(); + collectionIdField.set(enabled, 1L); + org.springframework.test.util.ReflectionTestUtils.setField(enabled, "createdAt", OffsetDateTime.now()); + + UserBirdCollection disabled = UserBirdCollection.builder() + .user(owner) + .discoveredDate(LocalDate.of(2026, 7, 21)) + .location(PointFactory.create(37.5, 127.0)) + .accessLevel(AccessLevelType.PUBLIC) + .birdIdSuggestionEnabled(false) + .build(); + collectionIdField.set(disabled, 2L); + org.springframework.test.util.ReflectionTestUtils.setField(disabled, "createdAt", OffsetDateTime.now()); + + List collections = List.of(enabled, disabled); + given(userRepository.findById(userId)).willReturn(Optional.of(owner)); + given(collectionRepository.findByUserId(userId)).willReturn(collections); + given(collectionImageUrlService.getPrimaryImageUrlsFor(collections)).willReturn(Map.of()); + given(collectionImageUrlService.getPrimaryImageThumbnailUrlsFor(collections)).willReturn(Map.of()); + + MyCollectionsResponse response = collectionQueryService.getMyCollections(userId); + + assertThat(response.items()) + .extracting(MyCollectionsResponse.Item::canSuggestBirdId) + .containsExactly(true, false); + } } diff --git a/src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java b/src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java new file mode 100644 index 00000000..401d9b3b --- /dev/null +++ b/src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java @@ -0,0 +1,86 @@ +package org.devkor.apu.saerok_server.domain.collection.mapper; + +import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetCollectionDetailResponse; +import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetCollectionEditDataResponse; +import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetLikedCollectionsResponse; +import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetNearbyCollectionsResponse; +import org.devkor.apu.saerok_server.domain.collection.api.dto.response.UpdateCollectionResponse; +import org.devkor.apu.saerok_server.domain.collection.application.helper.CollectionImageUrlService; +import org.devkor.apu.saerok_server.domain.collection.core.entity.AccessLevelType; +import org.devkor.apu.saerok_server.domain.collection.core.entity.UserBirdCollection; +import org.devkor.apu.saerok_server.domain.collection.core.util.PointFactory; +import org.devkor.apu.saerok_server.domain.profile.api.dto.response.UserProfileResponse; +import org.devkor.apu.saerok_server.domain.profile.mapper.UserProfileMapper; +import org.devkor.apu.saerok_server.domain.user.core.entity.User; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; +import org.springframework.test.util.ReflectionTestUtils; + +import java.time.LocalDate; +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +class CollectionSuggestionFlagMapperTest { + + private final CollectionWebMapper collectionWebMapper = Mappers.getMapper(CollectionWebMapper.class); + private final CollectionLikeWebMapper collectionLikeWebMapper = Mappers.getMapper(CollectionLikeWebMapper.class); + private final UserProfileMapper userProfileMapper = Mappers.getMapper(UserProfileMapper.class); + + @Test + void collectionResponsesMapCanSuggestBirdIdFromCollectionState() { + UserBirdCollection collection = suggestionEnabledCollection(); + + GetCollectionDetailResponse detail = collectionWebMapper.toGetCollectionDetailResponse( + collection, null, null, null, 0, 0, false, true + ); + GetCollectionEditDataResponse editData = collectionWebMapper.toGetCollectionEditDataResponse(collection); + UpdateCollectionResponse update = collectionWebMapper.toUpdateCollectionResponse(collection, null); + GetNearbyCollectionsResponse.Item nearby = collectionWebMapper.toGetNearbyCollectionsResponseItem( + collection, null, null, null, null, 0, 0, false, true + ); + GetLikedCollectionsResponse.Item liked = collectionLikeWebMapper.toLikedCollectionItem(collection); + + assertThat(detail.getCanSuggestBirdId()).isTrue(); + assertThat(editData.getCanSuggestBirdId()).isTrue(); + assertThat(update.canSuggestBirdId()).isTrue(); + assertThat(nearby.getCanSuggestBirdId()).isTrue(); + assertThat(liked.canSuggestBirdId()).isTrue(); + } + + @Test + void profileCollectionItemsMapCanSuggestBirdIdFromCollectionState() { + UserBirdCollection collection = suggestionEnabledCollection(); + CollectionImageUrlService imageUrlService = mock(CollectionImageUrlService.class); + given(imageUrlService.getPrimaryImageUrlsFor(List.of(collection))).willReturn(Map.of()); + given(imageUrlService.getPrimaryImageThumbnailUrlsFor(List.of(collection))).willReturn(Map.of()); + + List items = + userProfileMapper.toCollectionItems(List.of(collection), imageUrlService); + + assertThat(items).singleElement() + .extracting(UserProfileResponse.CollectionItem::canSuggestBirdId) + .isEqualTo(true); + } + + private UserBirdCollection suggestionEnabledCollection() { + User owner = new User(); + ReflectionTestUtils.setField(owner, "id", 10L); + + UserBirdCollection collection = UserBirdCollection.builder() + .user(owner) + .bird(null) + .discoveredDate(LocalDate.of(2026, 7, 22)) + .location(PointFactory.create(37.5, 127.0)) + .accessLevel(AccessLevelType.PUBLIC) + .birdIdSuggestionEnabled(true) + .build(); + ReflectionTestUtils.setField(collection, "id", 1L); + ReflectionTestUtils.setField(collection, "createdAt", OffsetDateTime.now()); + return collection; + } +} From 6025f2c0b45dd3621ebab55a51a7e8da6ad312a6 Mon Sep 17 00:00:00 2001 From: pizzazoa Date: Wed, 22 Jul 2026 23:59:38 +0900 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=AF=B8=20birdIdSugg?= =?UTF-8?q?estionEnabled=EB=A5=BC=20=EB=B0=9B=EB=8A=94=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=EC=97=90=EC=84=A0=20canSuggestBirdId=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=ED=95=84=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/dto/response/GetCollectionEditDataResponse.java | 5 +---- .../api/dto/response/UpdateCollectionResponse.java | 5 +---- .../domain/collection/mapper/CollectionWebMapper.java | 2 -- .../mapper/CollectionSuggestionFlagMapperTest.java | 6 ------ 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java index 0053fab1..644755d2 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/GetCollectionEditDataResponse.java @@ -37,12 +37,9 @@ public class GetCollectionEditDataResponse { @Schema(description = "birdId가 null일 때 동정 의견을 받을지 여부", example = "true") private Boolean birdIdSuggestionEnabled; - @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true") - private Boolean canSuggestBirdId; - @Schema(description = "이미지 ID", example = "300") private Long imageId; @Schema(description = "이미지 URL", example = "https://cdn.example.com/images/300.jpg") private String imageUrl; -} \ No newline at end of file +} diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java index 1dadd00e..16daacb3 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/api/dto/response/UpdateCollectionResponse.java @@ -37,8 +37,5 @@ public record UpdateCollectionResponse( AccessLevelType accessLevel, @Schema(description = "birdId가 null일 때 동정 의견을 받을지 여부", example = "true") - Boolean birdIdSuggestionEnabled, - - @Schema(description = "동정 의견을 받을 수 있는 상태인지 여부", example = "true") - Boolean canSuggestBirdId + Boolean birdIdSuggestionEnabled ) {} diff --git a/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java b/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java index 7ddcca66..be7b246b 100644 --- a/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java +++ b/src/main/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionWebMapper.java @@ -38,7 +38,6 @@ public interface CollectionWebMapper { GetCollectionEditDataCommand toGetCollectionDataCommand(Long userId, Long collectionId); @Mapping(target = "birdId", source = "bird.id") - @Mapping(target = "canSuggestBirdId", expression = "java(collection.canReceiveBirdIdSuggestions())") GetCollectionEditDataResponse toGetCollectionEditDataResponse(UserBirdCollection collection); @Mapping(target = "userId", source = "userId") @@ -46,7 +45,6 @@ public interface CollectionWebMapper { @Mapping(target = "birdId", source = "collection.bird.id") @Mapping(target = "collectionId", source = "collection.id") - @Mapping(target = "canSuggestBirdId", expression = "java(collection.canReceiveBirdIdSuggestions())") UpdateCollectionResponse toUpdateCollectionResponse(UserBirdCollection collection, String imageUrl); @Mapping(target = "bird.birdId", source = "collection", qualifiedByName = "getBirdId") diff --git a/src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java b/src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java index 401d9b3b..0d9e04d6 100644 --- a/src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java +++ b/src/test/java/org/devkor/apu/saerok_server/domain/collection/mapper/CollectionSuggestionFlagMapperTest.java @@ -1,10 +1,8 @@ package org.devkor.apu.saerok_server.domain.collection.mapper; import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetCollectionDetailResponse; -import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetCollectionEditDataResponse; import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetLikedCollectionsResponse; import org.devkor.apu.saerok_server.domain.collection.api.dto.response.GetNearbyCollectionsResponse; -import org.devkor.apu.saerok_server.domain.collection.api.dto.response.UpdateCollectionResponse; import org.devkor.apu.saerok_server.domain.collection.application.helper.CollectionImageUrlService; import org.devkor.apu.saerok_server.domain.collection.core.entity.AccessLevelType; import org.devkor.apu.saerok_server.domain.collection.core.entity.UserBirdCollection; @@ -38,16 +36,12 @@ void collectionResponsesMapCanSuggestBirdIdFromCollectionState() { GetCollectionDetailResponse detail = collectionWebMapper.toGetCollectionDetailResponse( collection, null, null, null, 0, 0, false, true ); - GetCollectionEditDataResponse editData = collectionWebMapper.toGetCollectionEditDataResponse(collection); - UpdateCollectionResponse update = collectionWebMapper.toUpdateCollectionResponse(collection, null); GetNearbyCollectionsResponse.Item nearby = collectionWebMapper.toGetNearbyCollectionsResponseItem( collection, null, null, null, null, 0, 0, false, true ); GetLikedCollectionsResponse.Item liked = collectionLikeWebMapper.toLikedCollectionItem(collection); assertThat(detail.getCanSuggestBirdId()).isTrue(); - assertThat(editData.getCanSuggestBirdId()).isTrue(); - assertThat(update.canSuggestBirdId()).isTrue(); assertThat(nearby.getCanSuggestBirdId()).isTrue(); assertThat(liked.canSuggestBirdId()).isTrue(); }