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.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.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/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/.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/.gitignore b/SossBar/.gitignore index 9289965..3d4135a 100644 --- a/SossBar/.gitignore +++ b/SossBar/.gitignore @@ -22,6 +22,7 @@ bin/ *.iws *.iml *.ipr +*.xml out/ !**/src/main/**/out/ !**/src/test/**/out/ @@ -36,4 +37,7 @@ out/ ### VS Code ### .vscode/ +### HTTP Client ### +/httpRequests/ + src/**/application-prod.yml 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/controller/ReviewController.java b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java new file mode 100644 index 0000000..1cf246d --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/controller/ReviewController.java @@ -0,0 +1,35 @@ +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.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; +import org.springframework.web.bind.annotation.RestController; + +import java.security.Principal; + +@Tag(name = "Review API", description = "후기 관련 API") +@RestController +@RequiredArgsConstructor +public class ReviewController { + + private final ReviewService reviewService; + + @Operation(summary = "후기 작성", description = "사용자는 로그인 후 다른 사용자에 대한 후기를 남길 수 있습니다.") + @PostMapping("/api/v1/reviews") + public ApiResTemplate createReview( + @RequestBody @Valid ReviewCreateReqDto reviewCreateReqDto, + Principal principal + ) { + ReviewCreateResDto reviewCreateResDto = reviewService.createReview(principal, reviewCreateReqDto); + + return ApiResTemplate.successResponse(SuccessCode.CREATE_SUCCESS, reviewCreateResDto); + } +} 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..c82d0c7 --- /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 { + private ReviewReqDto reviewReqDto; + private 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..4ce59e1 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/request/ReviewReqDto.java @@ -0,0 +1,43 @@ +package com.sossbar.review.dto.request; + +import com.sossbar.projects.entity.Project; +import com.sossbar.review.entity.Review; +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 +@Getter +public class ReviewReqDto { + @NotBlank + @Size(min = 10) + private String positiveFeedback; + + @Size(min = 10) + private String negativeFeedback; + + @NotNull + @Positive + private Long revieweeId; + + @NotNull + @Positive + private Long projectId; + + private List tagIds; + + public Review toEntity(User reviewer, User reviewee, Project project) { + return Review.builder() + .positiveFeedback(positiveFeedback) + .negativeFeedback(negativeFeedback) + .reviewer(reviewer) + .reviewee(reviewee) + .project(project) + .build(); + } +} 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/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 new file mode 100644 index 0000000..76166ea --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/dto/response/ReviewResDto.java @@ -0,0 +1,14 @@ +package com.sossbar.review.dto.response; + +import com.sossbar.tag.dto.response.TagResDto; + +import java.util.List; + +public record ReviewResDto ( + String positiveFeedback, + String negativeFeedback, + Long revieweeId, + Long projectId, + 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/Review.java b/SossBar/src/main/java/com/sossbar/review/entity/Review.java new file mode 100644 index 0000000..ca690a8 --- /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.projects.entity.Project; +import com.sossbar.user.entity.User; +import jakarta.persistence.*; +import lombok.*; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@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") + private User reviewer; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "reviewee_id") + private User reviewee; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "project_id") + 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; + } +} 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..b764763 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewSpectrum.java @@ -0,0 +1,37 @@ +package com.sossbar.review.entity; + +import com.sossbar.spectrumaxis.entity.SpectrumAxis; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@Getter +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; + } + +} 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..76b8682 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/entity/ReviewTag.java @@ -0,0 +1,35 @@ +package com.sossbar.review.entity; + +import com.sossbar.tag.entity.Tag; +import com.sossbar.user.entity.User; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +@Getter +public class ReviewTag { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long reviewTagId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "review_id") + private Review review; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "tag_id") + private Tag tag; + + public void setReview(Review review) { + this.review = review; + } + + public void setTag(Tag tag) { + this.tag = tag; + } + +} 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..09c4b9b --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/repository/ReviewRepository.java @@ -0,0 +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/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..82711d3 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/review/service/ReviewService.java @@ -0,0 +1,122 @@ +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; +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; +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.entity.Tag; +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.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class ReviewService { + + 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 ReviewCreateResDto createReview(Principal principal, ReviewCreateReqDto reviewCreateReqDto) { + ReviewReqDto reviewReqDto = reviewCreateReqDto.getReviewReqDto(); + List reviewTags = new ArrayList<>(); + + long reviewerIdentifier; + + try { + reviewerIdentifier = Long.parseLong(principal.getName()); + } catch (NumberFormatException e) { + throw new IllegalArgumentException(e); + } + + User reviewer = userRepository.findById(reviewerIdentifier) + .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND_EXCEPTION, reviewerIdentifier+"")); + User reviewee = userRepository.findById(reviewReqDto.getRevieweeId()) + .orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND_EXCEPTION, reviewerIdentifier+"")); + + if (reviewRepository.existsByReviewerAndReviewee(reviewer, reviewee)) { + throw new BusinessException(ErrorCode.DUPLICATE_REVIEW_EXCEPTION, reviewee.getId()+""); + } + + if (reviewer.getId().equals(reviewee.getId())) { + throw new BusinessException(ErrorCode.SELF_REVIEW_NOT_ALLOWED, ""); + } + + Project project = projectRepository.findById(reviewReqDto.getProjectId()) + .orElseThrow(() -> new BusinessException(ErrorCode.PROJECT_NOT_FOUND_EXCEPTION, reviewReqDto.getProjectId()+"")); + + Review savedReview = reviewRepository.save(reviewReqDto.toEntity(reviewer, reviewee, project)); + + // 태그 목록 저장 + List tagIds = reviewReqDto.getTagIds(); + if (tagIds != null && !tagIds.isEmpty()) { + List tags = tagRepository.findAllById(tagIds); + + if(tags.size() != tagIds.size()) { + throw new BusinessException(ErrorCode.TAG_NOT_FOUND, ""); + } + + reviewTags = tags.stream() + .map(tag -> ReviewTag.builder() + .review(savedReview) + .tag(tag) + .build()) + .collect(Collectors.toList()); + + reviewTagRepository.saveAll(reviewTags); + } + + // 각 스펙트럼 축 당 저장하기 + 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 BusinessException(ErrorCode.SPECTRUM_NOT_FOUND, ""); + } + + 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); + + return ReviewCreateResDto.from(savedReview, reviewTags, 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..b64d247 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/spectrumaxis/entity/SpectrumAxis.java @@ -0,0 +1,35 @@ +package com.sossbar.spectrumaxis.entity; + +import com.sossbar.review.entity.ReviewSpectrum; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Setter(AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +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<>(); + +} 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..499ee61 --- /dev/null +++ b/SossBar/src/main/java/com/sossbar/tag/entity/Tag.java @@ -0,0 +1,29 @@ +package com.sossbar.tag.entity; + +import com.sossbar.review.entity.ReviewTag; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Setter(AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +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 faddc8e..827d737 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: @@ -42,8 +47,8 @@ cloud: access-key: ${CLOUD_AWS_CREDENTIALS_ACCESS_KEY} secret-key: ${CLOUD_AWS_CREDENTIALS_SECRET_KEY} s3: - bucket: ${CLOUD_AWS_S3_BUCKET} url: ${CLOUD_AWS_S3_URL} + bucket: ${CLOUD_AWS_S3_BUCKET} region: static: ap-northeast-2 stack: diff --git a/SossBar/src/main/resources/data.sql b/SossBar/src/main/resources/data.sql new file mode 100644 index 0000000..d4624a0 --- /dev/null +++ b/SossBar/src/main/resources/data.sql @@ -0,0 +1,25 @@ +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번 항목', '냉철한 결과 지향', '따뜻한 관계 지향'); \ No newline at end of file