From b8290011ee10a80359d83bef82f1ccfe8338687b Mon Sep 17 00:00:00 2001 From: m00nsh Date: Tue, 11 Aug 2026 14:00:38 +0900 Subject: [PATCH] Feat: add extra count to home teaching maps --- .../home/dto/HomeTeachingMapResponse.java | 5 +- .../domain/home/service/HomeService.java | 24 +++++- .../domain/home/service/HomeServiceTest.java | 84 +++++++++++++++++++ 3 files changed, 109 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/teaching/backend/domain/home/dto/HomeTeachingMapResponse.java b/src/main/java/com/teaching/backend/domain/home/dto/HomeTeachingMapResponse.java index 38f2dae..f699995 100644 --- a/src/main/java/com/teaching/backend/domain/home/dto/HomeTeachingMapResponse.java +++ b/src/main/java/com/teaching/backend/domain/home/dto/HomeTeachingMapResponse.java @@ -15,12 +15,14 @@ public record HomeTeachingMapResponse( String type, String status, List sourcePlatforms, + int extraCount, LocalDateTime createdAt ) { public static HomeTeachingMapResponse from( TeachingMap teachingMap, - List sourcePlatforms + List sourcePlatforms, + int extraCount ) { TeachingMapType type = teachingMap.getType(); TeachingMapStatus status = teachingMap.getStatus(); @@ -32,6 +34,7 @@ public static HomeTeachingMapResponse from( type == null ? null : type.name(), status == null ? null : status.name(), sourcePlatforms == null ? List.of() : sourcePlatforms, + extraCount, teachingMap.getCreatedAt() ); } diff --git a/src/main/java/com/teaching/backend/domain/home/service/HomeService.java b/src/main/java/com/teaching/backend/domain/home/service/HomeService.java index 7551edd..2644d61 100644 --- a/src/main/java/com/teaching/backend/domain/home/service/HomeService.java +++ b/src/main/java/com/teaching/backend/domain/home/service/HomeService.java @@ -86,17 +86,31 @@ private List createTeachingMapResponses(Long userId, Li )); return teachingMaps.stream() - .map(teachingMap -> HomeTeachingMapResponse.from( + .map(teachingMap -> toTeachingMapResponse( teachingMap, - toSourcePlatforms(platformTypesByTeachingMapId.getOrDefault(teachingMap.getId(), List.of())) + platformTypesByTeachingMapId.getOrDefault(teachingMap.getId(), List.of()) )) .toList(); } - private List toSourcePlatforms(List platformTypes) { + private HomeTeachingMapResponse toTeachingMapResponse(TeachingMap teachingMap, List platformTypes) { + List displayablePlatformTypes = toDisplayablePlatformTypes(platformTypes); + return HomeTeachingMapResponse.from( + teachingMap, + toSourcePlatforms(displayablePlatformTypes), + extraCount(displayablePlatformTypes) + ); + } + + private List toDisplayablePlatformTypes(List platformTypes) { return platformTypes.stream() .filter(platformType -> platformType != null && platformType.getIconPath() != null) .distinct() + .toList(); + } + + private List toSourcePlatforms(List platformTypes) { + return platformTypes.stream() .limit(SOURCE_PLATFORM_LIMIT) .map(platformType -> new SourcePlatform( platformType.name(), @@ -105,6 +119,10 @@ private List toSourcePlatforms(List platformTypes) .toList(); } + private int extraCount(List platformTypes) { + return Math.max(0, platformTypes.size() - SOURCE_PLATFORM_LIMIT); + } + private String buildIconUrl(String iconPath) { return iconPath; } diff --git a/src/test/java/com/teaching/backend/domain/home/service/HomeServiceTest.java b/src/test/java/com/teaching/backend/domain/home/service/HomeServiceTest.java index 0672857..c1f6d37 100644 --- a/src/test/java/com/teaching/backend/domain/home/service/HomeServiceTest.java +++ b/src/test/java/com/teaching/backend/domain/home/service/HomeServiceTest.java @@ -232,6 +232,7 @@ void getDashboardMapsMaterialAndTeachingMapFields() { assertThat(result.activeTeachingMaps().get(0).type()).isEqualTo("DEEPDIVE"); assertThat(result.activeTeachingMaps().get(0).status()).isEqualTo("IN_PROGRESS"); assertThat(result.activeTeachingMaps().get(0).sourcePlatforms()).hasSize(3); + assertThat(result.activeTeachingMaps().get(0).extraCount()).isEqualTo(1); assertThat(result.activeTeachingMaps().get(0).sourcePlatforms()) .extracting("imageUrl") .containsExactly( @@ -241,6 +242,89 @@ void getDashboardMapsMaterialAndTeachingMapFields() { ); } + @Test + void getDashboardMapsSourcePlatformsAndExtraCountLikeTeachingMapList() { + List teachingMaps = List.of( + teachingMap(201L, USER_ID, "Map 1", TeachingMapType.SHORTCUT, createdAt(1)), + teachingMap(202L, USER_ID, "Map 2", TeachingMapType.DEEPDIVE, createdAt(2)), + teachingMap(203L, USER_ID, "Map 3", TeachingMapType.SHORTCUT, createdAt(3)) + ); + when(materialRepository.findHomeRecentMaterials(eq(USER_ID), eq(AiStatus.COMPLETED), any(Pageable.class))) + .thenReturn(new PageImpl<>(List.of())); + when(teachingMapRepository.findAllByUser_IdAndStatusAndIsDraftFalseAndDeletedAtIsNull( + eq(USER_ID), + eq(TeachingMapStatus.IN_PROGRESS), + any(Pageable.class) + )).thenReturn(new PageImpl<>(teachingMaps)); + when(teachingMapStepRepository.findActivePlatformTypesByTeachingMapIdIn(List.of(201L, 202L, 203L), USER_ID)) + .thenReturn(List.of( + platformProjection(201L, PlatformType.YOUTUBE), + platformProjection(201L, PlatformType.VELOG), + platformProjection(201L, PlatformType.BLOG), + platformProjection(202L, PlatformType.YOUTUBE), + platformProjection(202L, PlatformType.VELOG), + platformProjection(202L, PlatformType.BLOG), + platformProjection(202L, PlatformType.NOTION), + platformProjection(203L, PlatformType.YOUTUBE), + platformProjection(203L, PlatformType.VELOG), + platformProjection(203L, PlatformType.YOUTUBE), + platformProjection(203L, PlatformType.BLOG), + platformProjection(203L, PlatformType.NOTION), + platformProjection(203L, PlatformType.TISTORY) + )); + + HomeDashboardResponse result = homeService.getDashboard(USER_ID); + + assertThat(result.activeTeachingMaps().get(0).sourcePlatforms()).hasSize(3); + assertThat(result.activeTeachingMaps().get(0).extraCount()).isZero(); + assertThat(result.activeTeachingMaps().get(1).sourcePlatforms()).hasSize(3); + assertThat(result.activeTeachingMaps().get(1).extraCount()).isEqualTo(1); + assertThat(result.activeTeachingMaps().get(2).sourcePlatforms()).hasSize(3); + assertThat(result.activeTeachingMaps().get(2).extraCount()).isEqualTo(2); + assertThat(result.activeTeachingMaps().get(2).sourcePlatforms()) + .extracting("type") + .containsExactly("YOUTUBE", "VELOG", "BLOG"); + } + + @Test + void getDashboardDoesNotCountDuplicatePlatformsAsExtra() { + List teachingMaps = List.of( + teachingMap(201L, USER_ID, "Map 1", TeachingMapType.SHORTCUT, createdAt(1)), + teachingMap(202L, USER_ID, "Map 2", TeachingMapType.DEEPDIVE, createdAt(2)) + ); + when(materialRepository.findHomeRecentMaterials(eq(USER_ID), eq(AiStatus.COMPLETED), any(Pageable.class))) + .thenReturn(new PageImpl<>(List.of())); + when(teachingMapRepository.findAllByUser_IdAndStatusAndIsDraftFalseAndDeletedAtIsNull( + eq(USER_ID), + eq(TeachingMapStatus.IN_PROGRESS), + any(Pageable.class) + )).thenReturn(new PageImpl<>(teachingMaps)); + when(teachingMapStepRepository.findActivePlatformTypesByTeachingMapIdIn(List.of(201L, 202L), USER_ID)) + .thenReturn(List.of( + platformProjection(201L, PlatformType.VELOG), + platformProjection(201L, PlatformType.VELOG), + platformProjection(201L, PlatformType.VELOG), + platformProjection(201L, PlatformType.VELOG), + platformProjection(202L, PlatformType.VELOG), + platformProjection(202L, PlatformType.VELOG), + platformProjection(202L, PlatformType.NOTION), + platformProjection(202L, PlatformType.TISTORY) + )); + + HomeDashboardResponse result = homeService.getDashboard(USER_ID); + + assertThat(result.activeTeachingMaps().get(0).sourcePlatforms()).hasSize(1); + assertThat(result.activeTeachingMaps().get(0).sourcePlatforms()) + .extracting("type") + .containsExactly("VELOG"); + assertThat(result.activeTeachingMaps().get(0).extraCount()).isZero(); + assertThat(result.activeTeachingMaps().get(1).sourcePlatforms()).hasSize(3); + assertThat(result.activeTeachingMaps().get(1).sourcePlatforms()) + .extracting("type") + .containsExactly("VELOG", "NOTION", "TISTORY"); + assertThat(result.activeTeachingMaps().get(1).extraCount()).isZero(); + } + @Test void getDashboardDoesNotThrowWhenMaterialAiStatusIsNull() { Material material = material(101L, USER_ID, "Material", PlatformType.WEB, AiStatus.COMPLETED, createdAt(1));