diff --git a/src/main/java/com/newsnack/www/newsnackserver/common/code/failure/MemberFailureCode.java b/src/main/java/com/newsnack/www/newsnackserver/common/code/failure/MemberFailureCode.java index 10aafc9..4148804 100644 --- a/src/main/java/com/newsnack/www/newsnackserver/common/code/failure/MemberFailureCode.java +++ b/src/main/java/com/newsnack/www/newsnackserver/common/code/failure/MemberFailureCode.java @@ -10,7 +10,8 @@ public enum MemberFailureCode implements FailureCode { /** * 404 NOT FOUND */ - MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "가입된 멤버가 없습니다"); + MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "가입된 멤버가 없습니다"), + INTEREST_NOT_FOUND(HttpStatus.NOT_FOUND, "회원님의 관심사를 찾을 수 없습니다."); private final HttpStatus httpStatus; private final String message; diff --git a/src/main/java/com/newsnack/www/newsnackserver/common/code/success/MemberSuccessCode.java b/src/main/java/com/newsnack/www/newsnackserver/common/code/success/MemberSuccessCode.java index d07609c..a750b02 100644 --- a/src/main/java/com/newsnack/www/newsnackserver/common/code/success/MemberSuccessCode.java +++ b/src/main/java/com/newsnack/www/newsnackserver/common/code/success/MemberSuccessCode.java @@ -13,7 +13,9 @@ public enum MemberSuccessCode implements SuccessCode{ GET_LOGIN_USER_INFO_SUCCESS(HttpStatus.OK, "로그인 유저 정보 조회 성공"), GET_LIKED_ARTICLES_SUCCESS(HttpStatus.OK, "좋아요한 게시글 조회 성공"), GET_PARTICIPATED_DEBATES_SUCCESS(HttpStatus.OK, "참여한 토론들 조회 성공"), - GET_MY_COMMENTS_SUCCESS(HttpStatus.OK, "나의 댓글 목록 조회 성공"); + GET_MY_COMMENTS_SUCCESS(HttpStatus.OK, "나의 댓글 목록 조회 성공"), + UPDATE_INTEREST_SUCCESS(HttpStatus.OK, "관심사 변경 성공"), + GET_INTERESTED_ARTICLES_SUCCESS(HttpStatus.OK, "관심사 관련 아티글 조회 성공"); private final HttpStatus httpStatus; private final String message; diff --git a/src/main/java/com/newsnack/www/newsnackserver/controller/MemberController.java b/src/main/java/com/newsnack/www/newsnackserver/controller/MemberController.java index 529c47c..0418468 100644 --- a/src/main/java/com/newsnack/www/newsnackserver/controller/MemberController.java +++ b/src/main/java/com/newsnack/www/newsnackserver/controller/MemberController.java @@ -3,15 +3,12 @@ import com.newsnack.www.newsnackserver.annotation.MemberId; import com.newsnack.www.newsnackserver.common.code.success.MemberSuccessCode; import com.newsnack.www.newsnackserver.common.response.NewSnackResponse; -import com.newsnack.www.newsnackserver.dto.response.MemberInfoResponse; -import com.newsnack.www.newsnackserver.dto.response.MemberLikedArticleResponse; -import com.newsnack.www.newsnackserver.dto.response.MemberParticipatedDebateResponse; -import com.newsnack.www.newsnackserver.dto.response.MyPageCommentResponse; +import com.newsnack.www.newsnackserver.dto.request.MemberUpdateInterestRequest; +import com.newsnack.www.newsnackserver.dto.response.*; import com.newsnack.www.newsnackserver.service.MemberService; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -42,4 +39,14 @@ public NewSnackResponse> getMyComments(@MemberId Lon return NewSnackResponse.success(MemberSuccessCode.GET_MY_COMMENTS_SUCCESS, memberService.getMyComments(memberId)); } + @PatchMapping("/me/interest") + public NewSnackResponse updateInterest(@MemberId Long memberId, @Valid @RequestBody MemberUpdateInterestRequest request){ + memberService.updateInterest(memberId, request); + return NewSnackResponse.success(MemberSuccessCode.UPDATE_INTEREST_SUCCESS); + } + + @GetMapping("/me/articles/interested") + public NewSnackResponse> getInterestedArticles(@MemberId Long memberId){ + return NewSnackResponse.success(MemberSuccessCode.GET_INTERESTED_ARTICLES_SUCCESS, memberService.getInterestedArticles(memberId)); + } } diff --git a/src/main/java/com/newsnack/www/newsnackserver/domain/article/repository/ArticleJpaRepository.java b/src/main/java/com/newsnack/www/newsnackserver/domain/article/repository/ArticleJpaRepository.java index a17bcce..c7d9eb7 100644 --- a/src/main/java/com/newsnack/www/newsnackserver/domain/article/repository/ArticleJpaRepository.java +++ b/src/main/java/com/newsnack/www/newsnackserver/domain/article/repository/ArticleJpaRepository.java @@ -9,6 +9,7 @@ import org.springframework.data.jpa.repository.Query; import java.time.LocalDateTime; +import java.util.Collection; import java.util.List; public interface ArticleJpaRepository extends JpaRepository { @@ -30,4 +31,6 @@ public interface ArticleJpaRepository extends JpaRepository { List
findTop5ByCreatedAtAfterOrderByHeartCountDescIdDesc(LocalDateTime oneWeekAgo); + @Query("SELECT a from Article a where a.sectionCategory = :sectionCategory or a.sectionCategory = :sectionCategory1 order by a.id desc") + List
findAllBySectionCategoryOrderByIdDescJPQL(SectionCategory sectionCategory, SectionCategory sectionCategory1); } diff --git a/src/main/java/com/newsnack/www/newsnackserver/domain/member/model/Interest.java b/src/main/java/com/newsnack/www/newsnackserver/domain/member/model/Interest.java new file mode 100644 index 0000000..e795664 --- /dev/null +++ b/src/main/java/com/newsnack/www/newsnackserver/domain/member/model/Interest.java @@ -0,0 +1,12 @@ +package com.newsnack.www.newsnackserver.domain.member.model; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +@Getter +public enum Interest { + MONEY("MONEY"), SOCIETY("SOCIETY"), TREND("TREND"); + + private final String value; +} diff --git a/src/main/java/com/newsnack/www/newsnackserver/domain/member/model/Member.java b/src/main/java/com/newsnack/www/newsnackserver/domain/member/model/Member.java index bd88656..2682586 100644 --- a/src/main/java/com/newsnack/www/newsnackserver/domain/member/model/Member.java +++ b/src/main/java/com/newsnack/www/newsnackserver/domain/member/model/Member.java @@ -39,6 +39,9 @@ public class Member { private LocalDateTime deletedAt; + @Enumerated(EnumType.STRING) + private Interest interest; + @Builder public Member(String serialId, String name, String email, Provider provider, MemberRole role, String refreshToken, MemberStatus memberStatus) { this.serialId = serialId; @@ -53,4 +56,8 @@ public Member(String serialId, String name, String email, Provider provider, Mem public void updateRefreshToken(String refreshToken) { this.refreshToken = refreshToken; } + + public void updateInterest(Interest interest) { + this.interest = interest; + } } diff --git a/src/main/java/com/newsnack/www/newsnackserver/dto/request/MemberUpdateInterestRequest.java b/src/main/java/com/newsnack/www/newsnackserver/dto/request/MemberUpdateInterestRequest.java new file mode 100644 index 0000000..1b9d921 --- /dev/null +++ b/src/main/java/com/newsnack/www/newsnackserver/dto/request/MemberUpdateInterestRequest.java @@ -0,0 +1,19 @@ +package com.newsnack.www.newsnackserver.dto.request; + +import com.newsnack.www.newsnackserver.domain.member.model.Interest; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; + +public record MemberUpdateInterestRequest(@Max(value = 3, message = "3이하의 점수를 입력하세요") @Min(value = 0, message = "0이상의 점수를 입력하세요") int moneyCount, + @Max(value = 3, message = "3이하의 점수를 입력하세요") @Min(value = 0, message = "0이상의 점수를 입력하세요") int societyCount, + @Max(value = 3, message = "3이하의 점수를 입력하세요") @Min(value = 0, message = "0이상의 점수를 입력하세요") int trendCount) { + public Interest getInterestWithMostCount() { + if (moneyCount >= societyCount && moneyCount >= trendCount) { + return Interest.MONEY; + } else if (societyCount >= moneyCount && societyCount >= trendCount) { + return Interest.SOCIETY; + } else { + return Interest.TREND; + } + } +} diff --git a/src/main/java/com/newsnack/www/newsnackserver/dto/response/InterestedArticleResponse.java b/src/main/java/com/newsnack/www/newsnackserver/dto/response/InterestedArticleResponse.java new file mode 100644 index 0000000..af94240 --- /dev/null +++ b/src/main/java/com/newsnack/www/newsnackserver/dto/response/InterestedArticleResponse.java @@ -0,0 +1,9 @@ +package com.newsnack.www.newsnackserver.dto.response; + +import com.newsnack.www.newsnackserver.domain.article.model.Article; + +public record InterestedArticleResponse(Long id, String imageUrl, String title) { + public static InterestedArticleResponse of(Article article) { + return new InterestedArticleResponse(article.getId(), article.getImageUrl(), article.getTitle()); + } +} diff --git a/src/main/java/com/newsnack/www/newsnackserver/service/MemberService.java b/src/main/java/com/newsnack/www/newsnackserver/service/MemberService.java index 6094013..524efba 100644 --- a/src/main/java/com/newsnack/www/newsnackserver/service/MemberService.java +++ b/src/main/java/com/newsnack/www/newsnackserver/service/MemberService.java @@ -3,18 +3,19 @@ import com.newsnack.www.newsnackserver.common.code.failure.MemberFailureCode; import com.newsnack.www.newsnackserver.common.exception.MemberException; import com.newsnack.www.newsnackserver.domain.article.model.Article; +import com.newsnack.www.newsnackserver.domain.article.model.SectionCategory; +import com.newsnack.www.newsnackserver.domain.article.repository.ArticleJpaRepository; import com.newsnack.www.newsnackserver.domain.articleheart.model.ArticleHeart; import com.newsnack.www.newsnackserver.domain.articleheart.repository.ArticleHeartJpaRepository; import com.newsnack.www.newsnackserver.domain.comment.repository.CommentJpaRepository; import com.newsnack.www.newsnackserver.domain.debate.model.Debate; import com.newsnack.www.newsnackserver.domain.debateparticipation.model.DebateParticipation; import com.newsnack.www.newsnackserver.domain.debateparticipation.repository.DebateParticipationJpaRepository; +import com.newsnack.www.newsnackserver.domain.member.model.Interest; import com.newsnack.www.newsnackserver.domain.member.model.Member; import com.newsnack.www.newsnackserver.domain.member.repository.MemberJpaRepository; -import com.newsnack.www.newsnackserver.dto.response.MemberInfoResponse; -import com.newsnack.www.newsnackserver.dto.response.MemberLikedArticleResponse; -import com.newsnack.www.newsnackserver.dto.response.MemberParticipatedDebateResponse; -import com.newsnack.www.newsnackserver.dto.response.MyPageCommentResponse; +import com.newsnack.www.newsnackserver.dto.request.MemberUpdateInterestRequest; +import com.newsnack.www.newsnackserver.dto.response.*; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -29,6 +30,7 @@ public class MemberService { private final ArticleHeartJpaRepository articleHeartJpaRepository; private final DebateParticipationJpaRepository debateParticipationJpaRepository; private final CommentJpaRepository commentJpaRepository; + private final ArticleJpaRepository articleJpaRepository; public MemberInfoResponse getMemberInfo(Long memberId) { @@ -49,4 +51,34 @@ public List getParticipatedDebates(Long member public List getMyComments(Long memberId) { return commentJpaRepository.findAllByMemberIdJPQL(memberId); } + + @Transactional + public void updateInterest(Long memberId, MemberUpdateInterestRequest request) { + Member member = memberJpaRepository.findById(memberId).orElseThrow(() -> new MemberException(MemberFailureCode.MEMBER_NOT_FOUND)); + member.updateInterest(request.getInterestWithMostCount()); + } + + public List getInterestedArticles(Long memberId) { + Member member = memberJpaRepository.findById(memberId).orElseThrow(() -> new MemberException(MemberFailureCode.MEMBER_NOT_FOUND)); + List responses = null; + Interest interest = member.getInterest(); + if (interest == null) { + throw new MemberException(MemberFailureCode.INTEREST_NOT_FOUND); + } + switch (interest) { + case MONEY -> { + responses = articleJpaRepository.findAllBySectionCategoryOrderByIdDescJPQL(SectionCategory.ECONOMY, SectionCategory.TECHNOLOGY) + .stream().map(article -> InterestedArticleResponse.of(article)).toList(); + } + case SOCIETY -> { + responses = articleJpaRepository.findAllBySectionCategoryOrderByIdDescJPQL(SectionCategory.ENVIRONMENT, SectionCategory.POLITICS) + .stream().map(article -> InterestedArticleResponse.of(article)).toList(); + } + case TREND -> { + responses = articleJpaRepository.findAllBySectionCategoryOrderByIdDescJPQL(SectionCategory.ART, SectionCategory.TECHNOLOGY) + .stream().map(article -> InterestedArticleResponse.of(article)).toList(); + } + } + return responses; + } }