diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/DebateMessageRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/repository/DebateMessageRepository.java similarity index 87% rename from backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/DebateMessageRepository.java rename to backend/core/src/main/java/com/rollthedice/backend/domain/debate/repository/DebateMessageRepository.java index f2456e6f..6dd72f5e 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/DebateMessageRepository.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/repository/DebateMessageRepository.java @@ -1,4 +1,4 @@ -package com.rollthedice.backend.domain.news.repository; +package com.rollthedice.backend.domain.debate.repository; import com.rollthedice.backend.domain.debate.entity.DebateMessage; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateMessageService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateMessageService.java index 032ee552..76d9b583 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateMessageService.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/debate/service/DebateMessageService.java @@ -2,12 +2,11 @@ import com.rollthedice.backend.domain.debate.dto.request.DebateMessageRequest; import com.rollthedice.backend.domain.debate.dto.response.DebateMessageResponse; -import com.rollthedice.backend.domain.debate.dto.response.DebateSummaryResponse; import com.rollthedice.backend.domain.debate.entity.DebateRoom; import com.rollthedice.backend.domain.debate.exception.DebateRoomNotFoundException; import com.rollthedice.backend.domain.debate.mapper.DebateMessageMapper; import com.rollthedice.backend.domain.debate.repository.DebateRoomRepository; -import com.rollthedice.backend.domain.news.repository.DebateMessageRepository; +import com.rollthedice.backend.domain.debate.repository.DebateMessageRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java index edf03f94..b6d19e4f 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsApi.java @@ -2,6 +2,7 @@ import com.rollthedice.backend.domain.news.dto.response.NewsDetailResponse; import com.rollthedice.backend.domain.news.dto.response.NewsResponse; +import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; @@ -46,4 +47,17 @@ NewsDetailResponse getDetailNews( Long newsId ); + @Operation( + summary = "최근 읽은 뉴스 조회", + description = "가장 최근에 읽은 3개의 뉴스를 조회합니다.", + security = {@SecurityRequirement(name = "access_token")}, + tags = {"news"} + ) + @ApiResponse( + responseCode = "200", + description = "요청에 성공하였습니다." + ) + List getReadNews(); + + } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java index e5e12daf..a6e38e45 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/api/NewsController.java @@ -1,8 +1,11 @@ package com.rollthedice.backend.domain.news.api; +import com.rollthedice.backend.domain.crawling.NewsCrawlingService; import com.rollthedice.backend.domain.news.dto.response.NewsDetailResponse; import com.rollthedice.backend.domain.news.dto.response.NewsResponse; +import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; import com.rollthedice.backend.domain.news.service.NewsService; +import com.rollthedice.backend.domain.news.service.ReadNewsService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; @@ -15,6 +18,8 @@ @RequestMapping("news") public class NewsController implements NewsApi { private final NewsService newsService; + private final ReadNewsService readNewsService; + private final NewsCrawlingService crawlingService; @ResponseStatus(HttpStatus.OK) @GetMapping("") @@ -28,4 +33,10 @@ public List getNews(final Pageable pageable) { public NewsDetailResponse getDetailNews(final @PathVariable Long newsId) { return newsService.getDetailNews(newsId); } + + @ResponseStatus(HttpStatus.OK) + @GetMapping("/viewed-history") + public List getReadNews() { + return readNewsService.getReadNews(); + } } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/dto/response/ReadNewsResponse.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/dto/response/ReadNewsResponse.java new file mode 100644 index 00000000..215ceedc --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/dto/response/ReadNewsResponse.java @@ -0,0 +1,15 @@ +package com.rollthedice.backend.domain.news.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ReadNewsResponse { + private Long id; + private String title; +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/ReadNews.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/ReadNews.java index 9c7929c3..03abeb91 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/ReadNews.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/entity/ReadNews.java @@ -4,6 +4,7 @@ import com.rollthedice.backend.global.config.BaseTimeEntity; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; @@ -23,4 +24,10 @@ public class ReadNews extends BaseTimeEntity { @JoinColumn(name = "news_id") private News news; + @Builder + public ReadNews(Member member, News news) { + this.member = member; + this.news = news; + } + } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/mapper/NewsMapper.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/mapper/NewsMapper.java index f2b10ba6..d50c6ce7 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/mapper/NewsMapper.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/mapper/NewsMapper.java @@ -2,6 +2,7 @@ import com.rollthedice.backend.domain.news.dto.response.NewsDetailResponse; import com.rollthedice.backend.domain.news.dto.response.NewsResponse; +import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; import com.rollthedice.backend.domain.news.entity.News; import org.mapstruct.Mapper; import org.mapstruct.MappingConstants.ComponentModel; @@ -11,5 +12,7 @@ public interface NewsMapper { NewsResponse toResponse(final News news, boolean isBookmarked); + ReadNewsResponse toReadNewsResponse(final News news); + NewsDetailResponse toDetailResponse(final News news); } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/NewsRepository.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/NewsRepository.java index b70a295a..e147d4ae 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/NewsRepository.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/NewsRepository.java @@ -10,6 +10,5 @@ @Repository public interface NewsRepository extends JpaRepository { List findAllByContentIsNull(); - List findAllByOrderByViewsDescCreatedAtDesc( - final Pageable pageable); + List findAllByOrderByViewsDescCreatedAtDesc(final Pageable pageable); } 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 new file mode 100644 index 00000000..d821b1cb --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/repository/ReadNewsRepository.java @@ -0,0 +1,14 @@ +package com.rollthedice.backend.domain.news.repository; + +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.domain.news.entity.ReadNews; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface ReadNewsRepository extends JpaRepository { + List getTop3ByMemberOrderByCreatedAtDesc(Member member); + +} diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/NewsService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/NewsService.java index 02fa2878..bb3136c1 100644 --- a/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/NewsService.java +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/NewsService.java @@ -3,7 +3,10 @@ import com.rollthedice.backend.domain.bookmark.service.BookmarkService; import com.rollthedice.backend.domain.member.entity.Member; 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.ReadNews; import com.rollthedice.backend.domain.news.exception.NewsNotFoundException; +import com.rollthedice.backend.domain.news.repository.ReadNewsRepository; import com.rollthedice.backend.global.oauth2.service.AuthService; import com.rollthedice.backend.domain.news.contentqueue.ContentProducer; import com.rollthedice.backend.domain.news.dto.ContentMessageDto; @@ -29,6 +32,7 @@ public class NewsService { private final AuthService authService; private final ContentProducer contentProducer; private final NewsRepository newsRepository; + private final ReadNewsRepository readNewsRepository; private final NewsMapper newsMapper; private final BookmarkService bookmarkService; @@ -69,6 +73,13 @@ public List getNews(final Pageable pageable) { public NewsDetailResponse getDetailNews(Long newsId) { final News news = newsRepository.findById(newsId).orElseThrow(NewsNotFoundException::new); + readNewsRepository.save(ReadNews.builder() + .member(authService.getMember()).news(news).build()); return newsMapper.toDetailResponse(news); } + + public List getNewsByReadNews(final List news) { + return news.stream().map(newsMapper::toReadNewsResponse).collect(Collectors.toList()); + } + } diff --git a/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/ReadNewsService.java b/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/ReadNewsService.java new file mode 100644 index 00000000..c2618ff0 --- /dev/null +++ b/backend/core/src/main/java/com/rollthedice/backend/domain/news/service/ReadNewsService.java @@ -0,0 +1,26 @@ +package com.rollthedice.backend.domain.news.service; + +import com.rollthedice.backend.domain.member.entity.Member; +import com.rollthedice.backend.domain.news.dto.response.ReadNewsResponse; +import com.rollthedice.backend.domain.news.entity.ReadNews; +import com.rollthedice.backend.domain.news.repository.ReadNewsRepository; +import com.rollthedice.backend.global.oauth2.service.AuthService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class ReadNewsService { + private final AuthService authService; + private final ReadNewsRepository readNewsReository; + private final NewsService newsService; + + public List getReadNews() { + Member member = authService.getMember(); + List readNews = readNewsReository.getTop3ByMemberOrderByCreatedAtDesc(member); + return newsService.getNewsByReadNews(readNews.stream().map(r -> r.getNews()).collect(Collectors.toList())); + } +}