Skip to content
Closed
27 changes: 0 additions & 27 deletions src/main/java/com/somemore/domains/Review.java

This file was deleted.

25 changes: 0 additions & 25 deletions src/main/java/com/somemore/domains/VolunteerManagement.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ public enum ExceptionMessage {
EMPTY_FILE("파일이 존재하지 않습니다."),
INSTANTIATION_NOT_ALLOWED("인스턴스화 할 수 없는 클래스 입니다."),
CANNOT_CANCEL_DELETED_INTEREST_CENTER("이미 삭제된 관심 기관은 취소할 수 없습니다."),
DUPLICATE_INTEREST_CENTER("이미 관심 표시한 기관입니다.")
DUPLICATE_INTEREST_CENTER("이미 관심 표시한 기관입니다."),
NOT_EXISTS_VOLUNTEER_APPLY("존재하지 않는 봉사 활동 지원입니다."),
REVIEW_ALREADY_EXISTS("이미 작성한 리뷰가 존재합니다."),
REVIEW_RESTRICTED_TO_ATTENDED("리뷰는 참석한 봉사에 한해서만 작성할 수 있습니다.")
;

private final String message;
Expand Down
53 changes: 53 additions & 0 deletions src/main/java/com/somemore/review/domain/Review.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.somemore.review.domain;

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

import com.somemore.global.common.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Lob;
import jakarta.persistence.Table;
import java.util.UUID;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

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

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

@Column(name = "volunteer_apply_id", nullable = false)
private Long volunteerApplyId;

@Column(name = "volunteer_id", nullable = false, length = 16)
private UUID volunteerId;

@Column(name = "title", nullable = false)
private String title;

@Lob
@Column(name = "content", nullable = false)
private String content;

@Column(name = "img_url", nullable = false)
private String imgUrl;

@Builder
public Review(Long volunteerApplyId, UUID volunteerId, String title,
String content, String imgUrl) {
this.volunteerApplyId = volunteerApplyId;
this.volunteerId = volunteerId;
this.title = title;
this.content = content;
this.imgUrl = imgUrl;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.somemore.review.dto.request;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.somemore.review.domain.Review;
import com.somemore.volunteerapply.domain.VolunteerApply;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.UUID;
import lombok.Builder;

@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@Builder
public record ReviewCreateRequestDto(
@Schema(description = "봉사 모집글 아이디", example = "1")
@NotNull(message = "봉사 모집글 아이디는 필수 값입니다.")
Long recruitBoardId,
@Schema(description = "리뷰 제목", example = "내 인생 최고의 봉사 활동")
@NotBlank(message = "리뷰 제목은 필수 값입니다.")
String title,
@Schema(description = "리뷰 내용", example = "담당자님도 정말 친절하였고 정말 보람찬 봉사였어요 더보기..<br>")
@NotBlank(message = "리뷰 내용은 필수 값입니다.")
String content
) {

public Review toEntity(VolunteerApply apply, UUID volunteerId, String imgUrl) {
return Review.builder()
.volunteerApplyId(apply.getId())
.volunteerId(volunteerId)
.title(title)
.content(content)
.imgUrl(imgUrl)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.somemore.review.repository;

import com.somemore.review.domain.Review;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface ReviewJpaRepository extends JpaRepository<Review, Long> {

Optional<Review> findByIdAndDeletedFalse(Long id);

@Query("SELECT COUNT(r) > 0 FROM Review r WHERE r.volunteerApplyId = :volunteerId AND r.deleted = false")
boolean existsByVolunteerApplyId(Long volunteerId);

}
13 changes: 13 additions & 0 deletions src/main/java/com/somemore/review/repository/ReviewRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.somemore.review.repository;

import com.somemore.review.domain.Review;
import java.util.Optional;

public interface ReviewRepository {

Review save(Review review);

Optional<Review> findById(Long id);

boolean existsByVolunteerApplyId(Long volunteerApplyId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.somemore.review.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import com.somemore.review.domain.Review;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

@RequiredArgsConstructor
@Repository
public class ReviewRepositoryImpl implements ReviewRepository {

private final ReviewJpaRepository reviewJpaRepository;
private final JPAQueryFactory queryFactory;

@Override
public Review save(Review review) {
return reviewJpaRepository.save(review);
}

@Override
public Optional<Review> findById(Long id) {
return reviewJpaRepository.findByIdAndDeletedFalse(id);
}

@Override
public boolean existsByVolunteerApplyId(Long volunteerApplyId) {
return reviewJpaRepository.existsByVolunteerApplyId(volunteerApplyId);
}
}
52 changes: 52 additions & 0 deletions src/main/java/com/somemore/review/service/CreateReviewService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.somemore.review.service;

import static com.somemore.global.exception.ExceptionMessage.REVIEW_ALREADY_EXISTS;
import static com.somemore.global.exception.ExceptionMessage.REVIEW_RESTRICTED_TO_ATTENDED;

import com.somemore.global.exception.BadRequestException;
import com.somemore.review.domain.Review;
import com.somemore.review.dto.request.ReviewCreateRequestDto;
import com.somemore.review.repository.ReviewRepository;
import com.somemore.review.usecase.CreateReviewUseCase;
import com.somemore.volunteerapply.domain.VolunteerApply;
import com.somemore.volunteerapply.usecase.VolunteerApplyQueryUseCase;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@RequiredArgsConstructor
@Transactional
@Service
public class CreateReviewService implements CreateReviewUseCase {

private final ReviewRepository reviewRepository;
private final VolunteerApplyQueryUseCase volunteerApplyQueryUseCase;

@Override
public Long createReview(ReviewCreateRequestDto requestDto, UUID volunteerId, String imgUrl) {
VolunteerApply apply = getVolunteerApply(requestDto.recruitBoardId(), volunteerId);
validateReviewNotExist(apply);
validateActivityCompletion(apply);

Review review = requestDto.toEntity(apply, volunteerId, imgUrl);
return reviewRepository.save(review).getId();
}

private VolunteerApply getVolunteerApply(Long recruitBoardId, UUID volunteerId) {
return volunteerApplyQueryUseCase.getByRecruitIdAndVolunteerId(recruitBoardId, volunteerId);
}

private void validateReviewNotExist(VolunteerApply apply) {
if (reviewRepository.existsByVolunteerApplyId(apply.getId())) {
throw new BadRequestException(REVIEW_ALREADY_EXISTS.getMessage());
}
}

private void validateActivityCompletion(VolunteerApply apply) {
if (apply.isVolunteerActivityCompleted()) {
return;
}
throw new BadRequestException(REVIEW_RESTRICTED_TO_ATTENDED.getMessage());
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/somemore/review/usecase/CreateReviewUseCase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.somemore.review.usecase;

import com.somemore.review.dto.request.ReviewCreateRequestDto;
import java.util.UUID;

public interface CreateReviewUseCase {

Long createReview(ReviewCreateRequestDto requestDto, UUID volunteerId, String imgUrl);


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.somemore.volunteerapply.domain;

public enum ApplyStatus {
WAITING,
APPROVED,
REJECTED,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.somemore.volunteerapply.domain;

import static com.somemore.volunteerapply.domain.ApplyStatus.APPROVED;

import com.somemore.global.common.BaseEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import java.util.UUID;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@Table(name = "volunteer_apply")
public class VolunteerApply extends BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "volunteer_id", nullable = false, columnDefinition = "BINARY(16)")
private UUID volunteerId;

@Column(name = "recruit_board_id", nullable = false)
private Long recruitBoardId;

@Enumerated(EnumType.STRING)
@Column(name = "status", nullable = false, length = 20)
private ApplyStatus status = ApplyStatus.WAITING;

@Column(name = "attended", nullable = false)
private Boolean attended = false;

@Builder
public VolunteerApply(UUID volunteerId, Long recruitBoardId, ApplyStatus status,
Boolean attended) {
this.volunteerId = volunteerId;
this.recruitBoardId = recruitBoardId;
this.status = status;
this.attended = attended;
}

public void changeStatus(ApplyStatus status) {
if (isVolunteerActivityCompleted()) {
throw new IllegalStateException("이미 완료된 봉사활동에 대해서는 변경이 불가능합니다.");
}
this.status = status;
}

public void changeAttended(Boolean attended) {
if (this.status != APPROVED) {
throw new IllegalStateException("승인되지 않은 봉사 지원은 참석 여부를 변경할 수 없습니다.");
}
this.attended = attended;
}

public boolean isVolunteerActivityCompleted() {
return this.attended && this.status == APPROVED;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.somemore.volunteerapply.repository;

import com.somemore.volunteerapply.domain.VolunteerApply;
import org.springframework.data.jpa.repository.JpaRepository;

public interface VolunteerApplyJpaRepository extends JpaRepository<VolunteerApply, Long> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.somemore.volunteerapply.repository;

import com.somemore.volunteerapply.domain.VolunteerApply;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface VolunteerApplyRepository {

VolunteerApply save(VolunteerApply volunteerApply);
Optional<VolunteerApply> findById(Long id);
List<UUID> findVolunteerIdsByRecruitIds(List<Long> recruitIds);
Page<VolunteerApply> findAllByRecruitId(Long recruitId, Pageable pageable);
Optional<VolunteerApply> findByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId);

}
Loading