Skip to content

Commit

Permalink
MATE-136 : [FEAT] 사용자 활동에 따른 매너 타율 업데이트 기능 구현 (#128)
Browse files Browse the repository at this point in the history
* MATE-136 : [FEAT] Member 엔티티에 매너타율 업데이트 기능 구현

- 리뷰 시 Rating에 따라 매너타율 업데이트
- 회원 활동 유형에 따라 매너타율 업데이트

* MATE-136 : [FEAT] 메이트 리뷰 시 매너타율 업데이트 서비스 구현 및 리뷰 제약 조건 추가

- 메이트 구인글의 상태가 VISIT_COMPLETE일 때만 리뷰할 수 있도록 제약
- 중복해서 리뷰 작성이 불가능하도록 제약

* MATE-136 : [TEST] 메이트 리뷰 시 매너타율 업데이트 테스트

* MATE-136 : [FEAT] 굿즈 거래 리뷰 시 매너타율 업데이트 서비스 구현

* MATE-136 : [TEST] 굿즈 거래 리뷰 시 매너타율 업데이트 테스트

* MATE-136 : [FEAT] Member 엔티티에 게시글 삭제 시 매너타율 감소 기능 구현

* MATE-136 : [FEAT] 메이트 구인글 등록/삭제 시 매너타율 업데이트 서비스 구현

* MATE-136 : [TEST] 메이트 구인글 등록/삭제 시 매너타율 업데이트 테스트

* MATE-136 : [FEAT] 굿즈 거래글 등록/삭제 시 매너타율 업데이트 서비스 구현

* MATE-136 : [TEST] 굿즈 거래글 등록/삭제 시 매너타율 업데이트 테스트

* MATE-136 : [FEAT] 굿즈 거래글 거래 완료 시 매너타율 업데이트 서비스 구현

* MATE-136 : [TEST] 굿즈 거래글 거래 완료 시 매너타율 업데이트 테스트

* MATE-136 : [FEAT] 직관 참여 시 매너타율 업데이트 서비스 구현

* MATE-136 : [TEST] 직관 참여 시 매너타율 업데이트 테스트
  • Loading branch information
jooinjoo authored Jan 8, 2025
1 parent efa2a98 commit 98f0e73
Show file tree
Hide file tree
Showing 17 changed files with 324 additions and 90 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/example/mate/common/error/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public enum ErrorCode {
// Mate Review
NOT_PARTICIPANT_OR_AUTHOR(HttpStatus.FORBIDDEN, "R002", "리뷰어와 리뷰 대상자 모두 직관 참여자여야 합니다."),
REVIEW_NOT_FOUND_BY_ID(HttpStatus.NOT_FOUND, "R005", "해당 ID의 리뷰를 찾을 수 없습니다."),
MATE_REVIEW_STATUS_NOT_VISIT_COMPLETE(HttpStatus.BAD_REQUEST, "MR003", "메이트 후기는 직관완료 상태에서만 작성할 수 있습니다."),
MATE_REVIEW_ALREADY_EXISTS(HttpStatus.BAD_REQUEST, "MR004", "메이트 후기는 한 번만 작성할 수 있습니다."),

// FILE
FILE_IS_EMPTY(HttpStatus.BAD_REQUEST, "F001", "빈 파일을 업로드할 수 없습니다. 파일 내용을 확인해주세요."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.example.mate.domain.goodsPost.entity.Status;
import com.example.mate.domain.goodsPost.repository.GoodsPostImageRepository;
import com.example.mate.domain.goodsPost.repository.GoodsPostRepository;
import com.example.mate.domain.member.entity.ActivityType;
import com.example.mate.domain.member.entity.Member;
import com.example.mate.domain.member.repository.MemberRepository;
import java.util.ArrayList;
Expand Down Expand Up @@ -47,10 +48,14 @@ public GoodsPostResponse registerGoodsPost(Long memberId, GoodsPostRequest reque

attachImagesToGoodsPost(savedPost, files);

seller.updateManner(ActivityType.POST);
memberRepository.save(seller);

return GoodsPostResponse.of(savedPost);
}

public GoodsPostResponse updateGoodsPost(Long memberId, Long goodsPostId, GoodsPostRequest request, List<MultipartFile> files) {
public GoodsPostResponse updateGoodsPost(Long memberId, Long goodsPostId, GoodsPostRequest request,
List<MultipartFile> files) {
Member seller = findMemberById(memberId);
GoodsPost goodsPost = findGoodsPostById(goodsPostId);

Expand All @@ -74,6 +79,9 @@ public void deleteGoodsPost(Long memberId, Long goodsPostId) {

deleteExistingImageFiles(goodsPostId);
goodsPostRepository.delete(goodsPost);

seller.updateManner(ActivityType.DELETE);
memberRepository.save(seller);
}

@Transactional(readOnly = true)
Expand All @@ -90,10 +98,12 @@ public List<GoodsPostSummaryResponse> getMainGoodsPosts(Long teamId) {
}

@Transactional(readOnly = true)
public PageResponse<GoodsPostSummaryResponse> getPageGoodsPosts(Long teamId, String categoryVal, Pageable pageable) {
public PageResponse<GoodsPostSummaryResponse> getPageGoodsPosts(Long teamId, String categoryVal,
Pageable pageable) {
validateTeamInfo(teamId);
Category category = Category.from(categoryVal);
Page<GoodsPost> pageGoodsPosts = goodsPostRepository.findPageGoodsPosts(teamId, Status.OPEN, category, pageable);
Page<GoodsPost> pageGoodsPosts = goodsPostRepository.findPageGoodsPosts(teamId, Status.OPEN, category,
pageable);
return PageResponse.from(pageGoodsPosts, mapToGoodsPostSummaryResponses(pageGoodsPosts.getContent()));
}

Expand All @@ -104,6 +114,9 @@ public void completeTransaction(Long sellerId, Long goodsPostId, Long buyerId) {

validateTransactionEligibility(seller, buyer, goodsPost);
goodsPost.completeTransaction(buyer);

seller.updateManner(ActivityType.GOODS);
buyer.updateManner(ActivityType.GOODS);
}

private void attachImagesToGoodsPost(GoodsPost goodsPost, List<MultipartFile> files) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import com.example.mate.common.error.CustomException;
import com.example.mate.common.error.ErrorCode;
import com.example.mate.domain.goodsReview.dto.request.GoodsReviewRequest;
import com.example.mate.domain.goodsReview.dto.response.GoodsReviewResponse;
import com.example.mate.domain.goodsPost.entity.GoodsPost;
import com.example.mate.domain.goodsReview.entity.GoodsReview;
import com.example.mate.domain.goodsPost.entity.Status;
import com.example.mate.domain.goodsPost.repository.GoodsPostRepository;
import com.example.mate.domain.goodsReview.dto.request.GoodsReviewRequest;
import com.example.mate.domain.goodsReview.dto.response.GoodsReviewResponse;
import com.example.mate.domain.goodsReview.entity.GoodsReview;
import com.example.mate.domain.goodsReview.repository.GoodsReviewRepository;
import com.example.mate.domain.member.entity.Member;
import com.example.mate.domain.member.repository.MemberRepository;
Expand All @@ -29,8 +29,13 @@ public GoodsReviewResponse registerGoodsReview(Long reviewerId, Long goodsPostId
GoodsPost goodsPost = findGoodsPostById(goodsPostId);
validateReviewEligibility(goodsPost, reviewer);

GoodsReview review = request.toEntity(goodsPost, reviewer, goodsPost.getSeller());
return GoodsReviewResponse.of(reviewRepository.save(review));
Member seller = goodsPost.getSeller();
GoodsReview review = request.toEntity(goodsPost, reviewer, seller);
GoodsReview savedReview = reviewRepository.save(review);
seller.updateManner(request.getRating());
memberRepository.save(seller);

return GoodsReviewResponse.of(savedReview);
}

private GoodsPost findGoodsPostById(Long goodsPostId) {
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/com/example/mate/domain/mate/entity/Visit.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
package com.example.mate.domain.mate.entity;

import com.example.mate.domain.mate.dto.request.MateReviewCreateRequest;
import com.example.mate.domain.member.entity.ActivityType;
import com.example.mate.domain.member.entity.Member;
import jakarta.persistence.*;
import lombok.*;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;
import java.util.ArrayList;
import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "visit")
Expand Down Expand Up @@ -44,6 +58,7 @@ public static Visit createForComplete(MatePost post, List<Member> participants)
.visit(visit)
.build();
visit.participants.add(visitPart);
member.updateManner(ActivityType.MATE);
});

return visit;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.example.mate.domain.mate.repository;

import com.example.mate.domain.mate.entity.MateReview;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;

public interface MateReviewRepository extends JpaRepository<MateReview, Long> {

int countByRevieweeId(Long revieweeId);
Expand All @@ -20,4 +19,8 @@ public interface MateReviewRepository extends JpaRepository<MateReview, Long> {
""")
List<MateReview> findMateReviewsByVisitIdAndReviewerId(@Param("visitId") Long visitId,
@Param("reviewerId") Long reviewerId);

boolean existsByVisitIdAndReviewerIdAndRevieweeId(@Param("visitId") Long visitId,
@Param("reviewerId") Long reviewerId,
@Param("revieweeId") Long revieweeId);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,36 @@
package com.example.mate.domain.mate.service;

import static com.example.mate.common.error.ErrorCode.ALREADY_COMPLETED_POST;
import static com.example.mate.common.error.ErrorCode.INVALID_MATE_POST_PARTICIPANT_IDS;
import static com.example.mate.common.error.ErrorCode.MATCH_NOT_FOUND_BY_ID;
import static com.example.mate.common.error.ErrorCode.MATE_POST_COMPLETE_TIME_NOT_ALLOWED;
import static com.example.mate.common.error.ErrorCode.MATE_POST_MAX_PARTICIPANTS_EXCEEDED;
import static com.example.mate.common.error.ErrorCode.MATE_POST_NOT_FOUND_BY_ID;
import static com.example.mate.common.error.ErrorCode.MATE_POST_UPDATE_NOT_ALLOWED;
import static com.example.mate.common.error.ErrorCode.MEMBER_NOT_FOUND_BY_ID;
import static com.example.mate.common.error.ErrorCode.NOT_CLOSED_STATUS_FOR_COMPLETION;
import static com.example.mate.common.error.ErrorCode.NOT_PARTICIPANT_OR_AUTHOR;
import static com.example.mate.common.error.ErrorCode.TEAM_NOT_FOUND;

import com.example.mate.common.error.CustomException;
import com.example.mate.common.error.ErrorCode;
import com.example.mate.common.response.PageResponse;
import com.example.mate.domain.constant.TeamInfo;
import com.example.mate.domain.file.FileService;
import com.example.mate.domain.file.FileValidator;
import com.example.mate.domain.match.entity.Match;
import com.example.mate.domain.match.repository.MatchRepository;
import com.example.mate.domain.mate.dto.request.*;
import com.example.mate.domain.mate.dto.response.*;
import com.example.mate.domain.mate.dto.request.MatePostCompleteRequest;
import com.example.mate.domain.mate.dto.request.MatePostCreateRequest;
import com.example.mate.domain.mate.dto.request.MatePostSearchRequest;
import com.example.mate.domain.mate.dto.request.MatePostStatusRequest;
import com.example.mate.domain.mate.dto.request.MatePostUpdateRequest;
import com.example.mate.domain.mate.dto.request.MateReviewCreateRequest;
import com.example.mate.domain.mate.dto.response.MatePostCompleteResponse;
import com.example.mate.domain.mate.dto.response.MatePostDetailResponse;
import com.example.mate.domain.mate.dto.response.MatePostResponse;
import com.example.mate.domain.mate.dto.response.MatePostSummaryResponse;
import com.example.mate.domain.mate.dto.response.MateReviewCreateResponse;
import com.example.mate.domain.mate.entity.MatePost;
import com.example.mate.domain.mate.entity.MateReview;
import com.example.mate.domain.mate.entity.Status;
Expand All @@ -17,8 +39,11 @@
import com.example.mate.domain.mate.repository.MateReviewRepository;
import com.example.mate.domain.mateChat.repository.MateChatRoomMemberRepository;
import com.example.mate.domain.mateChat.repository.MateChatRoomRepository;
import com.example.mate.domain.member.entity.ActivityType;
import com.example.mate.domain.member.entity.Member;
import com.example.mate.domain.member.repository.MemberRepository;
import java.time.LocalDateTime;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
Expand All @@ -27,11 +52,6 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.List;

import static com.example.mate.common.error.ErrorCode.*;

@Service
@Transactional
@RequiredArgsConstructor
Expand Down Expand Up @@ -71,6 +91,9 @@ public MatePostResponse createMatePost(MatePostCreateRequest request, MultipartF

handleFileUpload(file, matePost);

author.updateManner(ActivityType.POST);
memberRepository.save(author);

return MatePostResponse.from(savedPost);
}

Expand Down Expand Up @@ -197,6 +220,11 @@ public void deleteMatePost(Long memberId, Long postId) {
deleteNonDefaultImage(matePost.getImageUrl());

mateRepository.delete(matePost);

Member member = memberRepository.findByIdAndNotDeleted(memberId)
.orElseThrow(() -> new CustomException(MEMBER_NOT_FOUND_BY_ID));
member.updateManner(ActivityType.DELETE);
memberRepository.save(member);
}

private void validatePostStatus(Status status) {
Expand All @@ -216,6 +244,7 @@ public MatePostCompleteResponse completeVisit(Long memberId, Long postId, MatePo
matePost.getMaxParticipants());

matePost.complete(participants);
matePost.getAuthor().updateManner(ActivityType.MATE);
return MatePostCompleteResponse.from(matePost);
}

Expand Down Expand Up @@ -266,6 +295,8 @@ public MateReviewCreateResponse createReview(Long postId, Long reviewerId, MateR

MateReview review = matePost.getVisit().createReview(reviewer, reviewee, request);
MateReview savedReview = mateReviewRepository.save(review);
reviewee.updateManner(request.getRating());
memberRepository.save(reviewee);

return MateReviewCreateResponse.from(savedReview);
}
Expand All @@ -274,6 +305,17 @@ private void validateReviewEligibility(MatePost matePost, Member reviewer, Membe
// 리뷰어와 리뷰 대상자 모두 참여자(또는 방장) 여부 검증
validateParticipant(matePost, reviewer);
validateParticipant(matePost, reviewee);

if (matePost.getStatus() != Status.VISIT_COMPLETE) {
throw new CustomException(ErrorCode.MATE_REVIEW_STATUS_NOT_VISIT_COMPLETE);
}

if (mateReviewRepository.existsByVisitIdAndReviewerIdAndRevieweeId(
matePost.getVisit().getId(),
reviewer.getId(),
reviewee.getId())) {
throw new CustomException(ErrorCode.MATE_REVIEW_ALREADY_EXISTS);
}
}

private void validateParticipant(MatePost matePost, Member member) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.example.mate.domain.member.entity;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum ActivityType {
POST(0.001F),
DELETE(-0.001F),
GOODS(0.002F),
MATE(0.003F);

private final Float value;
}
19 changes: 19 additions & 0 deletions src/main/java/com/example/mate/domain/member/entity/Member.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.mate.domain.member.entity;

import com.example.mate.domain.constant.Gender;
import com.example.mate.domain.constant.Rating;
import com.example.mate.domain.constant.TeamInfo;
import com.example.mate.domain.member.dto.request.JoinRequest;
import jakarta.persistence.Column;
Expand Down Expand Up @@ -99,6 +100,24 @@ public void changeAboutMe(String aboutMe) {
this.aboutMe = aboutMe;
}

public void updateManner(Rating rating) {
if (rating == Rating.BAD) {
this.manner = Math.max(0.0F, this.manner - 0.01F);
} else if (rating == Rating.GOOD) {
this.manner = Math.min(1.0F, this.manner + 0.02F);
} else {
this.manner = Math.min(1.0F, this.manner + 0.03F);
}
}

public void updateManner(ActivityType activityType) {
if (activityType == ActivityType.DELETE) {
this.manner = Math.max(0.0F, this.manner + activityType.getValue());
} else {
this.manner = Math.min(1.0F, this.manner + activityType.getValue());
}
}

public static Member of(JoinRequest request, String imageUrl) {
return Member.builder()
.name(request.getName())
Expand Down
Loading

0 comments on commit 98f0e73

Please sign in to comment.