diff --git a/backend/src/main/java/aimo/backend/common/scheduler/SchedulingConfig.java b/backend/src/main/java/aimo/backend/common/scheduler/SchedulingConfig.java new file mode 100644 index 0000000..d9ad2ce --- /dev/null +++ b/backend/src/main/java/aimo/backend/common/scheduler/SchedulingConfig.java @@ -0,0 +1,9 @@ +package aimo.backend.common.scheduler; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +@EnableScheduling +@Configuration +public class SchedulingConfig { +} diff --git a/backend/src/main/java/aimo/backend/common/scheduler/SchedulingService.java b/backend/src/main/java/aimo/backend/common/scheduler/SchedulingService.java new file mode 100644 index 0000000..d24a257 --- /dev/null +++ b/backend/src/main/java/aimo/backend/common/scheduler/SchedulingService.java @@ -0,0 +1,24 @@ +package aimo.backend.common.scheduler; + +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import aimo.backend.domains.member.repository.MemberAttemptCountRepository; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class SchedulingService { + + private final MemberAttemptCountRepository memberAttemptCountRepository; + + @Transactional + @Async + @Scheduled(cron = "0 0 0 * * ?") //매일 자정에 초기화 + public void deleteAllMemberPointLimitCount() { + memberAttemptCountRepository.deleteAll(); + } +} diff --git a/backend/src/main/java/aimo/backend/common/security/SecurityConfig.java b/backend/src/main/java/aimo/backend/common/security/SecurityConfig.java index 424d976..9c8ce46 100644 --- a/backend/src/main/java/aimo/backend/common/security/SecurityConfig.java +++ b/backend/src/main/java/aimo/backend/common/security/SecurityConfig.java @@ -20,6 +20,7 @@ import aimo.backend.common.properties.SecurityProperties; import aimo.backend.common.security.oAuth.OAuth2LoginFailureHandler; +import aimo.backend.domains.member.service.MemberPointService; import aimo.backend.domains.member.service.MemberService; import aimo.backend.common.security.filter.exceptionHandlingFilter.ExceptionHandlingFilter; import aimo.backend.common.security.filter.jwtFilter.JwtAuthenticationFilter; @@ -35,7 +36,7 @@ public class SecurityConfig { private final MemberService memberService; - + private final MemberPointService memberPointService; private final UserDetailsService userDetailsService; private final JwtTokenProvider jwtTokenProvider; private final CustomOAuth2UserService customOAuth2UserService; @@ -112,7 +113,7 @@ public LoginFilter loginFilter() { @Bean public JwtAuthenticationFilter jwtAuthenticationFilter() { - return new JwtAuthenticationFilter(jwtTokenProvider, securityProperties, pathMatcher); + return new JwtAuthenticationFilter(jwtTokenProvider, securityProperties, pathMatcher, memberPointService); } @Bean diff --git a/backend/src/main/java/aimo/backend/common/security/filter/jwtFilter/JwtAuthenticationFilter.java b/backend/src/main/java/aimo/backend/common/security/filter/jwtFilter/JwtAuthenticationFilter.java index 90f9390..40ba04f 100644 --- a/backend/src/main/java/aimo/backend/common/security/filter/jwtFilter/JwtAuthenticationFilter.java +++ b/backend/src/main/java/aimo/backend/common/security/filter/jwtFilter/JwtAuthenticationFilter.java @@ -4,6 +4,8 @@ import aimo.backend.common.exception.ApiException; import aimo.backend.common.properties.SecurityProperties; +import aimo.backend.domains.member.model.IncreasePoint; +import aimo.backend.domains.member.service.MemberPointService; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -27,6 +29,7 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { private final JwtTokenProvider jwtTokenProvider; private final SecurityProperties securityProperties; private final AntPathMatcher pathMatcher; + private final MemberPointService memberPointService; @Override protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { @@ -79,7 +82,12 @@ protected void doFilterInternal( } checkLogoutToken(accessToken); + log.info("access 토큰 인증 성공"); + + // 출석 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(jwtTokenProvider.extractMemberId(accessToken).get(), IncreasePoint.ATTENDANCE); + Authentication authentication = jwtTokenProvider.getAuthentication(accessToken); saveAuthentication(authentication); filterChain.doFilter(request, response); diff --git a/backend/src/main/java/aimo/backend/common/util/memberLoader/MemberLoader.java b/backend/src/main/java/aimo/backend/common/util/memberLoader/MemberLoader.java index 667199d..52a82ad 100644 --- a/backend/src/main/java/aimo/backend/common/util/memberLoader/MemberLoader.java +++ b/backend/src/main/java/aimo/backend/common/util/memberLoader/MemberLoader.java @@ -1,13 +1,7 @@ package aimo.backend.common.util.memberLoader; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.stereotype.Component; -import aimo.backend.domains.member.entity.Member; -import lombok.RequiredArgsConstructor; - -@Component -@RequiredArgsConstructor public class MemberLoader { public static Long getMemberId() { diff --git a/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java b/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java index dcd0b29..3f9c1b0 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java +++ b/backend/src/main/java/aimo/backend/domains/comment/service/ChildCommentService.java @@ -14,7 +14,9 @@ import aimo.backend.domains.comment.repository.ChildCommentRepository; import aimo.backend.domains.comment.repository.ParentCommentRepository; import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.model.IncreasePoint; import aimo.backend.domains.member.repository.MemberRepository; +import aimo.backend.domains.member.service.MemberPointService; import aimo.backend.domains.post.entity.Post; import aimo.backend.domains.post.repository.PostRepository; import lombok.RequiredArgsConstructor; @@ -29,6 +31,7 @@ public class ChildCommentService { private final PostRepository postRepository; private final ParentCommentService parentCommentService; private final ParentCommentRepository parentCommentRepository; + private final MemberPointService memberPointService; //자식 댓글 권한 확인 private void validateChildCommentAuthority(Long memberId, Long childCommentId) { @@ -56,6 +59,9 @@ public void saveChildComment(SaveChildCommentParameter parameter) { ChildComment childComment = ChildComment.of(content, member, parentComment, post); childCommentRepository.save(childComment); + + // 멤버 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(member.getId(), IncreasePoint.COMMENT); } //자식 댓글 수정 diff --git a/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java b/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java index 4761228..8e85b40 100644 --- a/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java +++ b/backend/src/main/java/aimo/backend/domains/comment/service/ParentCommentService.java @@ -15,7 +15,9 @@ import aimo.backend.domains.comment.entity.ParentComment; import aimo.backend.domains.comment.repository.ParentCommentRepository; import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.model.IncreasePoint; import aimo.backend.domains.member.repository.MemberRepository; +import aimo.backend.domains.member.service.MemberPointService; import aimo.backend.domains.post.entity.Post; import aimo.backend.domains.post.repository.PostRepository; import lombok.RequiredArgsConstructor; @@ -28,6 +30,7 @@ public class ParentCommentService { private final PostRepository postRepository; private final ParentCommentRepository parentCommentRepository; private final MemberRepository memberRepository; + private final MemberPointService memberPointService; // 부모 댓글 권한 확인 private void validateParentCommentAuthority(Long memberId, Long commentId) { @@ -51,8 +54,10 @@ public void saveParentComment(SaveParentCommentParameter parameter) { .orElseThrow(() -> ApiException.from(POST_NOT_FOUND)); ParentComment parentComment = ParentComment.of(member, post, parameter.content()); - parentCommentRepository.save(parentComment); + + // 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(memberId, IncreasePoint.COMMENT); } // 부모 댓글 수정 @@ -79,7 +84,7 @@ public void validateAndDeleteParentComment(DeleteParentCommentParameter paramete parentCommentRepository.findById(commentId) .ifPresent((parentComment) -> { - if(!parentComment.getChildComments().isEmpty()){ + if (!parentComment.getChildComments().isEmpty()) { parentComment.deleteParentCommentSoftlyWithContent(); return; } @@ -88,13 +93,13 @@ public void validateAndDeleteParentComment(DeleteParentCommentParameter paramete } // 자식 댓글이 없고 삭제된 부모 댓글이면 삭제 - public void deleteIfParentCommentIsDeletedAndChildrenIsEmpty(ParentComment parentComment){ + public void deleteIfParentCommentIsDeletedAndChildrenIsEmpty(ParentComment parentComment) { // 부모 댓글이 삭제되지 않은 상태면 return if (!parentComment.getIsDeleted()) { return; } // 자식 댓글이 존재하면 return - if(!parentComment.getChildComments().isEmpty()){ + if (!parentComment.getChildComments().isEmpty()) { return; } diff --git a/backend/src/main/java/aimo/backend/domains/like/controller/LikeController.java b/backend/src/main/java/aimo/backend/domains/like/controller/LikeController.java index d494b53..040f083 100644 --- a/backend/src/main/java/aimo/backend/domains/like/controller/LikeController.java +++ b/backend/src/main/java/aimo/backend/domains/like/controller/LikeController.java @@ -12,11 +12,11 @@ import aimo.backend.common.util.memberLoader.MemberLoader; import aimo.backend.domains.like.dto.parameter.LikeChildCommentParameter; import aimo.backend.domains.like.dto.parameter.LikeParentCommentParameter; +import aimo.backend.domains.like.dto.parameter.LikePostParameter; import aimo.backend.domains.like.model.LikeType; import aimo.backend.domains.like.service.ChildCommentLikeService; import aimo.backend.domains.like.service.ParentCommentLikeService; import aimo.backend.domains.like.service.PostLikeService; -import aimo.backend.domains.like.dto.parameter.LikePostParameter; import lombok.RequiredArgsConstructor; @RestController @@ -28,7 +28,6 @@ public class LikeController { private final ChildCommentLikeService childCommentLikeService; private final ParentCommentLikeService parentCommentLikeService; - @PostMapping("/comments/child/{childCommentId}/likes") public ResponseEntity> likeChildComment( @PathVariable Long childCommentId, @@ -61,7 +60,6 @@ public ResponseEntity> likeParentComment( .body(DataResponse.created()); } - @PostMapping("/{postId}/likes") public ResponseEntity> likePost( @PathVariable Long postId, diff --git a/backend/src/main/java/aimo/backend/domains/like/service/ChildCommentLikeService.java b/backend/src/main/java/aimo/backend/domains/like/service/ChildCommentLikeService.java index 57d994e..8bcc31b 100644 --- a/backend/src/main/java/aimo/backend/domains/like/service/ChildCommentLikeService.java +++ b/backend/src/main/java/aimo/backend/domains/like/service/ChildCommentLikeService.java @@ -13,7 +13,9 @@ import aimo.backend.domains.like.model.LikeType; import aimo.backend.domains.like.repository.ChildCommentLikeRepository; import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.model.IncreasePoint; import aimo.backend.domains.member.repository.MemberRepository; +import aimo.backend.domains.member.service.MemberPointService; import lombok.RequiredArgsConstructor; @Service @@ -24,6 +26,7 @@ public class ChildCommentLikeService { private final ChildCommentLikeRepository childCommentLikeRepository; private final MemberRepository memberRepository; private final ChildCommentRepository childCommentRepository; + private final MemberPointService memberPointService; @Transactional(rollbackFor = ApiException.class) public void likeChildComment(LikeChildCommentParameter parameter) { @@ -35,14 +38,19 @@ public void likeChildComment(LikeChildCommentParameter parameter) { ChildComment childComment = childCommentRepository.findById(childCommentId) .orElseThrow(() -> ApiException.from(CHILD_COMMENT_NOT_FOUND)); + // 좋아요 타입이 LIKE인 경우, 이미 좋아요 누르지 않았을 경우에만 좋아요 저장 if (parameter.likeType() == LikeType.LIKE) { if (childCommentLikeRepository.existsByChildCommentIdAndMemberId(childCommentId, memberId)) return; + // 좋아요 저장 childCommentLikeRepository.save(ChildCommentLike.from(member, childComment)); + // 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(memberId, IncreasePoint.LIKE); return; } + // 좋아요 타입이 DISLIKE인 경우, 좋아요 삭제 childCommentLikeRepository.deleteByMemberIdAndChildCommentId(member.getId(), childCommentId); } } diff --git a/backend/src/main/java/aimo/backend/domains/like/service/ParentCommentLikeService.java b/backend/src/main/java/aimo/backend/domains/like/service/ParentCommentLikeService.java index 3b5319f..be29f92 100644 --- a/backend/src/main/java/aimo/backend/domains/like/service/ParentCommentLikeService.java +++ b/backend/src/main/java/aimo/backend/domains/like/service/ParentCommentLikeService.java @@ -13,7 +13,9 @@ import aimo.backend.domains.like.model.LikeType; import aimo.backend.domains.like.repository.ParentCommentLikeRepository; import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.model.IncreasePoint; import aimo.backend.domains.member.repository.MemberRepository; +import aimo.backend.domains.member.service.MemberPointService; import lombok.RequiredArgsConstructor; @Service @@ -24,6 +26,7 @@ public class ParentCommentLikeService { private final ParentCommentLikeRepository parentCommentLikeRepository; private final ParentCommentRepository parentCommentRepository; private final MemberRepository memberRepository; + private final MemberPointService memberPointService; @Transactional(rollbackFor = ApiException.class) public void likeParentComment(LikeParentCommentParameter parameter) { @@ -37,14 +40,20 @@ public void likeParentComment(LikeParentCommentParameter parameter) { ParentComment parentComment = parentCommentRepository.findById(parentCommentId) .orElseThrow(() -> ApiException.from(PARENT_COMMENT_NOT_FOUND)); + // 라이크 타입이 LIKE인 경우 저장, 이미 라이크가 존재하면 무시 if (likeType == LikeType.LIKE) { // 라이크가 이미 존재하면 무시 if (parentCommentLikeRepository.existsByParentCommentIdAndMemberId(parentCommentId, memberId)) return; + // 라이크 저장 parentCommentLikeRepository.save(ParentCommentLike.from(member, parentComment)); + // 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(memberId, IncreasePoint.LIKE); + return; } + // 라이크 타입이 DISLIKE인 경우 삭제 parentCommentLikeRepository.deleteByMember_IdAndParentComment_Id(member.getId(), parentCommentId); } } diff --git a/backend/src/main/java/aimo/backend/domains/like/service/PostLikeService.java b/backend/src/main/java/aimo/backend/domains/like/service/PostLikeService.java index 6366df2..39f7915 100644 --- a/backend/src/main/java/aimo/backend/domains/like/service/PostLikeService.java +++ b/backend/src/main/java/aimo/backend/domains/like/service/PostLikeService.java @@ -6,11 +6,13 @@ import org.springframework.transaction.annotation.Transactional; import aimo.backend.common.exception.ApiException; +import aimo.backend.domains.like.dto.parameter.LikePostParameter; import aimo.backend.domains.like.entity.PostLike; import aimo.backend.domains.like.model.LikeType; import aimo.backend.domains.like.repository.PostLikeRepository; +import aimo.backend.domains.member.model.IncreasePoint; import aimo.backend.domains.member.repository.MemberRepository; -import aimo.backend.domains.like.dto.parameter.LikePostParameter; +import aimo.backend.domains.member.service.MemberPointService; import aimo.backend.domains.post.entity.Post; import aimo.backend.domains.post.repository.PostRepository; import lombok.RequiredArgsConstructor; @@ -23,6 +25,7 @@ public class PostLikeService { private final PostLikeRepository postLikeRepository; private final PostRepository postRepository; private final MemberRepository memberRepository; + private final MemberPointService memberPointService; @Transactional(rollbackFor = Exception.class) public void likePost(LikePostParameter parameter) { @@ -51,7 +54,9 @@ public void likePost(LikePostParameter parameter) { // 포스트 라이크 수 증가 post.increasePostLikesCount(); - return ; + // 멤버 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(memberId, IncreasePoint.LIKE); + return; } // 라이크가 이미 존재하면 삭제 diff --git a/backend/src/main/java/aimo/backend/domains/member/controller/MemberPointController.java b/backend/src/main/java/aimo/backend/domains/member/controller/MemberPointController.java new file mode 100644 index 0000000..289f230 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/member/controller/MemberPointController.java @@ -0,0 +1,32 @@ +package aimo.backend.domains.member.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import aimo.backend.common.dto.DataResponse; +import aimo.backend.common.util.memberLoader.MemberLoader; +import aimo.backend.domains.member.dto.response.FindMemberPointResponse; +import aimo.backend.domains.member.service.MemberPointService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RestController +@RequestMapping("/api/v1/members/points") +@RequiredArgsConstructor +public class MemberPointController { + + private final MemberPointService memberPointService; + + // 멤버 포인트 조회 + @GetMapping + public ResponseEntity> findMemberPoint() { + Long memberId = MemberLoader.getMemberId(); + + FindMemberPointResponse response = memberPointService.findMemberPoint(memberId); + + return ResponseEntity.ok(DataResponse.from(response)); + } +} diff --git a/backend/src/main/java/aimo/backend/domains/member/dto/response/FindMemberPointResponse.java b/backend/src/main/java/aimo/backend/domains/member/dto/response/FindMemberPointResponse.java new file mode 100644 index 0000000..c079d92 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/member/dto/response/FindMemberPointResponse.java @@ -0,0 +1,6 @@ +package aimo.backend.domains.member.dto.response; + +public record FindMemberPointResponse( + Integer memberPoint +) { +} diff --git a/backend/src/main/java/aimo/backend/domains/member/dto/response/FindMyInfoResponse.java b/backend/src/main/java/aimo/backend/domains/member/dto/response/FindMyInfoResponse.java index 678ed75..53aa3ff 100644 --- a/backend/src/main/java/aimo/backend/domains/member/dto/response/FindMyInfoResponse.java +++ b/backend/src/main/java/aimo/backend/domains/member/dto/response/FindMyInfoResponse.java @@ -5,23 +5,33 @@ public record FindMyInfoResponse( String nickname, String email, - String profileImageUrl + String profileImageUrl, + Integer point ) { public static FindMyInfoResponse of( String nickname, String email, - String profileImageUrl + String profileImageUrl, + Integer point ) { - return new FindMyInfoResponse(nickname, email, profileImageUrl); + return new FindMyInfoResponse(nickname, email, profileImageUrl, point); } - public static FindMyInfoResponse from(Member member){ + public static FindMyInfoResponse from(Member member) { if (member.getProfileImage() == null) { - return new FindMyInfoResponse(member.getNickname(), member.getEmail(), null); + return new FindMyInfoResponse( + member.getNickname(), + member.getEmail(), + null, + member.getPoint()); } - return new FindMyInfoResponse(member.getNickname(), member.getEmail(), member.getProfileImage().getUrl()); + return new FindMyInfoResponse( + member.getNickname(), + member.getEmail(), + member.getProfileImage().getUrl(), + member.getPoint()); } } diff --git a/backend/src/main/java/aimo/backend/domains/member/entity/Member.java b/backend/src/main/java/aimo/backend/domains/member/entity/Member.java index d8e7ac9..5cb257a 100644 --- a/backend/src/main/java/aimo/backend/domains/member/entity/Member.java +++ b/backend/src/main/java/aimo/backend/domains/member/entity/Member.java @@ -7,6 +7,7 @@ import java.util.List; import org.apache.commons.lang3.RandomStringUtils; +import org.hibernate.annotations.ColumnDefault; import aimo.backend.domains.comment.entity.ChildComment; import aimo.backend.domains.member.dto.parameter.SignUpParameter; @@ -85,6 +86,10 @@ public class Member extends BaseEntity { @OneToMany(mappedBy = "member") private List childComments = new ArrayList<>(); + @Column(nullable = false) + @ColumnDefault("0") + private int point = 0; + public void updateProfileImage(ProfileImage profileImage) { this.profileImage = profileImage; } @@ -153,4 +158,8 @@ private Member( this.parentComments = parentComments; this.childComments = childComments; } + + public void increasePoint(int point) { + this.point += point; + } } diff --git a/backend/src/main/java/aimo/backend/domains/member/entity/MemberAttemptCount.java b/backend/src/main/java/aimo/backend/domains/member/entity/MemberAttemptCount.java new file mode 100644 index 0000000..34c99a1 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/member/entity/MemberAttemptCount.java @@ -0,0 +1,79 @@ +package aimo.backend.domains.member.entity; + +import static lombok.AccessLevel.*; + +import org.hibernate.annotations.ColumnDefault; + +import aimo.backend.domains.member.model.IncreasePoint; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@AllArgsConstructor(access = PRIVATE) +@NoArgsConstructor(access = PROTECTED) +public class MemberAttemptCount { + + @Id + private Long memberId; + + @ColumnDefault("0") + private int likeCount = 0; + + @ColumnDefault("0") + private int commentCount = 0; + + @ColumnDefault("0") + private int voteCount = 0; + + @ColumnDefault("0") + private int postCount = 0; + + @ColumnDefault("0") + private int attendanceCount = 0; + + public static MemberAttemptCount createBasic(Long memberId) { + return new MemberAttemptCount(memberId, 0, 0, 0, 0, 0); + } + + public boolean canReceivePoint(IncreasePoint increasePoint) { + if (increasePoint == IncreasePoint.VOTE && voteCount < increasePoint.getLimitAttemptCountPerDay()) { + return true; + } + if (increasePoint == IncreasePoint.ATTENDANCE && attendanceCount < increasePoint.getLimitAttemptCountPerDay()) { + return true; + } + if (increasePoint == IncreasePoint.LIKE && likeCount < increasePoint.getLimitAttemptCountPerDay()) { + return true; + } + if (increasePoint == IncreasePoint.COMMENT && commentCount < increasePoint.getLimitAttemptCountPerDay()) { + return true; + } + + if (increasePoint == IncreasePoint.POST && postCount < increasePoint.getLimitAttemptCountPerDay()) { + return true; + } + return false; + } + + public void increaseCount(IncreasePoint increasePoint) { + if (increasePoint == IncreasePoint.VOTE) { + voteCount++; + } + if (increasePoint == IncreasePoint.ATTENDANCE) { + attendanceCount++; + } + if (increasePoint == IncreasePoint.LIKE) { + likeCount++; + } + if (increasePoint == IncreasePoint.COMMENT) { + commentCount++; + } + if (increasePoint == IncreasePoint.POST) { + postCount++; + } + } +} diff --git a/backend/src/main/java/aimo/backend/domains/member/model/DecreasePoint.java b/backend/src/main/java/aimo/backend/domains/member/model/DecreasePoint.java new file mode 100644 index 0000000..b54d3fc --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/member/model/DecreasePoint.java @@ -0,0 +1,15 @@ +package aimo.backend.domains.member.model; + +import lombok.Getter; + +@Getter +public enum DecreasePoint { + AI_REQUEST(10) + ; + + private final int point; + + DecreasePoint(int point) { + this.point = point; + } +} diff --git a/backend/src/main/java/aimo/backend/domains/member/model/IncreasePoint.java b/backend/src/main/java/aimo/backend/domains/member/model/IncreasePoint.java new file mode 100644 index 0000000..8b0a770 --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/member/model/IncreasePoint.java @@ -0,0 +1,22 @@ +package aimo.backend.domains.member.model; + +import lombok.Getter; + +@Getter +public enum IncreasePoint { + + LIKE(5, 3), + COMMENT(5, 3), + POST(20, 3), + VOTE(5, 3), + ATTENDANCE(10, 1), + ; + + private final int point; + private final int limitAttemptCountPerDay; + + IncreasePoint(int point, int limitAttemptCountPerDay) { + this.point = point; + this.limitAttemptCountPerDay = limitAttemptCountPerDay; + } +} diff --git a/backend/src/main/java/aimo/backend/domains/member/repository/MemberAttemptCountRepository.java b/backend/src/main/java/aimo/backend/domains/member/repository/MemberAttemptCountRepository.java new file mode 100644 index 0000000..7934fad --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/member/repository/MemberAttemptCountRepository.java @@ -0,0 +1,8 @@ +package aimo.backend.domains.member.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import aimo.backend.domains.member.entity.MemberAttemptCount; + +public interface MemberAttemptCountRepository extends JpaRepository { +} diff --git a/backend/src/main/java/aimo/backend/domains/member/service/MemberPointService.java b/backend/src/main/java/aimo/backend/domains/member/service/MemberPointService.java new file mode 100644 index 0000000..5a0bbfa --- /dev/null +++ b/backend/src/main/java/aimo/backend/domains/member/service/MemberPointService.java @@ -0,0 +1,45 @@ +package aimo.backend.domains.member.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import aimo.backend.common.exception.ApiException; +import aimo.backend.common.exception.ErrorCode; +import aimo.backend.domains.member.dto.response.FindMemberPointResponse; +import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.entity.MemberAttemptCount; +import aimo.backend.domains.member.model.IncreasePoint; +import aimo.backend.domains.member.repository.MemberAttemptCountRepository; +import aimo.backend.domains.member.repository.MemberRepository; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MemberPointService { + + private final MemberRepository memberRepository; + private final MemberAttemptCountRepository memberAttemptCountRepository; + + @Transactional + public void checkAndIncreaseMemberPoint(Long memberId, IncreasePoint increasePoint) { + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> ApiException.from(ErrorCode.MEMBER_NOT_FOUND)); + MemberAttemptCount memberAttemptCount = memberAttemptCountRepository.findById(memberId) + .orElse(MemberAttemptCount.createBasic(memberId)); + + // 하루 포인트 받을 수 있는 횟수 확인 후 포인트 증가 + if (memberAttemptCount.canReceivePoint(increasePoint)) { + memberAttemptCount.increaseCount(increasePoint); + member.increasePoint(increasePoint.getPoint()); + } + + memberAttemptCountRepository.save(memberAttemptCount); + } + + public FindMemberPointResponse findMemberPoint(Long memberId) { + Member member = memberRepository.findById(memberId) + .orElseThrow(() -> ApiException.from(ErrorCode.MEMBER_NOT_FOUND)); + return new FindMemberPointResponse(member.getPoint()); + } +} diff --git a/backend/src/main/java/aimo/backend/domains/post/service/PostService.java b/backend/src/main/java/aimo/backend/domains/post/service/PostService.java index 285db1c..0c49642 100644 --- a/backend/src/main/java/aimo/backend/domains/post/service/PostService.java +++ b/backend/src/main/java/aimo/backend/domains/post/service/PostService.java @@ -17,7 +17,9 @@ import aimo.backend.domains.comment.repository.ParentCommentRepository; import aimo.backend.domains.like.repository.PostLikeRepository; import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.model.IncreasePoint; import aimo.backend.domains.member.repository.MemberRepository; +import aimo.backend.domains.member.service.MemberPointService; import aimo.backend.domains.post.dto.parameter.DeletePostParameter; import aimo.backend.domains.post.dto.parameter.FindPostAndCommentsByIdParameter; import aimo.backend.domains.post.dto.parameter.FindPostByPostTypeParameter; @@ -48,6 +50,7 @@ public class PostService { private final ChildCommentRepository childCommentRepository; private final PostLikeRepository postLikeRepository; private final VoteRepository voteRepository; + private final MemberPointService memberPointService; // 글 저장 @Transactional @@ -57,7 +60,12 @@ public Long save(SavePostParameter savePostParameter) { privatePostService.publishPrivatePost(savePostParameter.privatePostId()); Post post = Post.of(savePostParameter, member); - return postRepository.save(post).getId(); + post = postRepository.save(post); + + // 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(member.getId(), IncreasePoint.POST); + + return post.getId(); } // 글 조회, dto로 응답 diff --git a/backend/src/main/java/aimo/backend/domains/vote/service/VoteService.java b/backend/src/main/java/aimo/backend/domains/vote/service/VoteService.java index 54fab9f..f728171 100644 --- a/backend/src/main/java/aimo/backend/domains/vote/service/VoteService.java +++ b/backend/src/main/java/aimo/backend/domains/vote/service/VoteService.java @@ -2,13 +2,14 @@ import static aimo.backend.common.exception.ErrorCode.*; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import aimo.backend.common.exception.ApiException; import aimo.backend.domains.member.entity.Member; +import aimo.backend.domains.member.model.IncreasePoint; import aimo.backend.domains.member.repository.MemberRepository; +import aimo.backend.domains.member.service.MemberPointService; import aimo.backend.domains.post.entity.Post; import aimo.backend.domains.post.repository.PostRepository; import aimo.backend.domains.vote.dto.SaveVotePostParameter; @@ -25,7 +26,7 @@ public class VoteService { private final VoteRepository voteRepository; private final MemberRepository memberRepository; private final PostRepository postRepository; - private final ApplicationEventPublisher eventPublisher; + private final MemberPointService memberPointService; // 투표하기 @Transactional(rollbackFor = ApiException.class) @@ -44,6 +45,9 @@ public void votePost(SaveVotePostParameter parameter) { () -> { Vote newVote = Vote.from(post, member, side); voteRepository.save(newVote); + + // 포인트 증가 + memberPointService.checkAndIncreaseMemberPoint(member.getId(), IncreasePoint.VOTE); } ); }