From 9b06461c11e2eb1cecce0efe90e36af2a16719dd Mon Sep 17 00:00:00 2001 From: goodispotato Date: Thu, 16 Apr 2026 11:59:28 +0900 Subject: [PATCH 01/12] =?UTF-8?q?=EC=9E=91=EC=97=85=20=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 10 ++++ .idea/JECT5-4th-Server.iml | 9 +++ .idea/compiler.xml | 21 +++++++ .idea/copilot.data.migration.ask2agent.xml | 6 ++ .idea/gradle.xml | 17 ++++++ .idea/misc.xml | 7 +++ .idea/modules.xml | 9 +++ .idea/modules/sossbar.main.iml | 8 +++ .idea/vcs.xml | 6 ++ .../review/controller/ReviewController.java | 22 ++++++++ .../dto/request/ReviewCreateReqDto.java | 12 ++++ .../review/dto/request/ReviewReqDto.java | 53 ++++++++++++++++++ .../review/dto/request/SpectrumReqDto.java | 12 ++++ .../review/dto/response/ReviewResDto.java | 17 ++++++ .../com/sossbar/review/entity/Review.java | 52 +++++++++++++++++ .../sossbar/review/entity/ReviewSpectrum.java | 42 ++++++++++++++ .../com/sossbar/review/entity/ReviewTag.java | 39 +++++++++++++ .../review/repository/ReviewRepository.java | 9 +++ .../repository/ReviewSpectrumRepository.java | 9 +++ .../repository/ReviewTagRepository.java | 9 +++ .../sossbar/review/service/ReviewService.java | 56 +++++++++++++++++++ .../dto/response/SpectrumAxisResDto.java | 9 +++ .../spectrumaxis/entity/SpectrumAxis.java | 33 +++++++++++ .../repository/SpectrumAxisRepository.java | 7 +++ .../sossbar/tag/dto/response/TagResDto.java | 7 +++ .../main/java/com/sossbar/tag/entity/Tag.java | 27 +++++++++ .../sossbar/tag/repository/TagRepository.java | 7 +++ SossBar/src/main/resources/application.yml | 1 + SossBar/src/main/resources/data.sql | 26 +++++++++ 29 files changed, 542 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/JECT5-4th-Server.iml create mode 100644 .idea/compiler.xml create mode 100644 .idea/copilot.data.migration.ask2agent.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/modules/sossbar.main.iml create mode 100644 .idea/vcs.xml create mode 100644 SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java create mode 100644 SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java create mode 100644 SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java create mode 100644 SossBar/src/main/java/com/sossbar/review/dto/request/SpectrumReqDto.java create mode 100644 SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java create mode 100644 SossBar/src/main/java/com/sossbar/review/entity/Review.java create mode 100644 SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java create mode 100644 SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java create mode 100644 SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java create mode 100644 SossBar/src/main/java/com/sossbar/review/repository/ReviewSpectrumRepository.java create mode 100644 SossBar/src/main/java/com/sossbar/review/repository/ReviewTagRepository.java create mode 100644 SossBar/src/main/java/com/sossbar/review/service/ReviewService.java create mode 100644 SossBar/src/main/java/com/sossbar/spectrumaxis/dto/response/SpectrumAxisResDto.java create mode 100644 SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java create mode 100644 SossBar/src/main/java/com/sossbar/spectrumaxis/repository/SpectrumAxisRepository.java create mode 100644 SossBar/src/main/java/com/sossbar/tag/dto/response/TagResDto.java create mode 100644 SossBar/src/main/java/com/sossbar/tag/entity/Tag.java create mode 100644 SossBar/src/main/java/com/sossbar/tag/repository/TagRepository.java create mode 100644 SossBar/src/main/resources/data.sql diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..ab1f416 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Ignored default folder with query files +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/JECT5-4th-Server.iml b/.idea/JECT5-4th-Server.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/JECT5-4th-Server.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..0a1ca4a --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/copilot.data.migration.ask2agent.xml b/.idea/copilot.data.migration.ask2agent.xml new file mode 100644 index 0000000..1f2ea11 --- /dev/null +++ b/.idea/copilot.data.migration.ask2agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..3990a2a --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,17 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..a94cba3 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..de50156 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/sossbar.main.iml b/.idea/modules/sossbar.main.iml new file mode 100644 index 0000000..dd2a079 --- /dev/null +++ b/.idea/modules/sossbar.main.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java new file mode 100644 index 0000000..8c13b6c --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java @@ -0,0 +1,22 @@ +package com.sossbar.review.controller; + +import com.sossbar.global.common.code.SuccessCode; +import com.sossbar.global.common.template.ApiResTemplate; +import com.sossbar.review.dto.request.ReviewCreateReqDto; +import com.sossbar.review.service.ReviewService; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ReviewController { + + private ReviewService reviewService; + + // 리뷰 작성 + @PostMapping("api/v1/reviews") + public ApiResTemplate createReview(@RequestBody ReviewCreateReqDto reviewCreateReqDto) { + reviewService.createReview(reviewCreateReqDto); + return ApiResTemplate.successWithNoContent(SuccessCode.SUCCESS); + } +} \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java new file mode 100644 index 0000000..1543d05 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java @@ -0,0 +1,12 @@ +package com.sossbar.review.dto.request; + +import lombok.Getter; + +import java.util.List; + +// 통합 DTO +@Getter +public class ReviewCreateReqDto { + ReviewReqDto reviewReqDto; + List spectrumReqDtos; +} diff --git a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java new file mode 100644 index 0000000..80326d5 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java @@ -0,0 +1,53 @@ +package com.sossbar.review.dto.request; + +import com.sossbar.review.entity.Review; +import com.sossbar.user.repository.UserRepository; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.Size; + +import java.util.List; + + +// 리뷰 + 태그 DTO +public record ReviewReqDto( + @NotBlank + @Size(min = 10) + String positiveFeedback, + + @NotBlank + @Size(min = 10) + String negativeFeedback, + + @NotNull + @Positive + Long reviewerId, + + @NotNull + @Positive + Long revieweeId, + + @NotNull + @Positive + Long projectId, + + List tagIds +) { + private UserRepository userRepository; + private ProjectRepository projectRepository; + + public Review toEntity() { + return Review.builder() + .positiveFeedback(positiveFeedback) + .negativeFeedback(negativeFeedback) + .reviewer(userRepository.findById(reviewerId)) + .reviewee(userRepository.findById(revieweeId)) + .project(projectRepository.findById(projectId)) + .build(); + } + + public List getTagIds() { + return tagIds; + } +} \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/dto/request/SpectrumReqDto.java b/SossBar/src/main/java/com/sossbar/review/dto/request/SpectrumReqDto.java new file mode 100644 index 0000000..088a53f --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/request/SpectrumReqDto.java @@ -0,0 +1,12 @@ +package com.sossbar.review.dto.request; + + +import lombok.Getter; + + +// 스펙트럼 항목 하나 당 DTO +@Getter +public class SpectrumReqDto { + Long spectrumAxisId; + Integer spectrumStrength; +} diff --git a/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java new file mode 100644 index 0000000..43a1d44 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java @@ -0,0 +1,17 @@ +package com.sossbar.review.dto.response; + +import com.sossbar.spectrumaxis.dto.response.SpectrumAxisResDto; +import com.sossbar.tag.dto.response.TagResDto; + +import java.util.List; + +// 아마 마이페이지에서 리뷰 조회할 때 필요할 듯 +public record ReviewResDto ( + String positiveFeedback, + String negativeFeedback, + Long revieweeId, + Long projectId, + List tags, + List spectrumAxes +) { +} diff --git a/SossBar/src/main/java/com/sossbar/review/entity/Review.java b/SossBar/src/main/java/com/sossbar/review/entity/Review.java new file mode 100644 index 0000000..f6c2059 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/entity/Review.java @@ -0,0 +1,52 @@ +package com.sossbar.review.entity; + +import com.sossbar.user.entity.User; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Review { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long reviewId; + + @Column + private String positiveFeedback; + + @Column + private String negativeFeedback; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "reviewer_id", insertable = false, updatable = false) + private User reviewer; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "reviewee_id", insertable = false, updatable = false) + private User reviewee; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "project_id", insertable = false, updatable = false) + private Project project; + + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, orphanRemoval = true) + private List reviewTags = new ArrayList<>(); + + @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, orphanRemoval = true) + private List reviewSpectrums = new ArrayList<>(); + + @Builder + public Review(String positiveFeedback, String negativeFeedback, User reviewer, User reviewee, Project project) { + this.positiveFeedback = positiveFeedback; + this.negativeFeedback = negativeFeedback; + this.reviewer = reviewer; + this.reviewee = reviewee; + this.project = project; + } +} \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java b/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java new file mode 100644 index 0000000..2ca5cf6 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java @@ -0,0 +1,42 @@ +package com.sossbar.review.entity; + +import com.sossbar.spectrumaxis.entity.SpectrumAxis; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ReviewSpectrum { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long reviewSpectrumId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "spectrum_axis_id") + private SpectrumAxis spectrumAxis; + + @Column + private Integer strength; + + public void setReview(Review review) { + this.review = review; + } + + public void setSpectrumAxis(SpectrumAxis spectrumAxis) { + this.spectrumAxis = spectrumAxis; + } + + @Builder + public ReviewSpectrum(Review review, SpectrumAxis spectrumAxis, Integer strength) { + this.review = review; + this.spectrumAxis = spectrumAxis; + this.strength = strength; + } +} diff --git a/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java new file mode 100644 index 0000000..345e6c4 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java @@ -0,0 +1,39 @@ +package com.sossbar.review.entity; + +import com.sossbar.tag.entity.Tag; +import com.sossbar.user.entity.User; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class ReviewTag { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long reviewTagId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id", insertable = false, updatable = false) + private Review review; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "tag_id", insertable = false, updatable = false) + private Tag tag; + + public void setReview(Review review) { + this.review = review; + } + + public void setTag(Tag tag) { + this.tag = tag; + } + + @Builder + public ReviewTag(Review review, Tag tag) { + this.review = review; + this.tag = tag; + } +} \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java b/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java new file mode 100644 index 0000000..3e5420b --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java @@ -0,0 +1,9 @@ +package com.sossbar.review.repository; + +import com.sossbar.review.entity.Review; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReviewRepository extends JpaRepository { +} diff --git a/SossBar/src/main/java/com/sossbar/review/repository/ReviewSpectrumRepository.java b/SossBar/src/main/java/com/sossbar/review/repository/ReviewSpectrumRepository.java new file mode 100644 index 0000000..d6961f8 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/repository/ReviewSpectrumRepository.java @@ -0,0 +1,9 @@ +package com.sossbar.review.repository; + +import com.sossbar.review.entity.ReviewSpectrum; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReviewSpectrumRepository extends JpaRepository { +} diff --git a/SossBar/src/main/java/com/sossbar/review/repository/ReviewTagRepository.java b/SossBar/src/main/java/com/sossbar/review/repository/ReviewTagRepository.java new file mode 100644 index 0000000..3b183c3 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/repository/ReviewTagRepository.java @@ -0,0 +1,9 @@ +package com.sossbar.review.repository; + +import com.sossbar.review.entity.ReviewTag; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ReviewTagRepository extends JpaRepository { +} diff --git a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java new file mode 100644 index 0000000..c87276e --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -0,0 +1,56 @@ +package com.sossbar.review.service; + +import com.sossbar.review.dto.request.ReviewCreateReqDto; +import com.sossbar.review.dto.request.ReviewReqDto; +import com.sossbar.review.dto.request.SpectrumReqDto; +import com.sossbar.review.entity.Review; +import com.sossbar.review.entity.ReviewSpectrum; +import com.sossbar.review.entity.ReviewTag; +import com.sossbar.review.repository.ReviewRepository; +import com.sossbar.review.repository.ReviewSpectrumRepository; +import com.sossbar.review.repository.ReviewTagRepository; +import com.sossbar.spectrumaxis.entity.SpectrumAxis; +import com.sossbar.spectrumaxis.repository.SpectrumAxisRepository; +import com.sossbar.tag.repository.TagRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class ReviewService { + + private ReviewRepository reviewRepository; + private TagRepository tagRepository; + private SpectrumAxisRepository spectrumAxisRepository; + private ReviewTagRepository reviewTagRepository; + private ReviewSpectrumRepository reviewSpectrumRepository; + + @Transactional + public void createReview(ReviewCreateReqDto reviewCreateReqDto) { + Review savedReview = reviewRepository.save(reviewCreateReqDto.getReviewReqDto().toEntity()); + + for (Long tagId : reviewCreateReqDto.getReviewReqDto().getTagIds()) { + reviewTagRepository.save(ReviewTag.builder() + .review(savedReview) + .tag(tagRepository.findById(tagId).orElseThrow(() -> new RuntimeException("다음과 같은 태그는 존재하지 않습니다: " + tagId))) + .build()); + } + + // 각 스펙트럼 축 당 저장하기... + List reviewSpectrums = reviewCreateReqDto.getSpectrumReqDtos().stream() + .map(spectrumReqDto -> { + SpectrumAxis spectrumAxis = spectrumAxisRepository.findById(spectrumReqDto.getSpectrumAxisId()).orElseThrow(() -> new RuntimeException("다음과 같은 스펙트럼 축은 존재하지 않습니다: " + spectrumReqDto.getSpectrumAxisId())); + + return ReviewSpectrum.builder() + .review(savedReview) + .spectrumAxis(spectrumAxis) + .strength(spectrumReqDto.getSpectrumStrength()) + .build(); + }) + .collect(Collectors.toList()); + + reviewSpectrumRepository.saveAll(reviewSpectrums); + } +} diff --git a/SossBar/src/main/java/com/sossbar/spectrumaxis/dto/response/SpectrumAxisResDto.java b/SossBar/src/main/java/com/sossbar/spectrumaxis/dto/response/SpectrumAxisResDto.java new file mode 100644 index 0000000..7181647 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/spectrumaxis/dto/response/SpectrumAxisResDto.java @@ -0,0 +1,9 @@ +package com.sossbar.spectrumaxis.dto.response; + +public record SpectrumAxisResDto( + Long spectrumAxisId, + String spectrumAxisName, + String leftLabel, + String rightLabel +) { +} diff --git a/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java b/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java new file mode 100644 index 0000000..b9399b5 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java @@ -0,0 +1,33 @@ +package com.sossbar.spectrumaxis.entity; + +import com.sossbar.review.entity.ReviewSpectrum; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Setter(AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class SpectrumAxis { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long spectrumAxisId; + + @Column + private String axisName; + + @Column + private String leftLabel; + + @Column + private String rightLabel; + + @OneToMany(mappedBy = "spectrumAxis", cascade = CascadeType.ALL, orphanRemoval = true) + private List reviewSpectrums = new ArrayList<>(); + +} \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/spectrumaxis/repository/SpectrumAxisRepository.java b/SossBar/src/main/java/com/sossbar/spectrumaxis/repository/SpectrumAxisRepository.java new file mode 100644 index 0000000..544dca1 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/spectrumaxis/repository/SpectrumAxisRepository.java @@ -0,0 +1,7 @@ +package com.sossbar.spectrumaxis.repository; + +import com.sossbar.spectrumaxis.entity.SpectrumAxis; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface SpectrumAxisRepository extends JpaRepository { +} diff --git a/SossBar/src/main/java/com/sossbar/tag/dto/response/TagResDto.java b/SossBar/src/main/java/com/sossbar/tag/dto/response/TagResDto.java new file mode 100644 index 0000000..416e10e --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/tag/dto/response/TagResDto.java @@ -0,0 +1,7 @@ +package com.sossbar.tag.dto.response; + +public record TagResDto( + Long tagId, + String tagName +) { +} diff --git a/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java b/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java new file mode 100644 index 0000000..736ae76 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java @@ -0,0 +1,27 @@ +package com.sossbar.tag.entity; + +import com.sossbar.review.entity.ReviewTag; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Setter(AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Tag { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long tagId; + + @Column + private String tagName; + + @OneToMany(mappedBy = "tag", cascade = CascadeType.ALL, orphanRemoval = true) + private List reviewTags = new ArrayList<>(); + +} diff --git a/SossBar/src/main/java/com/sossbar/tag/repository/TagRepository.java b/SossBar/src/main/java/com/sossbar/tag/repository/TagRepository.java new file mode 100644 index 0000000..ef5b083 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/tag/repository/TagRepository.java @@ -0,0 +1,7 @@ +package com.sossbar.tag.repository; + +import com.sossbar.tag.entity.Tag; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TagRepository extends JpaRepository { +} diff --git a/SossBar/src/main/resources/application.yml b/SossBar/src/main/resources/application.yml index 4711e28..3aac5cd 100644 --- a/SossBar/src/main/resources/application.yml +++ b/SossBar/src/main/resources/application.yml @@ -18,6 +18,7 @@ spring: hibernate: format_sql: true open-in-view: false + defer-datasource-initialization: true // 이거 추가한 거 잊지말기! logging: level: diff --git a/SossBar/src/main/resources/data.sql b/SossBar/src/main/resources/data.sql new file mode 100644 index 0000000..fd18049 --- /dev/null +++ b/SossBar/src/main/resources/data.sql @@ -0,0 +1,26 @@ +INSERT INTO tag(tag_name) VALUES ('약속을 잘 지켜요'); +INSERT INTO tag(tag_name) VALUES ('적극적이에요'); +INSERT INTO tag(tag_name) VALUES ('꼼꼼해요'); +INSERT INTO tag(tag_name) VALUES ('응답이 빨라요'); +INSERT INTO tag(tag_name) VALUES ('피드백을 잘 수용해요'); +INSERT INTO tag(tag_name) VALUES ('문서 정리를 잘해요'); +INSERT INTO tag(tag_name) VALUES ('아이디어가 많아요'); +INSERT INTO tag(tag_name) VALUES ('마감을 잘 지켜요'); +INSERT INTO tag(tag_name) VALUES ('팀 분위기를 좋게 만들어요'); +INSERT INTO tag(tag_name) VALUES ('시간 조율을 잘해요'); +INSERT INTO tag(tag_name) VALUES ('실행력이 좋아요'); +INSERT INTO tag(tag_name) VALUES ('작업 속도가 빨라요'); +INSERT INTO tag(tag_name) VALUES ('팀원들을 잘 도와줘요'); +INSERT INTO tag(tag_name) VALUES ('센스가 좋아요'); +INSERT INTO tag(tag_name) VALUES ('문제 해결을 잘 해요'); +INSERT INTO tag(tag_name) VALUES ('일정 관리를 잘 해요'); +INSERT INTO tag(tag_name) VALUES ('끈기있어요'); +INSERT INTO tag(tag_name) VALUES ('고마움을 잘 표현해요'); +INSERT INTO tag(tag_name) VALUES ('먼저 친근하게 다가와요'); +INSERT INTO tag(tag_name) VALUES ('모르는 것을 숨기지 않고 물어봐요'); + +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('1번 항목', '원칙 준수', '혁신 제안'); +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('2번 항목', '유연한 대처', '철저한 계획'); +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('3번 항목', '묵묵한 조력', '당당한 리드'); +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('4번 항목', '냉정한 과업', '따뜻한 관계'); +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('5번 항목', '침착한 대응', '빈틈없는 대비'); \ No newline at end of file From c8991d11369c56e36aa5e8fc9c7c6ec3bb0ee54f Mon Sep 17 00:00:00 2001 From: goodispotato Date: Thu, 16 Apr 2026 20:04:53 +0900 Subject: [PATCH 02/12] =?UTF-8?q?Feat/#5=20-=20=ED=9B=84=EA=B8=B0=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/controller/ReviewController.java | 18 +++++-- .../review/dto/request/ReviewReqDto.java | 38 +++++--------- .../review/dto/response/ReviewResDto.java | 1 - .../com/sossbar/review/entity/Review.java | 7 +-- .../sossbar/review/entity/ReviewSpectrum.java | 9 ++-- .../com/sossbar/review/entity/ReviewTag.java | 12 ++--- .../review/repository/ReviewRepository.java | 4 ++ .../sossbar/review/service/ReviewService.java | 52 ++++++++++++++----- SossBar/src/main/resources/application.yml | 7 ++- SossBar/src/main/resources/data.sql | 9 ++-- 10 files changed, 93 insertions(+), 64 deletions(-) diff --git a/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java index 8c13b6c..cc2bf95 100644 --- a/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java +++ b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java @@ -4,19 +4,29 @@ import com.sossbar.global.common.template.ApiResTemplate; import com.sossbar.review.dto.request.ReviewCreateReqDto; import com.sossbar.review.service.ReviewService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import java.security.Principal; + +@Tag(name = "Review API", description = "후기 관련 API") @RestController +@RequiredArgsConstructor public class ReviewController { - private ReviewService reviewService; + private final ReviewService reviewService; - // 리뷰 작성 + @Operation(summary = "후기 작성", description = "사용자는 로그인 후 다른 사용자에 대한 후기를 남길 수 있습니다.") @PostMapping("api/v1/reviews") - public ApiResTemplate createReview(@RequestBody ReviewCreateReqDto reviewCreateReqDto) { - reviewService.createReview(reviewCreateReqDto); + public ApiResTemplate createReview( + @RequestBody ReviewCreateReqDto reviewCreateReqDto, + Principal principal + ) { + reviewService.createReview(principal, reviewCreateReqDto); return ApiResTemplate.successWithNoContent(SuccessCode.SUCCESS); } } \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java index 80326d5..c7be515 100644 --- a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java +++ b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java @@ -1,53 +1,43 @@ package com.sossbar.review.dto.request; +import com.sossbar.projects.entity.Project; import com.sossbar.review.entity.Review; -import com.sossbar.user.repository.UserRepository; +import com.sossbar.user.entity.User; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Positive; import jakarta.validation.constraints.Size; +import lombok.Getter; import java.util.List; - // 리뷰 + 태그 DTO -public record ReviewReqDto( +@Getter +public class ReviewReqDto { @NotBlank @Size(min = 10) - String positiveFeedback, + private String positiveFeedback; - @NotBlank @Size(min = 10) - String negativeFeedback, + private String negativeFeedback; @NotNull @Positive - Long reviewerId, + private Long revieweeId; @NotNull @Positive - Long revieweeId, + private Long projectId; - @NotNull - @Positive - Long projectId, + private List tagIds; - List tagIds -) { - private UserRepository userRepository; - private ProjectRepository projectRepository; - - public Review toEntity() { + public Review toEntity(User reviewer, User reviewee, Project project) { return Review.builder() .positiveFeedback(positiveFeedback) .negativeFeedback(negativeFeedback) - .reviewer(userRepository.findById(reviewerId)) - .reviewee(userRepository.findById(revieweeId)) - .project(projectRepository.findById(projectId)) + .reviewer(reviewer) + .reviewee(reviewee) + .project(project) .build(); } - - public List getTagIds() { - return tagIds; - } } \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java index 43a1d44..7b4ac12 100644 --- a/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java +++ b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java @@ -5,7 +5,6 @@ import java.util.List; -// 아마 마이페이지에서 리뷰 조회할 때 필요할 듯 public record ReviewResDto ( String positiveFeedback, String negativeFeedback, diff --git a/SossBar/src/main/java/com/sossbar/review/entity/Review.java b/SossBar/src/main/java/com/sossbar/review/entity/Review.java index f6c2059..e95c633 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/Review.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/Review.java @@ -1,5 +1,6 @@ package com.sossbar.review.entity; +import com.sossbar.projects.entity.Project; import com.sossbar.user.entity.User; import jakarta.persistence.*; import lombok.*; @@ -24,15 +25,15 @@ public class Review { private String negativeFeedback; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "reviewer_id", insertable = false, updatable = false) + @JoinColumn(name = "reviewer_id") private User reviewer; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "reviewee_id", insertable = false, updatable = false) + @JoinColumn(name = "reviewee_id") private User reviewee; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "project_id", insertable = false, updatable = false) + @JoinColumn(name = "project_id") private Project project; @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, orphanRemoval = true) diff --git a/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java b/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java index 2ca5cf6..15b0cae 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java @@ -3,11 +3,14 @@ import com.sossbar.spectrumaxis.entity.SpectrumAxis; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.NoArgsConstructor; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder public class ReviewSpectrum { @Id @@ -33,10 +36,4 @@ public void setSpectrumAxis(SpectrumAxis spectrumAxis) { this.spectrumAxis = spectrumAxis; } - @Builder - public ReviewSpectrum(Review review, SpectrumAxis spectrumAxis, Integer strength) { - this.review = review; - this.spectrumAxis = spectrumAxis; - this.strength = strength; - } } diff --git a/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java index 345e6c4..987431d 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java @@ -4,11 +4,14 @@ import com.sossbar.user.entity.User; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.NoArgsConstructor; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder public class ReviewTag { @Id @@ -16,11 +19,11 @@ public class ReviewTag { private Long reviewTagId; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "review_id", insertable = false, updatable = false) + @JoinColumn(name = "review_id") private Review review; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "tag_id", insertable = false, updatable = false) + @JoinColumn(name = "tag_id") private Tag tag; public void setReview(Review review) { @@ -31,9 +34,4 @@ public void setTag(Tag tag) { this.tag = tag; } - @Builder - public ReviewTag(Review review, Tag tag) { - this.review = review; - this.tag = tag; - } } \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java b/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java index 3e5420b..9a1812c 100644 --- a/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java +++ b/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java @@ -1,9 +1,13 @@ package com.sossbar.review.repository; import com.sossbar.review.entity.Review; +import com.sossbar.user.entity.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface ReviewRepository extends JpaRepository { + + // 중복 리뷰 검증 + boolean existsByReviewerAndReviewee(User Reviewer, User Reviewee); } diff --git a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java index c87276e..817bacc 100644 --- a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -1,8 +1,9 @@ package com.sossbar.review.service; +import com.sossbar.projects.entity.Project; +import com.sossbar.projects.repository.ProjectRepository; import com.sossbar.review.dto.request.ReviewCreateReqDto; import com.sossbar.review.dto.request.ReviewReqDto; -import com.sossbar.review.dto.request.SpectrumReqDto; import com.sossbar.review.entity.Review; import com.sossbar.review.entity.ReviewSpectrum; import com.sossbar.review.entity.ReviewTag; @@ -12,36 +13,63 @@ import com.sossbar.spectrumaxis.entity.SpectrumAxis; import com.sossbar.spectrumaxis.repository.SpectrumAxisRepository; import com.sossbar.tag.repository.TagRepository; +import com.sossbar.user.entity.User; +import com.sossbar.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.security.Principal; import java.util.List; import java.util.stream.Collectors; @Service +@RequiredArgsConstructor public class ReviewService { - private ReviewRepository reviewRepository; - private TagRepository tagRepository; - private SpectrumAxisRepository spectrumAxisRepository; - private ReviewTagRepository reviewTagRepository; - private ReviewSpectrumRepository reviewSpectrumRepository; + private final ReviewRepository reviewRepository; + private final TagRepository tagRepository; + private final SpectrumAxisRepository spectrumAxisRepository; + private final ReviewTagRepository reviewTagRepository; + private final ReviewSpectrumRepository reviewSpectrumRepository; + private final UserRepository userRepository; + private final ProjectRepository projectRepository; @Transactional - public void createReview(ReviewCreateReqDto reviewCreateReqDto) { - Review savedReview = reviewRepository.save(reviewCreateReqDto.getReviewReqDto().toEntity()); + public void createReview(Principal principal, ReviewCreateReqDto reviewCreateReqDto) { + ReviewReqDto reviewReqDto = reviewCreateReqDto.getReviewReqDto(); - for (Long tagId : reviewCreateReqDto.getReviewReqDto().getTagIds()) { + Long reviewerIdentifier = Long.parseLong(principal.getName()); + + User reviewer = userRepository.findById(reviewerIdentifier) + .orElseThrow(() -> new RuntimeException("해당 유저는 존재하지 않습니다: " + reviewerIdentifier)); + User reviewee = userRepository.findById(reviewReqDto.getRevieweeId()) + .orElseThrow(() -> new RuntimeException("해당 유저는 존재하지 않습니다: " + reviewReqDto.getRevieweeId())); + + if (reviewRepository.existsByReviewerAndReviewee(reviewer, reviewee)) { + throw new IllegalStateException("이미 해당 유저에게 후기를 남긴 적이 있습니다."); + } + + if (reviewer.getId().equals(reviewee.getId())) { + throw new IllegalStateException("자기 자신에게 후기를 남길 수 없습니다."); + } + + Project project = projectRepository.findById(reviewReqDto.getProjectId()) + .orElseThrow(() -> new RuntimeException("해당 프로젝트는 존재하지 않습니다: " + reviewReqDto.getProjectId())); + + Review savedReview = reviewRepository.save(reviewReqDto.toEntity(reviewer, reviewee, project)); + + for (Long tagId : reviewReqDto.getTagIds()) { reviewTagRepository.save(ReviewTag.builder() .review(savedReview) - .tag(tagRepository.findById(tagId).orElseThrow(() -> new RuntimeException("다음과 같은 태그는 존재하지 않습니다: " + tagId))) + .tag(tagRepository.findById(tagId).orElseThrow(() -> new RuntimeException("해당 태그는 존재하지 않습니다: " + tagId))) .build()); } - // 각 스펙트럼 축 당 저장하기... + // 각 스펙트럼 축 당 저장하기 List reviewSpectrums = reviewCreateReqDto.getSpectrumReqDtos().stream() .map(spectrumReqDto -> { - SpectrumAxis spectrumAxis = spectrumAxisRepository.findById(spectrumReqDto.getSpectrumAxisId()).orElseThrow(() -> new RuntimeException("다음과 같은 스펙트럼 축은 존재하지 않습니다: " + spectrumReqDto.getSpectrumAxisId())); + SpectrumAxis spectrumAxis = spectrumAxisRepository.findById(spectrumReqDto.getSpectrumAxisId()).orElseThrow(() -> new RuntimeException("해당 스펙트럼은 존재하지 않습니다: " + spectrumReqDto.getSpectrumAxisId())); return ReviewSpectrum.builder() .review(savedReview) diff --git a/SossBar/src/main/resources/application.yml b/SossBar/src/main/resources/application.yml index 0d81284..06a96b0 100644 --- a/SossBar/src/main/resources/application.yml +++ b/SossBar/src/main/resources/application.yml @@ -12,7 +12,12 @@ spring: password: ${spring.datasource.password} driver-class-name: ${spring.datasource.driver-class-name} + sql: + init: + mode: always + jpa: + defer-datasource-initialization: true hibernate: ddl-auto: update naming: @@ -22,7 +27,6 @@ spring: hibernate: format_sql: true open-in-view: false - defer-datasource-initialization: true // 이거 추가한 거 잊지말기! logging: level: @@ -44,7 +48,6 @@ cloud: secret-key: ${CLOUD_AWS_CREDENTIALS_SECRET_KEY} s3: bucket: ${CLOUD_AWS_S3_BUCKET} - url: ${CLOUD_AWS_S3_URL} region: static: ap-northeast-2 stack: diff --git a/SossBar/src/main/resources/data.sql b/SossBar/src/main/resources/data.sql index fd18049..d4624a0 100644 --- a/SossBar/src/main/resources/data.sql +++ b/SossBar/src/main/resources/data.sql @@ -19,8 +19,7 @@ INSERT INTO tag(tag_name) VALUES ('고마움을 잘 표현해요'); INSERT INTO tag(tag_name) VALUES ('먼저 친근하게 다가와요'); INSERT INTO tag(tag_name) VALUES ('모르는 것을 숨기지 않고 물어봐요'); -INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('1번 항목', '원칙 준수', '혁신 제안'); -INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('2번 항목', '유연한 대처', '철저한 계획'); -INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('3번 항목', '묵묵한 조력', '당당한 리드'); -INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('4번 항목', '냉정한 과업', '따뜻한 관계'); -INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('5번 항목', '침착한 대응', '빈틈없는 대비'); \ No newline at end of file +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('1번 항목', '서포트형', '리드형'); +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('2번 항목', '빠른 작업 속도 중시', '천천히 신중한 고민 중시'); +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('3번 항목', '상황별 유연한 대처', '철저한 계획 기반 실행'); +INSERT INTO spectrum_axis(axis_name, left_label, right_label) VALUES ('4번 항목', '냉철한 결과 지향', '따뜻한 관계 지향'); \ No newline at end of file From 61fb3763bd9ea6f5b8500b5ee6789e45ae06dc30 Mon Sep 17 00:00:00 2001 From: goodispotato Date: Thu, 16 Apr 2026 20:58:24 +0900 Subject: [PATCH 03/12] =?UTF-8?q?Refactor/#5=20-=20=EB=A6=AC=EB=B7=B0?= =?UTF-8?q?=ED=83=9C=EA=B7=B8=20=EC=A0=80=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sossbar/review/service/ReviewService.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java index 817bacc..edada2c 100644 --- a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -12,6 +12,7 @@ import com.sossbar.review.repository.ReviewTagRepository; import com.sossbar.spectrumaxis.entity.SpectrumAxis; import com.sossbar.spectrumaxis.repository.SpectrumAxisRepository; +import com.sossbar.tag.entity.Tag; import com.sossbar.tag.repository.TagRepository; import com.sossbar.user.entity.User; import com.sossbar.user.repository.UserRepository; @@ -59,11 +60,23 @@ public void createReview(Principal principal, ReviewCreateReqDto reviewCreateReq Review savedReview = reviewRepository.save(reviewReqDto.toEntity(reviewer, reviewee, project)); - for (Long tagId : reviewReqDto.getTagIds()) { - reviewTagRepository.save(ReviewTag.builder() - .review(savedReview) - .tag(tagRepository.findById(tagId).orElseThrow(() -> new RuntimeException("해당 태그는 존재하지 않습니다: " + tagId))) - .build()); + // 태그 목록 저장 + List tagIds = reviewReqDto.getTagIds(); + if (tagIds != null && !tagIds.isEmpty()) { + List tags = tagRepository.findAllById(tagIds); + + if(tags.size() != tagIds.size()) { + throw new RuntimeException("일부 태그가 존재하지 않습니다."); + } + + List reviewTags = tags.stream() + .map(tag -> ReviewTag.builder() + .review(savedReview) + .tag(tag) + .build()) + .collect(Collectors.toList()); + + reviewTagRepository.saveAll(reviewTags); } // 각 스펙트럼 축 당 저장하기 From a023268298f04f5d86d5a895a9a5185c4d2dccb4 Mon Sep 17 00:00:00 2001 From: goodispotato Date: Thu, 16 Apr 2026 21:12:30 +0900 Subject: [PATCH 04/12] =?UTF-8?q?Refactor/#5=20-=20=EB=A6=AC=EB=B7=B0?= =?UTF-8?q?=EC=8A=A4=ED=8E=99=ED=8A=B8=EB=9F=BC=20=EC=A0=80=EC=9E=A5=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=B5=9C=EC=A0=81=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sossbar/review/service/ReviewService.java | 32 +++++++++++++------ .../spectrumaxis/entity/SpectrumAxis.java | 2 ++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java index edada2c..4c39e2f 100644 --- a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -4,6 +4,7 @@ import com.sossbar.projects.repository.ProjectRepository; import com.sossbar.review.dto.request.ReviewCreateReqDto; import com.sossbar.review.dto.request.ReviewReqDto; +import com.sossbar.review.dto.request.SpectrumReqDto; import com.sossbar.review.entity.Review; import com.sossbar.review.entity.ReviewSpectrum; import com.sossbar.review.entity.ReviewTag; @@ -22,6 +23,7 @@ import java.security.Principal; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Service @@ -80,18 +82,28 @@ public void createReview(Principal principal, ReviewCreateReqDto reviewCreateReq } // 각 스펙트럼 축 당 저장하기 - List reviewSpectrums = reviewCreateReqDto.getSpectrumReqDtos().stream() - .map(spectrumReqDto -> { - SpectrumAxis spectrumAxis = spectrumAxisRepository.findById(spectrumReqDto.getSpectrumAxisId()).orElseThrow(() -> new RuntimeException("해당 스펙트럼은 존재하지 않습니다: " + spectrumReqDto.getSpectrumAxisId())); - - return ReviewSpectrum.builder() - .review(savedReview) - .spectrumAxis(spectrumAxis) - .strength(spectrumReqDto.getSpectrumStrength()) - .build(); - }) + List spectrumAxisIds = reviewCreateReqDto.getSpectrumReqDtos().stream() + .map(SpectrumReqDto::getSpectrumAxisId) + .distinct() .collect(Collectors.toList()); + List spectrumAxes = spectrumAxisRepository.findAllById(spectrumAxisIds); + + Map spectrumAxisMap = spectrumAxes.stream() + .collect(Collectors.toMap(SpectrumAxis::getSpectrumAxisId, axis -> axis)); + + if(spectrumAxisMap.size() != spectrumAxes.size()) { + throw new RuntimeException("일부 스펙트럼이 존재하지 않습니다."); + } + + List reviewSpectrums = reviewCreateReqDto.getSpectrumReqDtos().stream() + .map(dto -> ReviewSpectrum.builder() + .review(savedReview) + .spectrumAxis(spectrumAxisMap.get(dto.getSpectrumAxisId())) + .strength(dto.getSpectrumStrength()) + .build()) + .collect(Collectors.toList()); + reviewSpectrumRepository.saveAll(reviewSpectrums); } } diff --git a/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java b/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java index b9399b5..627639c 100644 --- a/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java +++ b/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java @@ -3,6 +3,7 @@ import com.sossbar.review.entity.ReviewSpectrum; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -12,6 +13,7 @@ @Entity @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter public class SpectrumAxis { @Id From 109431124deb6d003bec394e810e4e210af4b0fa Mon Sep 17 00:00:00 2001 From: goodispotato Date: Thu, 16 Apr 2026 21:44:18 +0900 Subject: [PATCH 05/12] =?UTF-8?q?Chore/#5=20-=20.gitignore=EC=97=90=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20.idea=20?= =?UTF-8?q?=ED=8F=B4=EB=8D=94=20=EC=B6=94=EC=A0=81=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SossBar/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SossBar/.gitignore b/SossBar/.gitignore index 9289965..f2ab2d4 100644 --- a/SossBar/.gitignore +++ b/SossBar/.gitignore @@ -36,4 +36,7 @@ out/ ### VS Code ### .vscode/ +### HTTP Client ### +/httpRequests/ + src/**/application-prod.yml From 535b1e9200556a6f282b57e731892ebc97785c79 Mon Sep 17 00:00:00 2001 From: goodispotato Date: Thu, 16 Apr 2026 21:50:18 +0900 Subject: [PATCH 06/12] =?UTF-8?q?Style/#5=20-=20URL=20=EB=A7=A4=ED=95=91?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20missing=20EOL=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sossbar/review/controller/ReviewController.java | 4 ++-- .../java/com/sossbar/review/dto/request/ReviewReqDto.java | 2 +- SossBar/src/main/java/com/sossbar/review/entity/Review.java | 2 +- .../src/main/java/com/sossbar/review/entity/ReviewTag.java | 2 +- .../java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java index cc2bf95..be1a776 100644 --- a/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java +++ b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java @@ -21,7 +21,7 @@ public class ReviewController { private final ReviewService reviewService; @Operation(summary = "후기 작성", description = "사용자는 로그인 후 다른 사용자에 대한 후기를 남길 수 있습니다.") - @PostMapping("api/v1/reviews") + @PostMapping("/api/v1/reviews") public ApiResTemplate createReview( @RequestBody ReviewCreateReqDto reviewCreateReqDto, Principal principal @@ -29,4 +29,4 @@ public ApiResTemplate createReview( reviewService.createReview(principal, reviewCreateReqDto); return ApiResTemplate.successWithNoContent(SuccessCode.SUCCESS); } -} \ No newline at end of file +} diff --git a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java index c7be515..4ce59e1 100644 --- a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java +++ b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java @@ -40,4 +40,4 @@ public Review toEntity(User reviewer, User reviewee, Project project) { .project(project) .build(); } -} \ No newline at end of file +} diff --git a/SossBar/src/main/java/com/sossbar/review/entity/Review.java b/SossBar/src/main/java/com/sossbar/review/entity/Review.java index e95c633..398a945 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/Review.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/Review.java @@ -50,4 +50,4 @@ public Review(String positiveFeedback, String negativeFeedback, User reviewer, U this.reviewee = reviewee; this.project = project; } -} \ No newline at end of file +} diff --git a/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java index 987431d..548d385 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java @@ -34,4 +34,4 @@ public void setTag(Tag tag) { this.tag = tag; } -} \ No newline at end of file +} diff --git a/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java b/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java index 627639c..b64d247 100644 --- a/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java +++ b/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java @@ -32,4 +32,4 @@ public class SpectrumAxis { @OneToMany(mappedBy = "spectrumAxis", cascade = CascadeType.ALL, orphanRemoval = true) private List reviewSpectrums = new ArrayList<>(); -} \ No newline at end of file +} From ad0504949fd823ddc6362dbab41181dfb1acbcfe Mon Sep 17 00:00:00 2001 From: goodispotato Date: Fri, 17 Apr 2026 12:39:11 +0900 Subject: [PATCH 07/12] =?UTF-8?q?Style/#5=20-=20=EC=9E=90=EB=B0=94=20?= =?UTF-8?q?=EB=AA=85=EB=AA=85=20=EA=B7=9C=EC=B9=99=20=EB=B0=8F=20=EC=BA=A1?= =?UTF-8?q?=EC=8A=90=ED=99=94=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/modules/sossbar.iml | 12 ++ .idea/modules/sossbar.test.iml | 153 ++++++++++++++++++ .../dto/request/ReviewCreateReqDto.java | 4 +- .../review/repository/ReviewRepository.java | 2 +- 4 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 .idea/modules/sossbar.iml create mode 100644 .idea/modules/sossbar.test.iml diff --git a/.idea/modules/sossbar.iml b/.idea/modules/sossbar.iml new file mode 100644 index 0000000..a32d54d --- /dev/null +++ b/.idea/modules/sossbar.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules/sossbar.test.iml b/.idea/modules/sossbar.test.iml new file mode 100644 index 0000000..0f30d94 --- /dev/null +++ b/.idea/modules/sossbar.test.iml @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java index 1543d05..c82d0c7 100644 --- a/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java +++ b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewCreateReqDto.java @@ -7,6 +7,6 @@ // 통합 DTO @Getter public class ReviewCreateReqDto { - ReviewReqDto reviewReqDto; - List spectrumReqDtos; + private ReviewReqDto reviewReqDto; + private List spectrumReqDtos; } diff --git a/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java b/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java index 9a1812c..09c4b9b 100644 --- a/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java +++ b/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java @@ -9,5 +9,5 @@ public interface ReviewRepository extends JpaRepository { // 중복 리뷰 검증 - boolean existsByReviewerAndReviewee(User Reviewer, User Reviewee); + boolean existsByReviewerAndReviewee(User reviewer, User reviewee); } From 340093cc981ae7f1d09aebbf522ee161135ad041 Mon Sep 17 00:00:00 2001 From: goodispotato Date: Fri, 17 Apr 2026 12:42:55 +0900 Subject: [PATCH 08/12] =?UTF-8?q?Refactor/#5=20-=20Review=20=EC=97=94?= =?UTF-8?q?=ED=8B=B0=ED=8B=B0=EC=97=90=EC=84=9C=20@Setter=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SossBar/src/main/java/com/sossbar/review/entity/Review.java | 1 - 1 file changed, 1 deletion(-) diff --git a/SossBar/src/main/java/com/sossbar/review/entity/Review.java b/SossBar/src/main/java/com/sossbar/review/entity/Review.java index 398a945..ca690a8 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/Review.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/Review.java @@ -10,7 +10,6 @@ @Entity @Getter -@Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Review { From 8eff94310637fc17bbe453dffe70c1a4a1deafb7 Mon Sep 17 00:00:00 2001 From: goodispotato Date: Fri, 17 Apr 2026 13:00:59 +0900 Subject: [PATCH 09/12] =?UTF-8?q?Fix/#5=20-=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sossbar/review/service/ReviewService.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java index 4c39e2f..147f99f 100644 --- a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -42,7 +42,13 @@ public class ReviewService { public void createReview(Principal principal, ReviewCreateReqDto reviewCreateReqDto) { ReviewReqDto reviewReqDto = reviewCreateReqDto.getReviewReqDto(); - Long reviewerIdentifier = Long.parseLong(principal.getName()); + Long reviewerIdentifier; + + try { + reviewerIdentifier = Long.parseLong(principal.getName()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(e); + } User reviewer = userRepository.findById(reviewerIdentifier) .orElseThrow(() -> new RuntimeException("해당 유저는 존재하지 않습니다: " + reviewerIdentifier)); From b58471b640aa30b7779ad76d6efcdf0179c47084 Mon Sep 17 00:00:00 2001 From: goodispotato Date: Sat, 18 Apr 2026 21:40:01 +0900 Subject: [PATCH 10/12] =?UTF-8?q?Chore/#5=20-=20.gitignore=EC=97=90=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20applicati?= =?UTF-8?q?on.yml=20=ED=8C=8C=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SossBar/.gitignore | 1 + SossBar/src/main/resources/application.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/SossBar/.gitignore b/SossBar/.gitignore index f2ab2d4..3d4135a 100644 --- a/SossBar/.gitignore +++ b/SossBar/.gitignore @@ -22,6 +22,7 @@ bin/ *.iws *.iml *.ipr +*.xml out/ !**/src/main/**/out/ !**/src/test/**/out/ diff --git a/SossBar/src/main/resources/application.yml b/SossBar/src/main/resources/application.yml index 06a96b0..827d737 100644 --- a/SossBar/src/main/resources/application.yml +++ b/SossBar/src/main/resources/application.yml @@ -47,6 +47,7 @@ cloud: access-key: ${CLOUD_AWS_CREDENTIALS_ACCESS_KEY} secret-key: ${CLOUD_AWS_CREDENTIALS_SECRET_KEY} s3: + url: ${CLOUD_AWS_S3_URL} bucket: ${CLOUD_AWS_S3_BUCKET} region: static: ap-northeast-2 From 47d6bb4f03ee3114e8b3678add160c3a32daf8eb Mon Sep 17 00:00:00 2001 From: goodispotato Date: Sat, 18 Apr 2026 22:49:39 +0900 Subject: [PATCH 11/12] =?UTF-8?q?Refactor/#5=20-=20@Valid=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EB=B0=8F=20=EC=83=9D=EC=84=B1=EB=90=9C=20=EB=A6=AC?= =?UTF-8?q?=EB=B7=B0=20=EC=A0=95=EB=B3=B4=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/controller/ReviewController.java | 11 +++-- .../dto/response/ReviewCreateResDto.java | 45 +++++++++++++++++++ .../review/dto/response/ReviewResDto.java | 4 +- .../review/dto/response/SpectrumResDto.java | 10 +++++ .../sossbar/review/entity/ReviewSpectrum.java | 6 +-- .../com/sossbar/review/entity/ReviewTag.java | 6 +-- .../sossbar/review/service/ReviewService.java | 11 +++-- .../main/java/com/sossbar/tag/entity/Tag.java | 2 + 8 files changed, 77 insertions(+), 18 deletions(-) create mode 100644 SossBar/src/main/java/com/sossbar/review/dto/response/ReviewCreateResDto.java create mode 100644 SossBar/src/main/java/com/sossbar/review/dto/response/SpectrumResDto.java diff --git a/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java index be1a776..1cf246d 100644 --- a/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java +++ b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java @@ -3,9 +3,11 @@ import com.sossbar.global.common.code.SuccessCode; import com.sossbar.global.common.template.ApiResTemplate; import com.sossbar.review.dto.request.ReviewCreateReqDto; +import com.sossbar.review.dto.response.ReviewCreateResDto; import com.sossbar.review.service.ReviewService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -22,11 +24,12 @@ public class ReviewController { @Operation(summary = "후기 작성", description = "사용자는 로그인 후 다른 사용자에 대한 후기를 남길 수 있습니다.") @PostMapping("/api/v1/reviews") - public ApiResTemplate createReview( - @RequestBody ReviewCreateReqDto reviewCreateReqDto, + public ApiResTemplate createReview( + @RequestBody @Valid ReviewCreateReqDto reviewCreateReqDto, Principal principal ) { - reviewService.createReview(principal, reviewCreateReqDto); - return ApiResTemplate.successWithNoContent(SuccessCode.SUCCESS); + ReviewCreateResDto reviewCreateResDto = reviewService.createReview(principal, reviewCreateReqDto); + + return ApiResTemplate.successResponse(SuccessCode.CREATE_SUCCESS, reviewCreateResDto); } } diff --git a/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewCreateResDto.java b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewCreateResDto.java new file mode 100644 index 0000000..d68221d --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewCreateResDto.java @@ -0,0 +1,45 @@ +package com.sossbar.review.dto.response; + +import com.sossbar.review.entity.Review; +import com.sossbar.review.entity.ReviewSpectrum; +import com.sossbar.review.entity.ReviewTag; +import com.sossbar.tag.dto.response.TagResDto; +import lombok.Builder; + +import java.util.List; +import java.util.stream.Collectors; + +@Builder +public record ReviewCreateResDto ( + ReviewResDto reviewResDto, + List spectrumResDtos +) { + public static ReviewCreateResDto from(Review savedReview, List reviewTags, List reviewSpectrums) { + List tagResDtos = reviewTags.stream() + .map(reviewTag -> new TagResDto( + reviewTag.getTag().getTagId(), + reviewTag.getTag().getTagName() + )) + .collect(Collectors.toList()); + + ReviewResDto reviewResDto = new ReviewResDto( + savedReview.getPositiveFeedback(), + savedReview.getNegativeFeedback(), + savedReview.getReviewee().getId(), + savedReview.getProject().getProjectId(), + tagResDtos + ); + + List spectrumResDtos = reviewSpectrums.stream() + .map(reviewSpectrum -> SpectrumResDto.builder() + .spectrumAxisId(reviewSpectrum.getSpectrumAxis().getSpectrumAxisId()) + .spectrumStrength(reviewSpectrum.getStrength()) + .build()) + .collect(Collectors.toList()); + + return ReviewCreateResDto.builder() + .reviewResDto(reviewResDto) + .spectrumResDtos(spectrumResDtos) + .build(); + } +} diff --git a/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java index 7b4ac12..76166ea 100644 --- a/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java +++ b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java @@ -1,6 +1,5 @@ package com.sossbar.review.dto.response; -import com.sossbar.spectrumaxis.dto.response.SpectrumAxisResDto; import com.sossbar.tag.dto.response.TagResDto; import java.util.List; @@ -10,7 +9,6 @@ public record ReviewResDto ( String negativeFeedback, Long revieweeId, Long projectId, - List tags, - List spectrumAxes + List tagResDtos ) { } diff --git a/SossBar/src/main/java/com/sossbar/review/dto/response/SpectrumResDto.java b/SossBar/src/main/java/com/sossbar/review/dto/response/SpectrumResDto.java new file mode 100644 index 0000000..2785934 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/response/SpectrumResDto.java @@ -0,0 +1,10 @@ +package com.sossbar.review.dto.response; + +import lombok.Builder; + +@Builder +public record SpectrumResDto ( + Long spectrumAxisId, + Integer spectrumStrength +) { +} diff --git a/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java b/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java index 15b0cae..b764763 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java @@ -2,15 +2,13 @@ import com.sossbar.spectrumaxis.entity.SpectrumAxis; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; +import lombok.*; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder +@Getter public class ReviewSpectrum { @Id diff --git a/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java index 548d385..76b8682 100644 --- a/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java @@ -3,15 +3,13 @@ import com.sossbar.tag.entity.Tag; import com.sossbar.user.entity.User; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; +import lombok.*; @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @Builder +@Getter public class ReviewTag { @Id diff --git a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java index 147f99f..c81f26f 100644 --- a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -5,6 +5,7 @@ import com.sossbar.review.dto.request.ReviewCreateReqDto; import com.sossbar.review.dto.request.ReviewReqDto; import com.sossbar.review.dto.request.SpectrumReqDto; +import com.sossbar.review.dto.response.ReviewCreateResDto; import com.sossbar.review.entity.Review; import com.sossbar.review.entity.ReviewSpectrum; import com.sossbar.review.entity.ReviewTag; @@ -22,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional; import java.security.Principal; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -39,10 +41,11 @@ public class ReviewService { private final ProjectRepository projectRepository; @Transactional - public void createReview(Principal principal, ReviewCreateReqDto reviewCreateReqDto) { + public ReviewCreateResDto createReview(Principal principal, ReviewCreateReqDto reviewCreateReqDto) { ReviewReqDto reviewReqDto = reviewCreateReqDto.getReviewReqDto(); + List reviewTags = new ArrayList<>(); - Long reviewerIdentifier; + long reviewerIdentifier; try { reviewerIdentifier = Long.parseLong(principal.getName()); @@ -77,7 +80,7 @@ public void createReview(Principal principal, ReviewCreateReqDto reviewCreateReq throw new RuntimeException("일부 태그가 존재하지 않습니다."); } - List reviewTags = tags.stream() + reviewTags = tags.stream() .map(tag -> ReviewTag.builder() .review(savedReview) .tag(tag) @@ -111,5 +114,7 @@ public void createReview(Principal principal, ReviewCreateReqDto reviewCreateReq .collect(Collectors.toList()); reviewSpectrumRepository.saveAll(reviewSpectrums); + + return ReviewCreateResDto.from(savedReview, reviewTags, reviewSpectrums); } } diff --git a/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java b/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java index 736ae76..499ee61 100644 --- a/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java +++ b/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java @@ -3,6 +3,7 @@ import com.sossbar.review.entity.ReviewTag; import jakarta.persistence.*; import lombok.AccessLevel; +import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -12,6 +13,7 @@ @Entity @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter public class Tag { @Id From 49e4ad28f42d276c8cc194b516f6bf27f8d9fa72 Mon Sep 17 00:00:00 2001 From: goodispotato Date: Sat, 18 Apr 2026 23:10:01 +0900 Subject: [PATCH 12/12] =?UTF-8?q?Refactor/#5=20-=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=EC=97=90=EB=9F=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sossbar/global/common/code/ErrorCode.java | 8 +++++++- .../sossbar/review/service/ReviewService.java | 16 +++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/SossBar/src/main/java/com/sossbar/global/common/code/ErrorCode.java b/SossBar/src/main/java/com/sossbar/global/common/code/ErrorCode.java index 2d34c0a..a85a3e5 100644 --- a/SossBar/src/main/java/com/sossbar/global/common/code/ErrorCode.java +++ b/SossBar/src/main/java/com/sossbar/global/common/code/ErrorCode.java @@ -39,7 +39,13 @@ public enum ErrorCode { // PROJECT PROJECT_NOT_FOUND_EXCEPTION(HttpStatus.NOT_FOUND, "해당 프로젝트가 없습니다. projectId = ", "PROJECT-001"), PROJECT_CREATE_ROLLBACK_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR, "프로젝트 생성 중 DB 오류가 발생하여 업로드된 이미지를 롤백했습니다. imageUrl = ", "PROJECT-002"), - PROJECT_UPDATE_ROLLBACK_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR, "프로젝트 수정 중 DB 오류가 발생하여 업로드된 이미지를 롤백했습니다. imageUrl = ", "PROJECT-003"); + PROJECT_UPDATE_ROLLBACK_EXCEPTION(HttpStatus.INTERNAL_SERVER_ERROR, "프로젝트 수정 중 DB 오류가 발생하여 업로드된 이미지를 롤백했습니다. imageUrl = ", "PROJECT-003"), + + // REVIEW + DUPLICATE_REVIEW_EXCEPTION(HttpStatus.CONFLICT,"이미 해당 사용자에게 후기를 남겼습니다. revieweeId = ","REVIEW-001"), + SELF_REVIEW_NOT_ALLOWED(HttpStatus.BAD_REQUEST, "자기 자신에게 후기를 남길 수 없습니다.", "REVIEW-002"), + TAG_NOT_FOUND(HttpStatus.NOT_FOUND, "일부 태그가 존재하지 않습니다.", "REVIEW-003"), + SPECTRUM_NOT_FOUND(HttpStatus.NOT_FOUND, "일부 스펙트럼이 존재하지 않습니다.", "REVIEW-004"); private final HttpStatus httpStatus; private final String message; diff --git a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java index c81f26f..82711d3 100644 --- a/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -1,5 +1,7 @@ package com.sossbar.review.service; +import com.sossbar.global.common.code.ErrorCode; +import com.sossbar.global.common.exception.BusinessException; import com.sossbar.projects.entity.Project; import com.sossbar.projects.repository.ProjectRepository; import com.sossbar.review.dto.request.ReviewCreateReqDto; @@ -54,20 +56,20 @@ public ReviewCreateResDto createReview(Principal principal, ReviewCreateReqDto r } User reviewer = userRepository.findById(reviewerIdentifier) - .orElseThrow(() -> new RuntimeException("해당 유저는 존재하지 않습니다: " + reviewerIdentifier)); + .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND_EXCEPTION, reviewerIdentifier+"")); User reviewee = userRepository.findById(reviewReqDto.getRevieweeId()) - .orElseThrow(() -> new RuntimeException("해당 유저는 존재하지 않습니다: " + reviewReqDto.getRevieweeId())); + .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND_EXCEPTION, reviewerIdentifier+"")); if (reviewRepository.existsByReviewerAndReviewee(reviewer, reviewee)) { - throw new IllegalStateException("이미 해당 유저에게 후기를 남긴 적이 있습니다."); + throw new BusinessException(ErrorCode.DUPLICATE_REVIEW_EXCEPTION, reviewee.getId()+""); } if (reviewer.getId().equals(reviewee.getId())) { - throw new IllegalStateException("자기 자신에게 후기를 남길 수 없습니다."); + throw new BusinessException(ErrorCode.SELF_REVIEW_NOT_ALLOWED, ""); } Project project = projectRepository.findById(reviewReqDto.getProjectId()) - .orElseThrow(() -> new RuntimeException("해당 프로젝트는 존재하지 않습니다: " + reviewReqDto.getProjectId())); + .orElseThrow(() -> new BusinessException(ErrorCode.PROJECT_NOT_FOUND_EXCEPTION, reviewReqDto.getProjectId()+"")); Review savedReview = reviewRepository.save(reviewReqDto.toEntity(reviewer, reviewee, project)); @@ -77,7 +79,7 @@ public ReviewCreateResDto createReview(Principal principal, ReviewCreateReqDto r List tags = tagRepository.findAllById(tagIds); if(tags.size() != tagIds.size()) { - throw new RuntimeException("일부 태그가 존재하지 않습니다."); + throw new BusinessException(ErrorCode.TAG_NOT_FOUND, ""); } reviewTags = tags.stream() @@ -102,7 +104,7 @@ public ReviewCreateResDto createReview(Principal principal, ReviewCreateReqDto r .collect(Collectors.toMap(SpectrumAxis::getSpectrumAxisId, axis -> axis)); if(spectrumAxisMap.size() != spectrumAxes.size()) { - throw new RuntimeException("일부 스펙트럼이 존재하지 않습니다."); + throw new BusinessException(ErrorCode.SPECTRUM_NOT_FOUND, ""); } List reviewSpectrums = reviewCreateReqDto.getSpectrumReqDtos().stream()