Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/#141 리뷰 추가 기능 구현 #190

Merged
merged 7 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void cancel(User tokenUser, boolean projectHasReq) {
validateAvailableCancel(tokenUser);
// 매칭 준비중이지만 요청이 있을때는 잔디력 감소
if (projectHasReq) {
this.creator.decreaseJandiRate();
this.creator.updateJandiRateByCancel();
}
this.projectStatus = ProjectStatus.CANCELED;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package io.oeid.mogakgo.domain.review.application;

import io.oeid.mogakgo.domain.project.infrastructure.ProjectJpaRepository;
import io.oeid.mogakgo.domain.review.application.dto.req.ReviewCreateReq;
import io.oeid.mogakgo.domain.review.application.dto.res.ReviewCreateRes;
import io.oeid.mogakgo.domain.review.domain.Review;
import io.oeid.mogakgo.domain.review.exception.ReviewException;
import io.oeid.mogakgo.domain.review.infrastructure.ReviewJpaRepository;
import io.oeid.mogakgo.domain.user.application.UserCommonService;
import io.oeid.mogakgo.exception.code.ErrorCode400;
import io.oeid.mogakgo.exception.code.ErrorCode404;
import java.time.Duration;
import java.time.LocalDateTime;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class ReviewService {

private final ReviewJpaRepository reviewRepository;
private final ProjectJpaRepository projectRepository;
private final UserCommonService userCommonService;

@Transactional
public ReviewCreateRes createNewReview(ReviewCreateReq request) {
reviewRepository.findReviewByProjectData(request.getSenderId(), request.getReceiverId(),
request.getProjectId()).ifPresent(review -> {
throw new ReviewException(ErrorCode400.REVIEW_ALREADY_EXISTS);
});
var sender = userCommonService.getUserById(request.getSenderId());
var receiver = userCommonService.getUserById(request.getReceiverId());
var project = projectRepository.findById(request.getProjectId())
.orElseThrow(() -> new ReviewException(ErrorCode404.PROJECT_NOT_FOUND));
var review = reviewRepository.save(Review.builder()
.sender(sender)
.receiver(receiver)
.project(project)
.rating(request.getRating())
.build()
);
receiver.updateJandiRateByReview(review.getRating(),
calculateProjectTime(project.getMeetingInfo().getMeetStartTime(),
project.getMeetingInfo().getMeetEndTime()));
return ReviewCreateRes.from(review);
}

private double calculateProjectTime(LocalDateTime meetStartTime, LocalDateTime meetEndTime) {
Duration duration = Duration.between(meetStartTime, meetEndTime);
double hours = duration.toHours();
double minutes = duration.toMinutes() % 60;
return hours + minutes / 60;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.oeid.mogakgo.domain.review.application.dto.req;

import io.oeid.mogakgo.domain.review.domain.enums.ReviewRating;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class ReviewCreateReq {
private Long senderId;
private Long receiverId;
private Long projectId;
private ReviewRating rating;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.oeid.mogakgo.domain.review.application.dto.res;

import io.oeid.mogakgo.domain.review.domain.Review;
import io.oeid.mogakgo.domain.review.domain.enums.ReviewRating;
import java.time.LocalDateTime;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ReviewCreateRes {
private Long id;
private Long senderId;
private Long receiverId;
private Long projectId;
private ReviewRating rating;
private LocalDateTime createdAt;

public static ReviewCreateRes from(Review review) {
return new ReviewCreateRes(
review.getId(),
review.getSender().getId(),
review.getReceiver().getId(),
review.getProject().getId(),
review.getRating(),
review.getCreatedAt()
);
}
}
81 changes: 81 additions & 0 deletions src/main/java/io/oeid/mogakgo/domain/review/domain/Review.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package io.oeid.mogakgo.domain.review.domain;

import static jakarta.persistence.GenerationType.IDENTITY;
import static lombok.AccessLevel.PROTECTED;

import io.oeid.mogakgo.domain.project.domain.entity.Project;
import io.oeid.mogakgo.domain.review.domain.enums.ReviewRating;
import io.oeid.mogakgo.domain.review.exception.ReviewException;
import io.oeid.mogakgo.domain.user.domain.User;
import io.oeid.mogakgo.exception.code.ErrorCode400;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import java.time.LocalDateTime;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;

@Getter
@Entity
@Table(name = "review_tb")
@NoArgsConstructor(access = PROTECTED)
public class Review {

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id")
private Long id;

@ManyToOne
@JoinColumn(name = "sender_id")
private User sender;

@ManyToOne
@JoinColumn(name = "receiver_id")
private User receiver;

@ManyToOne
@JoinColumn(name = "project_id")
private Project project;

@Enumerated(EnumType.STRING)
@Column(name = "rating")
private ReviewRating rating;

@CreationTimestamp
@Column(name = "created_at")
LocalDateTime createdAt;

@Builder
private Review(User sender, User receiver, Project project, ReviewRating rating) {
validateUsers(sender, receiver);
this.sender = sender;
this.receiver = receiver;
this.project = validateProject(project);
this.rating = rating;
}

private void validateUsers(User sender, User receiver) {
if (sender == null || receiver == null) {
throw new ReviewException(ErrorCode400.REVIEW_SENDER_OR_RECEIVER_NOT_FOUND);
}
if (sender.getId().equals(receiver.getId())) {
throw new ReviewException(ErrorCode400.REVIEW_USER_DUPLICATED);
}
}

private Project validateProject(Project project) {
if (project == null) {
throw new ReviewException(ErrorCode400.REVIEW_PROJECT_NOT_NULL);
}
return project;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.oeid.mogakgo.domain.review.domain.enums;

import lombok.Getter;

@Getter
public enum ReviewRating {
ONE(-2),
TWO(-1),
THREE(1),
FOUR(2),
FIVE(3);

private final int value;

ReviewRating(int value) {
this.value = value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.oeid.mogakgo.domain.review.exception;

import io.oeid.mogakgo.exception.code.ErrorCode;
import io.oeid.mogakgo.exception.exception_class.CustomException;

public class ReviewException extends CustomException {

public ReviewException(ErrorCode errorCode) {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.oeid.mogakgo.domain.review.infrastructure;

import io.oeid.mogakgo.domain.review.domain.Review;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

@Repository
public interface ReviewJpaRepository extends JpaRepository<Review, Long> {

@Query("select r from Review r where r.sender.id = ?1 and r.receiver.id = ?2 and r.project.id = ?3")
Optional<Review> findReviewByProjectData(Long id, Long id1, Long id2);
}
27 changes: 17 additions & 10 deletions src/main/java/io/oeid/mogakgo/domain/user/domain/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import io.oeid.mogakgo.domain.achievement.domain.Achievement;
import io.oeid.mogakgo.domain.geo.domain.enums.Region;
import io.oeid.mogakgo.domain.review.domain.enums.ReviewRating;
import io.oeid.mogakgo.domain.user.domain.enums.Role;
import io.oeid.mogakgo.domain.user.exception.UserException;
import io.oeid.mogakgo.exception.code.ErrorCode400;
Expand Down Expand Up @@ -43,6 +44,7 @@ public class User {

private static final int MAX_TAG_SIZE = 3;
private static final int MAX_AVAILABLE_LIKE_COUNT = 10;
private static final double JANDI_WEIGHT = 2.5;

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Expand Down Expand Up @@ -111,19 +113,21 @@ public class User {
@JoinColumn(name = "achievement_id")
private Achievement achievement;

private User(Long githubPk, String githubId, String avatarUrl, String githubUrl, String repositoryUrl) {
private User(Long githubPk, String githubId, String avatarUrl, String githubUrl,
String repositoryUrl) {
this.githubPk = githubPk;
this.username = githubId;
this.githubId = githubId;
this.avatarUrl = avatarUrl;
this.githubUrl = githubUrl;
this.repositoryUrl = repositoryUrl;
this.role = Role.ROLE_USER;
this.jandiRate = 0d;
this.jandiRate = 10d;
this.signupYn = false;
}

public static User of(long githubPk, String username, String avatarUrl, String githubUrl, String repositoryUrl) {
public static User of(long githubPk, String username, String avatarUrl, String githubUrl,
String repositoryUrl) {
return new User(githubPk, username, avatarUrl, githubUrl, repositoryUrl);
}

Expand All @@ -145,7 +149,8 @@ public Collection<GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority(role.name()));
}

public void updateGithubInfo(String githubId, String avatarUrl, String githubUrl, String repositoryUrl) {
public void updateGithubInfo(String githubId, String avatarUrl, String githubUrl,
String repositoryUrl) {
this.githubId = githubId;
this.avatarUrl = avatarUrl;
this.githubUrl = githubUrl;
Expand Down Expand Up @@ -200,17 +205,21 @@ public void updateRegion(Region region) {
}
}

public void updateUserInfos(String username, String avatarUrl, String bio, Achievement achievement) {
public void updateUserInfos(String username, String avatarUrl, String bio,
Achievement achievement) {
updateUsername(username);
this.avatarUrl = verifyAvatarUrl(avatarUrl);
this.bio = bio;
this.achievement = achievement;
deleteAllWantJobTags();
}

//TODO : 추후 구현 필요
public void decreaseJandiRate() {
return;
public void updateJandiRateByReview(ReviewRating rating, double time) {
this.jandiRate += rating.getValue() * time * JANDI_WEIGHT;
}

public void updateJandiRateByCancel() {
this.jandiRate += -5 * JANDI_WEIGHT;
}

private boolean validateAvailableRegionUpdate(Region region) {
Expand All @@ -225,6 +234,4 @@ private String verifyAvatarUrl(String avatarUrl) {
}




}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public enum ErrorCode400 implements ErrorCode {
CHAT_ROOM_CLOSED("E110101", "채팅방이 종료되어 채팅을 할 수 없습니다."),
CHAT_ROOM_USER_CANNOT_DUPLICATE("E110102", "채팅방에 중복된 유저가 있습니다."),
CHAT_ROOM_USER_NOT_CONTAINS("E110103", "채팅방에 해당 유저가 없습니다."),

REVIEW_SENDER_OR_RECEIVER_NOT_FOUND("E120101", "리뷰를 작성하기 위한 유저 정보가 존재하지 않습니다."),
REVIEW_USER_DUPLICATED("E120102", "자신에 대한 리뷰는 작성할 수 없습니다."),
REVIEW_PROJECT_NOT_NULL("E120103", "리뷰를 작성하기 위한 프로젝트 정보가 존재하지 않습니다."),
REVIEW_ALREADY_EXISTS("E120104", "이미 작성된 리뷰가 존재합니다."),
;

private final HttpStatus httpStatus = HttpStatus.BAD_REQUEST;
Expand Down
Loading