From 89061516c03795b440cc0e3331ced7caa8b6fc95 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Tue, 4 Jun 2024 16:08:25 +0900 Subject: [PATCH 01/20] =?UTF-8?q?refactor:=20News=20Category=20directory?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20(service=20->=20entity)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/news/{service => entity}/NewsCategory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename backend/core/src/main/java/com/rollthedice/backend/domain/news/{service => entity}/NewsCategory.java (88%) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/NewsCategory.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/NewsCategory.java similarity index 88% rename from backend/core/src/main/java/com/rollthedice/backend/domain/news/service/NewsCategory.java rename to backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/NewsCategory.java index 6cec2e54..a21bf462 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/NewsCategory.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/NewsCategory.java @@ -1,4 +1,4 @@ -package com.rollthedice.backend.domain.news.service; +package com.rollthedice.backend.domain.news.entity; import lombok.Getter; From 8eba20b9a50c955c2796f457e0cd92560fb05f91 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 09:30:03 +0900 Subject: [PATCH 02/20] =?UTF-8?q?feat:=20QueryDsl=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/core/build.gradle | 13 ++++++++++++- .../backend/global/config/QueryDslConfig.java | 18 ++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java diff --git a/backend/core/build.gradle b/backend/core/build.gradle index 8c0c2e44..8d7ae0a3 100644 --- a/backend/core/build.gradle +++ b/backend/core/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.1.7' id 'io.spring.dependency-management' version '1.1.4' + id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.rollthedice' @@ -21,6 +22,11 @@ repositories { mavenCentral() } + +ext { + queryDslVersion = "5.0.0" +} + dependencies { if (isAppleSilicon()) { runtimeOnly("io.netty:netty-resolver-dns-native-macos:4.1.94.Final:osx-aarch_64") @@ -41,6 +47,11 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' implementation 'org.springframework.boot:spring-boot-starter-data-redis:2.3.1.RELEASE' implementation 'org.springframework.boot:spring-boot-starter-webflux' + implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0' + + implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta" + implementation "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta" annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' @@ -64,4 +75,4 @@ tasks.named('test') { def boolean isAppleSilicon() { return System.getProperty("os.name") == "Mac OS X" && System.getProperty("os.arch") == "aarch64" -} \ No newline at end of file +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java b/backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java new file mode 100644 index 00000000..3b8d8895 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java @@ -0,0 +1,18 @@ +package com.rollthedice.backend.global.config; + + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class QueryDslConfig { + @Configuration + public class QuerydslConfig { + @Bean + public JPAQueryFactory jpaQueryFactory(final EntityManager em) { + return new JPAQueryFactory(em); + } + } +} \ No newline at end of file From 34db6e9b7e7c2510bf9c867ed2768cf8cc4efa19 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 15:52:52 +0900 Subject: [PATCH 03/20] =?UTF-8?q?feat:=20ReadNews=20=EB=82=A0=EC=A7=9C?= =?UTF-8?q?=EB=B3=84=20=EC=9D=BD=EC=9D=80=20=EB=89=B4=EC=8A=A4=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=20=EC=A1=B0=ED=9A=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../news/repository/ReadNewsRepository.java | 3 ++- .../repository/ReadNewsCustomRepository.java | 8 ++++++ .../ReadNewsCustomRepositoryImpl.java | 25 +++++++++++++++++++ .../backend/global/config/QueryDslConfig.java | 18 ------------- 4 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java create mode 100644 backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java delete mode 100644 backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepository.java index d821b1cb..0dec52dc 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepository.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepository.java @@ -2,13 +2,14 @@ import com.rollthedice.backend.domain.member.entity.Member; import com.rollthedice.backend.domain.news.entity.ReadNews; +import com.rollthedice.backend.domain.statistics.repository.ReadNewsCustomRepository; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository -public interface ReadNewsRepository extends JpaRepository { +public interface ReadNewsRepository extends JpaRepository, ReadNewsCustomRepository { List getTop3ByMemberOrderByCreatedAtDesc(Member member); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java new file mode 100644 index 00000000..767ff3da --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java @@ -0,0 +1,8 @@ +package com.rollthedice.backend.domain.statistics.repository; + +import java.time.LocalDate; + +public interface ReadNewsCustomRepository { + Long findReadNewsByDate(LocalDate date); + +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java new file mode 100644 index 00000000..f0691867 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java @@ -0,0 +1,25 @@ +package com.rollthedice.backend.domain.statistics.repository; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import com.rollthedice.backend.domain.news.entity.QReadNews; +import lombok.RequiredArgsConstructor; + +import java.time.LocalDate; + +@RequiredArgsConstructor +public class ReadNewsCustomRepositoryImpl implements ReadNewsCustomRepository { + private final JPAQueryFactory queryFactory; + + @Override + public Long findReadNewsByDate(LocalDate date) { + QReadNews readNews = QReadNews.readNews; + + return queryFactory + .select(readNews.count()) + .from(readNews) + .where(readNews.createdAt.between( + date.atStartOfDay(), + date.plusDays(1).atStartOfDay().minusNanos(1))) + .fetchOne(); + } +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java b/backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java deleted file mode 100644 index 3b8d8895..00000000 --- a/backend/core/src/main/java/com/rollthedice/backend/global/config/QueryDslConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.rollthedice.backend.global.config; - - -import com.querydsl.jpa.impl.JPAQueryFactory; -import jakarta.persistence.EntityManager; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class QueryDslConfig { - @Configuration - public class QuerydslConfig { - @Bean - public JPAQueryFactory jpaQueryFactory(final EntityManager em) { - return new JPAQueryFactory(em); - } - } -} \ No newline at end of file From 6dbdbf8edf405f4946a7d80062c8fa7a03630f5d Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 20:46:38 +0900 Subject: [PATCH 04/20] =?UTF-8?q?chore:=20Querydsl=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/core/build.gradle | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/core/build.gradle b/backend/core/build.gradle index 8d7ae0a3..2497c09c 100644 --- a/backend/core/build.gradle +++ b/backend/core/build.gradle @@ -2,7 +2,6 @@ plugins { id 'java' id 'org.springframework.boot' version '3.1.7' id 'io.spring.dependency-management' version '1.1.4' - id "com.ewerk.gradle.plugins.querydsl" version "1.0.10" } group = 'com.rollthedice' @@ -22,7 +21,6 @@ repositories { mavenCentral() } - ext { queryDslVersion = "5.0.0" } @@ -47,11 +45,12 @@ dependencies { implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0' implementation 'org.springframework.boot:spring-boot-starter-data-redis:2.3.1.RELEASE' implementation 'org.springframework.boot:spring-boot-starter-webflux' - implementation 'org.springframework.boot:spring-boot-starter-data-elasticsearch' - implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0' + implementation 'com.fasterxml.jackson.core:jackson-core:2.17.0' implementation "com.querydsl:querydsl-jpa:${queryDslVersion}:jakarta" - implementation "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta" + annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" annotationProcessor 'org.projectlombok:lombok' annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' @@ -75,4 +74,4 @@ tasks.named('test') { def boolean isAppleSilicon() { return System.getProperty("os.name") == "Mac OS X" && System.getProperty("os.arch") == "aarch64" -} +} \ No newline at end of file From 671c70ba5b850130c1cb2a44a9f034e6ff782924 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 20:47:26 +0900 Subject: [PATCH 05/20] =?UTF-8?q?feat:=20=EB=82=A0=EC=A7=9C=EB=B3=84=20?= =?UTF-8?q?=EB=89=B4=EC=8A=A4=20=EC=A1=B0=ED=9A=8C=EC=88=98=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/statistics/api/StatisticsApi.java | 24 +++++++++++++++++ .../statistics/api/StatisticsController.java | 26 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java create mode 100644 backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java new file mode 100644 index 00000000..2c8e7b30 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java @@ -0,0 +1,24 @@ +package com.rollthedice.backend.domain.statistics.api; + +import com.rollthedice.backend.domain.news.dto.response.NewsResponse; +import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import org.springframework.data.domain.Pageable; + +import java.util.List; + +public interface StatisticsApi { + @Operation( + summary = "최근 일주일 날짜별 뉴스 조회수 조회", + description = "최근 일주일간 날짜별로 뉴스 조회수를 조회합니다.", + security = {@SecurityRequirement(name = "access_token")}, + tags = {"Statistics"} + ) + @ApiResponse( + responseCode = "200", + description = "요청에 성공하였습니다." + ) + List getViewsOfDates(); +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java new file mode 100644 index 00000000..f7f12cd9 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java @@ -0,0 +1,26 @@ +package com.rollthedice.backend.domain.statistics.api; + +import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.statistics.service.StatisticsService; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("statistics") +public class StatisticsController implements StatisticsApi { + private final StatisticsService statisticsService; + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/per-dates") + @Override + public List getViewsOfDates() { + return statisticsService.getViewsOfDates(); + } +} From eac9ae8b8547c1d9d29dd0fe909f0922ac2093fb Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 20:47:36 +0900 Subject: [PATCH 06/20] feat: QuerydslConfig --- .../backend/global/config/QuerydslConfig.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 backend/core/src/main/java/com/rollthedice/backend/global/config/QuerydslConfig.java diff --git a/backend/core/src/main/java/com/rollthedice/backend/global/config/QuerydslConfig.java b/backend/core/src/main/java/com/rollthedice/backend/global/config/QuerydslConfig.java new file mode 100644 index 00000000..91a1e7ce --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/global/config/QuerydslConfig.java @@ -0,0 +1,26 @@ +package com.rollthedice.backend.global.config; + + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class QuerydslConfig { + + private final EntityManager em; + + @Autowired + public QuerydslConfig(EntityManager em) { + this.em = em; + } + + @Bean + public JPAQueryFactory jpaQueryFactory() { + return new JPAQueryFactory(em); + } +} \ No newline at end of file From 15fdc6da28ecb3a95cd52b0ccfc8e5f9f1990e37 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 20:48:16 +0900 Subject: [PATCH 07/20] =?UTF-8?q?feat:=20getViewOfDates=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/DateViewStatisticsResponse.java | 15 +++++++++++ .../statistics/service/StatisticsService.java | 26 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/DateViewStatisticsResponse.java create mode 100644 backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/DateViewStatisticsResponse.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/DateViewStatisticsResponse.java new file mode 100644 index 00000000..6cc5a98b --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/DateViewStatisticsResponse.java @@ -0,0 +1,15 @@ +package com.rollthedice.backend.domain.statistics.dto; + +import lombok.*; + +import java.time.LocalDate; + +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class DateViewStatisticsResponse { + private Long views; + private LocalDate dateTime; +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java new file mode 100644 index 00000000..c1dd5bfa --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java @@ -0,0 +1,26 @@ +package com.rollthedice.backend.domain.statistics.service; + +import com.rollthedice.backend.domain.news.repository.ReadNewsRepository; +import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +@Service +@RequiredArgsConstructor +public class StatisticsService { + private final ReadNewsRepository readNewsRepository; + + public List getViewsOfDates() { + List responses = new ArrayList<>(); + IntStream.range(0, 7) + .forEach(day -> responses.add(DateViewStatisticsResponse.builder() + .views(readNewsRepository.findReadNewsByDate(LocalDate.now().minusDays(day))) + .dateTime(LocalDate.now().minusDays(day)).build())); + return responses; + } +} From 104eb4e3238da65e21062c76d90b4683b00a39da Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 21:10:25 +0900 Subject: [PATCH 08/20] =?UTF-8?q?feat:=20QuerydslConfig=20=EC=BB=A8?= =?UTF-8?q?=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/rollthedice/backend/support/RepositoryTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/core/src/test/java/com/rollthedice/backend/support/RepositoryTest.java b/backend/core/src/test/java/com/rollthedice/backend/support/RepositoryTest.java index 89b01e50..0bfdc47c 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/support/RepositoryTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/support/RepositoryTest.java @@ -1,6 +1,7 @@ package com.rollthedice.backend.support; import com.rollthedice.backend.global.config.JpaAuditingConfig; +import com.rollthedice.backend.global.config.QuerydslConfig; import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.context.annotation.Import; @@ -13,7 +14,7 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @DataJpaTest -@Import({JpaAuditingConfig.class}) +@Import({JpaAuditingConfig.class, QuerydslConfig.class}) @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) public @interface RepositoryTest { } \ No newline at end of file From 152ccd98f28bb7222e1237445bf9410731558dd4 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 21:35:21 +0900 Subject: [PATCH 09/20] =?UTF-8?q?test:=20StatisticsController=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 --- .../statistics/StatisticsControllerTest.java | 48 +++++++++++++++++++ .../domain/statistics/StatisticsFixture.java | 15 ++++++ 2 files changed, 63 insertions(+) create mode 100644 backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsControllerTest.java create mode 100644 backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsControllerTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsControllerTest.java new file mode 100644 index 00000000..6ae1508f --- /dev/null +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsControllerTest.java @@ -0,0 +1,48 @@ +package com.rollthedice.backend.domain.statistics; + +import com.rollthedice.backend.domain.statistics.api.StatisticsController; +import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.statistics.service.StatisticsService; +import com.rollthedice.backend.global.BaseControllerTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.ResultActions; + +import java.util.List; + +import static com.rollthedice.backend.domain.statistics.StatisticsFixture.DATE_VIEW_STATISTICS_RESPONSE; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@DisplayName("StatisticsController의 ") +@WebMvcTest(StatisticsController.class) +class StatisticsControllerTest extends BaseControllerTest { + @MockBean + private StatisticsService statisticsService; + + @Test + @DisplayName("최근 일주일 날짜별 뉴스 조회수 조회 API가 수행되는가") + void getViewsOfDates() throws Exception { + //given + List responses = List.of(DATE_VIEW_STATISTICS_RESPONSE()); + given(statisticsService.getViewsOfDates()).willReturn(responses); + + //when + final ResultActions perform = mockMvc.perform( + get("/statistics/per-dates") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + accessToken) + ).andDo(print()); + + //then + perform.andExpect(status().isOk()) + .andExpect(jsonPath("$..['views']").exists()) + .andExpect(jsonPath("$..['dateTime']").exists()); + } +} diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java new file mode 100644 index 00000000..658b4987 --- /dev/null +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java @@ -0,0 +1,15 @@ +package com.rollthedice.backend.domain.statistics; + +import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; + +import java.time.LocalDate; + +public class StatisticsFixture { + + public static DateViewStatisticsResponse DATE_VIEW_STATISTICS_RESPONSE() { + return DateViewStatisticsResponse.builder() + .views(1L) + .dateTime(LocalDate.of(2024, 6, 15)) + .build(); + } +} From 444841161b5fe4a43d08c225039ee7372e23b6ef Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 21:36:35 +0900 Subject: [PATCH 10/20] =?UTF-8?q?rename:=20test=20package=20=EB=AA=85=20co?= =?UTF-8?q?ntroller=20->=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/news/{controller => api}/NewsControllerTest.java | 0 .../domain/statistics/{ => api}/StatisticsControllerTest.java | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename backend/core/src/test/java/com/rollthedice/backend/domain/news/{controller => api}/NewsControllerTest.java (100%) rename backend/core/src/test/java/com/rollthedice/backend/domain/statistics/{ => api}/StatisticsControllerTest.java (100%) diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/news/controller/NewsControllerTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/news/api/NewsControllerTest.java similarity index 100% rename from backend/core/src/test/java/com/rollthedice/backend/domain/news/controller/NewsControllerTest.java rename to backend/core/src/test/java/com/rollthedice/backend/domain/news/api/NewsControllerTest.java diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsControllerTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java similarity index 100% rename from backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsControllerTest.java rename to backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java From 921bfb0a706269b5bcd45f480931fa42c196f570 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 21:48:33 +0900 Subject: [PATCH 11/20] =?UTF-8?q?style:=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/news/api/NewsControllerTest.java | 3 +-- .../backend/domain/news/service/NewsServiceTest.java | 5 ----- .../domain/statistics/api/StatisticsControllerTest.java | 2 +- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/news/api/NewsControllerTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/news/api/NewsControllerTest.java index 1c790adc..200419be 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/news/api/NewsControllerTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/news/api/NewsControllerTest.java @@ -1,6 +1,5 @@ -package com.rollthedice.backend.domain.news.controller; +package com.rollthedice.backend.domain.news.api; -import com.rollthedice.backend.domain.news.api.NewsController; import com.rollthedice.backend.domain.news.exception.NewsNotFoundException; import com.rollthedice.backend.domain.news.repository.NewsRepository; import com.rollthedice.backend.domain.news.service.NewsService; diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/news/service/NewsServiceTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/news/service/NewsServiceTest.java index df80c961..0ebf8b3b 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/news/service/NewsServiceTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/news/service/NewsServiceTest.java @@ -6,23 +6,19 @@ import com.rollthedice.backend.domain.news.dto.response.NewsDetailResponse; import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; import com.rollthedice.backend.domain.news.entity.News; -import com.rollthedice.backend.domain.news.entity.ReadNews; import com.rollthedice.backend.domain.news.exception.NewsNotFoundException; import com.rollthedice.backend.domain.news.mapper.NewsMapper; import com.rollthedice.backend.domain.news.repository.NewsRepository; import com.rollthedice.backend.domain.news.repository.ReadNewsRepository; import com.rollthedice.backend.global.LoginTest; -import com.rollthedice.backend.support.RepositoryTest; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; @@ -36,7 +32,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.when; @Slf4j @DisplayName("NewsService의") diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java index 6ae1508f..0890893c 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java @@ -1,4 +1,4 @@ -package com.rollthedice.backend.domain.statistics; +package com.rollthedice.backend.domain.statistics.api; import com.rollthedice.backend.domain.statistics.api.StatisticsController; import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; From c3427ec9ad710624a07858df09a66f2a659f1188 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 21:48:51 +0900 Subject: [PATCH 12/20] =?UTF-8?q?test:=20StatisticsServiceTest=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/StatisticsServiceTest.java | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java new file mode 100644 index 00000000..2bd16a58 --- /dev/null +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java @@ -0,0 +1,41 @@ +package com.rollthedice.backend.domain.statistics.service; + +import com.rollthedice.backend.domain.news.repository.ReadNewsRepository; +import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.global.LoginTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; + +import java.time.LocalDate; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.BDDMockito.given; + +@DisplayName("StatisticsService의 ") +@ExtendWith(MockitoExtension.class) +public class StatisticsServiceTest extends LoginTest { + @Autowired + private StatisticsService statisticsService; + @MockBean + private ReadNewsRepository readNewsRepository; + + @Test + @DisplayName("최근 일주일 날짜별 뉴스 조회수가 조회되는가") + void getViewsOfDates() { + //given + int oneWeek = 7; + given(readNewsRepository.findReadNewsByDate(LocalDate.now())).willReturn(anyLong()); + + //when + List result = statisticsService.getViewsOfDates(); + + //then + assertThat(result).hasSize(oneWeek); + } +} From c32c4fe4a475638583f56a3287188927e1c10eab Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 22:48:41 +0900 Subject: [PATCH 13/20] =?UTF-8?q?test:=20ReadNewsRepositoryTest=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ReadNewsRepositoryTest.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java new file mode 100644 index 00000000..a9e7920c --- /dev/null +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java @@ -0,0 +1,50 @@ +package com.rollthedice.backend.domain.news.repository; + +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.domain.member.repository.MemberRepository; +import com.rollthedice.backend.domain.news.entity.News; +import com.rollthedice.backend.domain.news.entity.ReadNews; +import com.rollthedice.backend.support.RepositoryTest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDate; + +import static com.rollthedice.backend.domain.member.MemberFixture.MEMBER; +import static org.assertj.core.api.Assertions.assertThat; + +@DisplayName("ReadNewsRepository의 ") +@RepositoryTest +public class ReadNewsRepositoryTest { + @Autowired + private ReadNewsRepository readNewsRepository; + @Autowired + private NewsRepository newsRepository; + @Autowired + private MemberRepository memberRepository; + + private Member member; + + @BeforeEach + void setUp() { + member = memberRepository.save(MEMBER()); + } + + @Test + @DisplayName("하루동안 조회한 뉴스 개수를 반환할 수 있는가") + void findReadNewsByDate() { + //given + int expect = 5; + for (int i = 0; i < expect; i++) { + readNewsRepository.save(ReadNews.builder().member(member).news(newsRepository.save(News.builder().id((long) i).build())).build()); + } + + //when + Long result = readNewsRepository.findReadNewsByDate(LocalDate.now()); + + //then + assertThat(result).isEqualTo(expect); + } +} From dbdc4d9719ce48c09abc0c7700e2b7942af0ba35 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 23:50:21 +0900 Subject: [PATCH 14/20] =?UTF-8?q?feat:=20statistics.dto=EC=97=90=20respons?= =?UTF-8?q?e=20=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/{ => response}/DateViewStatisticsResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/{ => response}/DateViewStatisticsResponse.java (76%) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/DateViewStatisticsResponse.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/response/DateViewStatisticsResponse.java similarity index 76% rename from backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/DateViewStatisticsResponse.java rename to backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/response/DateViewStatisticsResponse.java index 6cc5a98b..449bbd91 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/DateViewStatisticsResponse.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/response/DateViewStatisticsResponse.java @@ -1,4 +1,4 @@ -package com.rollthedice.backend.domain.statistics.dto; +package com.rollthedice.backend.domain.statistics.dto.response; import lombok.*; From b199b0fa51bbc74cbc4f30eaef7b00f43d1bcc92 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 23:51:19 +0900 Subject: [PATCH 15/20] =?UTF-8?q?feat:=20getCategoryStatistics=20API=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/statistics/api/StatisticsApi.java | 17 ++++++++++++++--- .../statistics/api/StatisticsController.java | 10 +++++++++- .../response/CategoryStatisticsResponse.java | 13 +++++++++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/response/CategoryStatisticsResponse.java diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java index 2c8e7b30..3f8b53d7 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsApi.java @@ -1,11 +1,10 @@ package com.rollthedice.backend.domain.statistics.api; -import com.rollthedice.backend.domain.news.dto.response.NewsResponse; -import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import org.springframework.data.domain.Pageable; import java.util.List; @@ -21,4 +20,16 @@ public interface StatisticsApi { description = "요청에 성공하였습니다." ) List getViewsOfDates(); + + @Operation( + summary = "카테고리별 조회수 조회", + description = "카테고리별 조회수를 조회합니다.", + security = {@SecurityRequirement(name = "access_token")}, + tags = {"Statistics"} + ) + @ApiResponse( + responseCode = "200", + description = "요청에 성공하였습니다." + ) + List getCategoryStatistics(); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java index f7f12cd9..8dc19f3d 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/api/StatisticsController.java @@ -1,6 +1,7 @@ package com.rollthedice.backend.domain.statistics.api; -import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; import com.rollthedice.backend.domain.statistics.service.StatisticsService; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -23,4 +24,11 @@ public class StatisticsController implements StatisticsApi { public List getViewsOfDates() { return statisticsService.getViewsOfDates(); } + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/categories") + @Override + public List getCategoryStatistics() { + return statisticsService.getCategoryStatistics(); + } } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/response/CategoryStatisticsResponse.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/response/CategoryStatisticsResponse.java new file mode 100644 index 00000000..dd2031bf --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/dto/response/CategoryStatisticsResponse.java @@ -0,0 +1,13 @@ +package com.rollthedice.backend.domain.statistics.dto.response; + +import lombok.*; + +@Getter +@Setter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CategoryStatisticsResponse { + private Long views; + private String category; +} From a53117c27d673bfc6a9c8a2ec64ae6387f41ebef Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 23:51:54 +0900 Subject: [PATCH 16/20] =?UTF-8?q?feat:=20getCountOfReadNewsByCategory=20qu?= =?UTF-8?q?erydsl=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ReadNewsCustomRepository.java | 5 ++++- .../ReadNewsCustomRepositoryImpl.java | 20 +++++++++++++++---- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java index 767ff3da..a6758a67 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java @@ -1,8 +1,11 @@ package com.rollthedice.backend.domain.statistics.repository; +import com.rollthedice.backend.domain.member.entity.Member; + import java.time.LocalDate; public interface ReadNewsCustomRepository { - Long findReadNewsByDate(LocalDate date); + Long getCountOfReadNewsByDate(LocalDate date); + Long getCountOfReadNewsByCategory(Member member, String category); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java index f0691867..a629c52b 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java @@ -1,19 +1,20 @@ package com.rollthedice.backend.domain.statistics.repository; import com.querydsl.jpa.impl.JPAQueryFactory; -import com.rollthedice.backend.domain.news.entity.QReadNews; +import com.rollthedice.backend.domain.member.entity.Member; import lombok.RequiredArgsConstructor; import java.time.LocalDate; +import static com.rollthedice.backend.domain.news.entity.QNews.news; +import static com.rollthedice.backend.domain.news.entity.QReadNews.readNews; + @RequiredArgsConstructor public class ReadNewsCustomRepositoryImpl implements ReadNewsCustomRepository { private final JPAQueryFactory queryFactory; @Override - public Long findReadNewsByDate(LocalDate date) { - QReadNews readNews = QReadNews.readNews; - + public Long getCountOfReadNewsByDate(LocalDate date) { return queryFactory .select(readNews.count()) .from(readNews) @@ -22,4 +23,15 @@ public Long findReadNewsByDate(LocalDate date) { date.plusDays(1).atStartOfDay().minusNanos(1))) .fetchOne(); } + + @Override + public Long getCountOfReadNewsByCategory(Member member, String category) { + return queryFactory + .select(readNews.count()) + .from(readNews) + .join(readNews.news, news) + .where(readNews.member.eq(member) + .and(news.category.eq(category)) + ).fetchOne(); + } } From ca64137ce4bb6abe995c3246939e5be2b3d5456a Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 23:52:14 +0900 Subject: [PATCH 17/20] =?UTF-8?q?feat:=20getCategoryStatistics=20service?= =?UTF-8?q?=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/service/StatisticsService.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java index c1dd5bfa..2ef96cd5 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java @@ -1,12 +1,17 @@ package com.rollthedice.backend.domain.statistics.service; +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.domain.news.entity.NewsCategory; import com.rollthedice.backend.domain.news.repository.ReadNewsRepository; -import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; +import com.rollthedice.backend.global.oauth2.service.AuthService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.time.LocalDate; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; @@ -14,13 +19,27 @@ @RequiredArgsConstructor public class StatisticsService { private final ReadNewsRepository readNewsRepository; + private final AuthService authService; public List getViewsOfDates() { List responses = new ArrayList<>(); IntStream.range(0, 7) .forEach(day -> responses.add(DateViewStatisticsResponse.builder() - .views(readNewsRepository.findReadNewsByDate(LocalDate.now().minusDays(day))) - .dateTime(LocalDate.now().minusDays(day)).build())); + .views(readNewsRepository.getCountOfReadNewsByDate(LocalDate.now().minusDays(day))) + .dateTime(LocalDate.now().minusDays(day)).build())); + return responses; + } + + public List getCategoryStatistics() { + Member member = authService.getMember(); + List responses = new ArrayList<>(); + for (NewsCategory category : NewsCategory.values()) { + long views = readNewsRepository.getCountOfReadNewsByCategory(member, category.getName()); + CategoryStatisticsResponse response = CategoryStatisticsResponse.builder() + .category(category.getName()) + .views(views).build(); + responses.add(response); + } return responses; } } From f8b8136bbe838c62d6923eba4ebc4215f784e9d9 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Mon, 17 Jun 2024 23:53:03 +0900 Subject: [PATCH 18/20] =?UTF-8?q?test:=20=EC=B9=B4=ED=85=8C=EA=B3=A0?= =?UTF-8?q?=EB=A6=AC=EB=B3=84=20=EC=A1=B0=ED=9A=8C=ED=95=9C=20=EB=89=B4?= =?UTF-8?q?=EC=8A=A4=20=EA=B0=9C=EC=88=98=20=EA=B4=80=EB=A0=A8=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/ReadNewsRepositoryTest.java | 24 +++++++++++++++-- .../domain/statistics/StatisticsFixture.java | 11 +++++++- .../api/StatisticsControllerTest.java | 26 +++++++++++++++++-- .../service/StatisticsServiceTest.java | 22 ++++++++++++++-- 4 files changed, 76 insertions(+), 7 deletions(-) diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java index a9e7920c..1c618550 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java @@ -3,6 +3,7 @@ import com.rollthedice.backend.domain.member.entity.Member; import com.rollthedice.backend.domain.member.repository.MemberRepository; import com.rollthedice.backend.domain.news.entity.News; +import com.rollthedice.backend.domain.news.entity.NewsCategory; import com.rollthedice.backend.domain.news.entity.ReadNews; import com.rollthedice.backend.support.RepositoryTest; import org.junit.jupiter.api.BeforeEach; @@ -34,7 +35,7 @@ void setUp() { @Test @DisplayName("하루동안 조회한 뉴스 개수를 반환할 수 있는가") - void findReadNewsByDate() { + void getCountOfReadNewsByDate() { //given int expect = 5; for (int i = 0; i < expect; i++) { @@ -42,7 +43,26 @@ void findReadNewsByDate() { } //when - Long result = readNewsRepository.findReadNewsByDate(LocalDate.now()); + Long result = readNewsRepository.getCountOfReadNewsByDate(LocalDate.now()); + + //then + assertThat(result).isEqualTo(expect); + } + + @Test + @DisplayName("회원이 카테고리별로 조회한 뉴스 개수를 반환할 수 있는가") + void getCountOfReadNewsByCategory() { + //given + int expect = 5; + String category = NewsCategory.SCIENCE.getName(); + for (int i = 0; i < expect; i++) { + readNewsRepository.save(ReadNews.builder().member(member) + .news(newsRepository.save( + News.builder().id((long) i).category(category).build())).build()); + } + + //when + Long result = readNewsRepository.getCountOfReadNewsByCategory(member, category); //then assertThat(result).isEqualTo(expect); diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java index 658b4987..8c8ed161 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/StatisticsFixture.java @@ -1,6 +1,8 @@ package com.rollthedice.backend.domain.statistics; -import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.news.entity.NewsCategory; +import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; import java.time.LocalDate; @@ -12,4 +14,11 @@ public static DateViewStatisticsResponse DATE_VIEW_STATISTICS_RESPONSE() { .dateTime(LocalDate.of(2024, 6, 15)) .build(); } + + public static CategoryStatisticsResponse CATEGORY_STATISTICS_RESPONSE() { + return CategoryStatisticsResponse.builder() + .views(2L) + .category(NewsCategory.SCIENCE.getName()) + .build(); + } } diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java index 0890893c..8580eec2 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/api/StatisticsControllerTest.java @@ -1,7 +1,7 @@ package com.rollthedice.backend.domain.statistics.api; -import com.rollthedice.backend.domain.statistics.api.StatisticsController; -import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; import com.rollthedice.backend.domain.statistics.service.StatisticsService; import com.rollthedice.backend.global.BaseControllerTest; import org.junit.jupiter.api.DisplayName; @@ -13,6 +13,7 @@ import java.util.List; +import static com.rollthedice.backend.domain.statistics.StatisticsFixture.CATEGORY_STATISTICS_RESPONSE; import static com.rollthedice.backend.domain.statistics.StatisticsFixture.DATE_VIEW_STATISTICS_RESPONSE; import static org.mockito.BDDMockito.given; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; @@ -45,4 +46,25 @@ void getViewsOfDates() throws Exception { .andExpect(jsonPath("$..['views']").exists()) .andExpect(jsonPath("$..['dateTime']").exists()); } + + @Test + @DisplayName("카테고리별 조회수 조회 API가 수행되는 ") + void getCategoryStatistics() throws Exception { + //given + List responses = List.of(CATEGORY_STATISTICS_RESPONSE()); + given(statisticsService.getCategoryStatistics()).willReturn(responses); + + //when + final ResultActions perform = mockMvc.perform( + get("/statistics/categories") + .contentType(MediaType.APPLICATION_JSON) + .header("Authorization", "Bearer " + accessToken) + ).andDo(print()); + + //perform + perform.andExpect(status().isOk()) + .andExpect(jsonPath("$..['views']").exists()) + .andExpect(jsonPath("$..['category']").exists()); + + } } diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java index 2bd16a58..fca456e0 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java @@ -1,7 +1,10 @@ package com.rollthedice.backend.domain.statistics.service; +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.domain.news.entity.NewsCategory; import com.rollthedice.backend.domain.news.repository.ReadNewsRepository; -import com.rollthedice.backend.domain.statistics.dto.DateViewStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.CategoryStatisticsResponse; +import com.rollthedice.backend.domain.statistics.dto.response.DateViewStatisticsResponse; import com.rollthedice.backend.global.LoginTest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -30,7 +33,7 @@ public class StatisticsServiceTest extends LoginTest { void getViewsOfDates() { //given int oneWeek = 7; - given(readNewsRepository.findReadNewsByDate(LocalDate.now())).willReturn(anyLong()); + given(readNewsRepository.getCountOfReadNewsByDate(LocalDate.now())).willReturn(anyLong()); //when List result = statisticsService.getViewsOfDates(); @@ -38,4 +41,19 @@ void getViewsOfDates() { //then assertThat(result).hasSize(oneWeek); } + + @Test + @DisplayName("카테고리별 조회수가 조회되는가") + void getCategoryStatistics() { + //given + long views = 3; + String category = NewsCategory.SCIENCE.getName(); + given(readNewsRepository.getCountOfReadNewsByCategory(loginUser, category)).willReturn(views); + + //when + List result = statisticsService.getCategoryStatistics(); + + //then + assertThat(result).hasSize(NewsCategory.values().length); + } } From e3217d299676a27b27f1512ea1ac0c5281040ef1 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Tue, 18 Jun 2024 00:01:42 +0900 Subject: [PATCH 19/20] =?UTF-8?q?refactor:=20=EB=82=A0=EC=A7=9C=EB=B3=84?= =?UTF-8?q?=20=EC=9D=BD=EC=9D=80=20=EB=89=B4=EC=8A=A4=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=88=98=20=EB=B0=98=ED=99=98=20=EB=A1=9C=EC=A7=81=EC=97=90=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9C=A0=EC=A0=80=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/repository/ReadNewsCustomRepository.java | 2 +- .../repository/ReadNewsCustomRepositoryImpl.java | 9 +++++---- .../domain/statistics/service/StatisticsService.java | 3 ++- .../domain/news/repository/ReadNewsRepositoryTest.java | 2 +- .../domain/statistics/service/StatisticsServiceTest.java | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java index a6758a67..472c552e 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepository.java @@ -5,7 +5,7 @@ import java.time.LocalDate; public interface ReadNewsCustomRepository { - Long getCountOfReadNewsByDate(LocalDate date); + Long getCountOfReadNewsByDate(Member member, LocalDate date); Long getCountOfReadNewsByCategory(Member member, String category); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java index a629c52b..8fe479f3 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/repository/ReadNewsCustomRepositoryImpl.java @@ -14,13 +14,14 @@ public class ReadNewsCustomRepositoryImpl implements ReadNewsCustomRepository { private final JPAQueryFactory queryFactory; @Override - public Long getCountOfReadNewsByDate(LocalDate date) { + public Long getCountOfReadNewsByDate(Member member, LocalDate date) { return queryFactory .select(readNews.count()) .from(readNews) - .where(readNews.createdAt.between( - date.atStartOfDay(), - date.plusDays(1).atStartOfDay().minusNanos(1))) + .where(readNews.member.eq(member) + .and(readNews.createdAt.between( + date.atStartOfDay(), + date.plusDays(1).atStartOfDay().minusNanos(1)))) .fetchOne(); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java index 2ef96cd5..6a9db10f 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/statistics/service/StatisticsService.java @@ -22,10 +22,11 @@ public class StatisticsService { private final AuthService authService; public List getViewsOfDates() { + Member member = authService.getMember(); List responses = new ArrayList<>(); IntStream.range(0, 7) .forEach(day -> responses.add(DateViewStatisticsResponse.builder() - .views(readNewsRepository.getCountOfReadNewsByDate(LocalDate.now().minusDays(day))) + .views(readNewsRepository.getCountOfReadNewsByDate(member, LocalDate.now().minusDays(day))) .dateTime(LocalDate.now().minusDays(day)).build())); return responses; } diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java index 1c618550..5427888c 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepositoryTest.java @@ -43,7 +43,7 @@ void getCountOfReadNewsByDate() { } //when - Long result = readNewsRepository.getCountOfReadNewsByDate(LocalDate.now()); + Long result = readNewsRepository.getCountOfReadNewsByDate(member, LocalDate.now()); //then assertThat(result).isEqualTo(expect); diff --git a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java index fca456e0..fddb53a3 100644 --- a/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java +++ b/backend/core/src/test/java/com/rollthedice/backend/domain/statistics/service/StatisticsServiceTest.java @@ -33,7 +33,7 @@ public class StatisticsServiceTest extends LoginTest { void getViewsOfDates() { //given int oneWeek = 7; - given(readNewsRepository.getCountOfReadNewsByDate(LocalDate.now())).willReturn(anyLong()); + given(readNewsRepository.getCountOfReadNewsByDate(loginUser, LocalDate.now())).willReturn(1L); //when List result = statisticsService.getViewsOfDates(); From cfd4c6b7769c6a9ddef61358e5aa3e279efae3d5 Mon Sep 17 00:00:00 2001 From: yeonjy Date: Tue, 18 Jun 2024 00:10:22 +0900 Subject: [PATCH 20/20] =?UTF-8?q?fix:=20NewsCategory=20directory=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/domain/crawling/NewsCrawlingService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/crawling/NewsCrawlingService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/crawling/NewsCrawlingService.java index 63ba708f..15457ea8 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/crawling/NewsCrawlingService.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/crawling/NewsCrawlingService.java @@ -2,7 +2,7 @@ import com.rollthedice.backend.domain.news.dto.NewsUrlDto; import com.rollthedice.backend.domain.news.entity.News; -import com.rollthedice.backend.domain.news.service.NewsCategory; +import com.rollthedice.backend.domain.news.entity.NewsCategory; import com.rollthedice.backend.domain.news.service.NewsService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -11,7 +11,6 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.springframework.beans.factory.annotation.Value; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -32,7 +31,7 @@ public class NewsCrawlingService { private final NewsService newsService; @Transactional - // @Scheduled(cron = CRON, zone = ZONE) +// @Scheduled(cron = CRON, zone = ZONE) public void scrap() throws IOException { for (NewsCategory category : NewsCategory.values()) { String categoryUrl = MAIN_URL + category.getNum();