Skip to content

Commit 538c48c

Browse files
authored
Merge pull request ChwitKey#116 from Cherrypickk/feature/27-article-attention-check
feat: 스크랩 기사 조회 api 기능구현 & 기사 상세조회 isScrapped, isLiked 필드 추가
2 parents 362a6f7 + eff21e5 commit 538c48c

File tree

6 files changed

+99
-10
lines changed

6 files changed

+99
-10
lines changed

src/main/java/com/example/cherrypickserver/article/application/ArticleService.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,19 @@
22

33
import com.example.cherrypickserver.article.dto.request.CreateArticleReq;
44
import com.example.cherrypickserver.article.dto.response.DetailArticleRes;
5+
import com.example.cherrypickserver.article.dto.response.ScrapArticleRes;
56
import com.example.cherrypickserver.article.dto.response.SearchArticleRes;
67
import com.example.cherrypickserver.article.dto.response.ShareArticleRes;
78
import org.springframework.data.domain.Page;
89
import org.springframework.data.domain.Pageable;
910

1011
import java.text.ParseException;
12+
import java.util.List;
1113

1214

1315
public interface ArticleService {
1416

15-
DetailArticleRes detailArticle(Long articleIdx);
17+
DetailArticleRes detailArticle(Long memberId, Long articleIdx);
1618

1719
Page<SearchArticleRes> searchArticle(String cond, String sortType, Pageable pageable);
1820

@@ -23,4 +25,6 @@ public interface ArticleService {
2325
Page<SearchArticleRes> searchArticleByKeyword(Long memberId, String keyword, String sortType, Pageable pageable);
2426

2527
Page<SearchArticleRes> searchArticleByIndustry(Long memberId, String industry, String sortType, Pageable pageable);
28+
29+
List<ScrapArticleRes> getScrapArticle(Long memberId);
2630
}

src/main/java/com/example/cherrypickserver/article/application/ArticleServiceImpl.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
import com.example.cherrypickserver.article.domain.*;
44
import com.example.cherrypickserver.article.dto.assembler.ArticleAssembler;
5-
import com.example.cherrypickserver.article.dto.request.CreateArticleReq;
65
import com.example.cherrypickserver.article.dto.response.DetailArticleRes;
6+
import com.example.cherrypickserver.article.dto.response.ScrapArticleRes;
77
import com.example.cherrypickserver.article.dto.response.SearchArticleRes;
88
import com.example.cherrypickserver.article.exception.AlreadyAttendArticleException;
99
import com.example.cherrypickserver.article.exception.ArticleAttentionNotFoundException;
@@ -18,7 +18,9 @@
1818
import org.springframework.transaction.annotation.Transactional;
1919
import org.springframework.util.StringUtils;
2020

21-
import java.text.ParseException;
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
import java.util.stream.Collectors;
2224

2325

2426
@Service
@@ -32,9 +34,11 @@ public class ArticleServiceImpl implements ArticleService {
3234
private final ArticleAssembler articleAssembler;
3335

3436
@Override
35-
public DetailArticleRes detailArticle(Long articleId) {
37+
public DetailArticleRes detailArticle(Long memberId, Long articleId) {
38+
Member member = memberRepository.findByIdAndIsEnable(memberId, true).orElseThrow(MemberNotFoundException::new);
3639
Article article = articleRepository.findByIdAndIsEnable(articleId, true).orElseThrow(ArticleNotFoundException::new);
37-
return DetailArticleRes.toDto(article, articleAssembler.calUploadedAt(article.getUploadedAt()));
40+
List<ArticleAttention> attentionCheck = articleAttentionRepository.findByArticleAndMemberAndIsEnable(article, member, true);
41+
return DetailArticleRes.toDto(article, attentionCheck, articleAssembler.calUploadedAt(article.getUploadedAt()));
3842
}
3943

4044
@Override
@@ -87,4 +91,16 @@ public Page<SearchArticleRes> searchArticleByIndustry(Long memberId, String indu
8791
Page<Article> articles = articleRepository.findByIndustryOrTitleContainingOrContentsContainingAndIsEnable(Industry.fromValue(industry), industry, industry, true, pageable);
8892
return articles.map(m -> SearchArticleRes.toDto(m, articleAssembler.calUploadedAt(m.getUploadedAt())));
8993
}
94+
95+
@Override
96+
public List<ScrapArticleRes> getScrapArticle(Long memberId) {
97+
Member member = memberRepository.findByIdAndIsEnable(memberId, true).orElseThrow(MemberNotFoundException::new);
98+
List<ArticleAttention> articleAttentions = articleAttentionRepository.findByMemberAndIsEnable(member, true);
99+
100+
List<Article> scrappedArticles = new ArrayList<>();
101+
for (ArticleAttention articleAttention : articleAttentions) {
102+
articleRepository.findByIdAndIsEnable(articleAttention.getArticle().getId(), true).ifPresent(scrappedArticles::add);
103+
}
104+
return scrappedArticles.stream().map(m -> ScrapArticleRes.toDto(m, articleAssembler.calUploadedAt(m.getUploadedAt()))).collect(Collectors.toList());
105+
}
90106
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
package com.example.cherrypickserver.article.domain;
22

3+
import com.example.cherrypickserver.member.domain.Member;
34
import org.springframework.data.jpa.repository.JpaRepository;
45

6+
import java.util.List;
57
import java.util.Optional;
68

79
public interface ArticleAttentionRepository extends JpaRepository<ArticleAttention, Long> {
810
Optional<ArticleAttention> findByArticleIdAndMemberIdAndAttentionTypeAndIsEnable(Long articleId, Long memberId, AttentionType type, Boolean isEnable);
11+
12+
List<ArticleAttention> findByArticleAndMemberAndIsEnable(Article article, Member member, Boolean isEnable);
13+
14+
List<ArticleAttention> findByMemberAndIsEnable(Member member, Boolean isEnable);
915
}

src/main/java/com/example/cherrypickserver/article/dto/response/DetailArticleRes.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.example.cherrypickserver.article.dto.response;
22

33
import com.example.cherrypickserver.article.domain.Article;
4+
import com.example.cherrypickserver.article.domain.ArticleAttention;
5+
import com.example.cherrypickserver.article.domain.AttentionType;
46
import lombok.Builder;
57
import lombok.Data;
68

@@ -21,9 +23,11 @@ public class DetailArticleRes {
2123
private String reporter;
2224
private String industry;
2325
private String url;
26+
private Boolean isLiked;
27+
private Boolean isScrapped;
2428
private List<DetailArticlePhotoRes> articlePhoto;
2529

26-
public static DetailArticleRes toDto(Article article, String uploadedAt) {
30+
public static DetailArticleRes toDto(Article article, List<ArticleAttention> articleAttentions, String uploadedAt) {
2731
return DetailArticleRes.builder()
2832
.articleId(article.getId())
2933
.title(article.getTitle())
@@ -33,7 +37,21 @@ public static DetailArticleRes toDto(Article article, String uploadedAt) {
3337
.reporter(article.getReporter())
3438
.industry(article.getIndustry().getValueGpt())
3539
.url(article.getUrl())
40+
.isLiked(checkAttention(articleAttentions, AttentionType.LIKE))
41+
.isScrapped(checkAttention(articleAttentions, AttentionType.SCRAP))
3642
.articlePhoto(article.getArticlePhoto().stream().map(DetailArticlePhotoRes::toDto).collect(Collectors.toList()))
3743
.build();
3844
}
45+
46+
private static Boolean checkAttention(List<ArticleAttention> articleAttentions, AttentionType like) {
47+
if (articleAttentions.size() != 0) {
48+
for (ArticleAttention articleAttention : articleAttentions) {
49+
if (articleAttention.getAttentionType().equals(like)) {
50+
return true;
51+
}
52+
}
53+
}
54+
return false;
55+
56+
}
3957
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package com.example.cherrypickserver.article.dto.response;
2+
3+
import com.example.cherrypickserver.article.domain.Article;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
7+
@Data
8+
@Builder
9+
public class ScrapArticleRes {
10+
private Long articleId;
11+
private String title;
12+
private String publisher;
13+
private String uploadedAt;
14+
private String thumbnailUrl;
15+
16+
public static ScrapArticleRes toDto(Article article, String uploadedAt) {
17+
return ScrapArticleRes.builder()
18+
.articleId(article.getId())
19+
.title(article.getTitle())
20+
.publisher(article.getPublisher())
21+
.uploadedAt(uploadedAt)
22+
.thumbnailUrl(article.getArticlePhoto().get(0).getArticleImgUrl())
23+
.build();
24+
}
25+
}

src/main/java/com/example/cherrypickserver/article/presentation/ArticleController.java

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package com.example.cherrypickserver.article.presentation;
22

33
import com.example.cherrypickserver.article.application.ArticleService;
4-
import com.example.cherrypickserver.article.dto.request.CreateArticleReq;
54
import com.example.cherrypickserver.article.dto.response.DetailArticleRes;
5+
import com.example.cherrypickserver.article.dto.response.ScrapArticleRes;
66
import com.example.cherrypickserver.article.dto.response.SearchArticleRes;
77
import com.example.cherrypickserver.global.dto.ResponseCustom;
88
import com.example.cherrypickserver.global.resolver.Auth;
@@ -18,7 +18,7 @@
1818
import org.springframework.data.domain.Pageable;
1919
import org.springframework.web.bind.annotation.*;
2020

21-
import java.text.ParseException;
21+
import java.util.List;
2222

2323
@Tag(name = "Article Controller", description = "기사 관련 컨트롤러")
2424
@RequestMapping("/api/articles")
@@ -34,10 +34,15 @@ public class ArticleController {
3434
@ApiResponse(responseCode = "200", description = "기사 상세조회 성공"),
3535
@ApiResponse(responseCode = "404", description = "존재하지 않는 기사"),
3636
})
37+
@Auth
3738
@ResponseBody
3839
@GetMapping("/detail/{articleId}")
39-
public ResponseCustom<DetailArticleRes> detailArticle(@Parameter(description = "기사 id") @PathVariable Long articleId) {
40-
return ResponseCustom.OK(articleService.detailArticle(articleId));
40+
public ResponseCustom<DetailArticleRes> detailArticle(
41+
@Parameter(description = "멤버 id") @IsLogin LoginStatus loginStatus,
42+
@Parameter(description = "기사 id") @PathVariable Long articleId
43+
)
44+
{
45+
return ResponseCustom.OK(articleService.detailArticle(loginStatus.getMemberId(), articleId));
4146
}
4247

4348
// // 기사 검색 (커맨드 + 정렬)
@@ -131,4 +136,19 @@ public ResponseCustom<Void> unAttendArticle(
131136
articleService.unAttendArticle(articleId, loginStatus.getMemberId(), type);
132137
return ResponseCustom.OK();
133138
}
139+
140+
// 스크랩 기사 조회
141+
@Operation(summary = "스크랩 기사 조회", description = "스크랩한 기사를 조회합니다.")
142+
@ApiResponses({
143+
@ApiResponse(responseCode = "200", description = "스크랩 기사 조회 성공"),
144+
})
145+
@Auth
146+
@ResponseBody
147+
@GetMapping("/scrap")
148+
public ResponseCustom<List<ScrapArticleRes>> getScrapArticle(
149+
@Parameter(description = "멤버 id") @IsLogin LoginStatus loginStatus
150+
)
151+
{
152+
return ResponseCustom.OK(articleService.getScrapArticle(loginStatus.getMemberId()));
153+
}
134154
}

0 commit comments

Comments
 (0)