From 49285c789ac97f4382ba21d6e438f883da1e6eb2 Mon Sep 17 00:00:00 2001 From: oosedus Date: Mon, 29 Jul 2024 21:53:53 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=ED=9B=84=EA=B8=B0=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=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 --- .../api/review/ReviewController.java | 43 ++++++++++- .../dto/review/request/SaveReviewRequest.java | 24 ++++++ .../review/response/SaveReviewResponse.java | 68 +++++++++++++++++ .../service/review/ReviewService.java | 75 ++++++++++++++++++- 4 files changed, 205 insertions(+), 5 deletions(-) create mode 100644 src/main/java/likelion/MZConnent/dto/review/request/SaveReviewRequest.java create mode 100644 src/main/java/likelion/MZConnent/dto/review/response/SaveReviewResponse.java diff --git a/src/main/java/likelion/MZConnent/api/review/ReviewController.java b/src/main/java/likelion/MZConnent/api/review/ReviewController.java index 19b3930..7832ef3 100644 --- a/src/main/java/likelion/MZConnent/api/review/ReviewController.java +++ b/src/main/java/likelion/MZConnent/api/review/ReviewController.java @@ -1,16 +1,25 @@ package likelion.MZConnent.api.review; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import likelion.MZConnent.dto.paging.response.PageContentResponse; +import likelion.MZConnent.dto.review.request.SaveReviewRequest; import likelion.MZConnent.dto.review.response.ReviewsSimpleResponse; +import likelion.MZConnent.dto.review.response.SaveReviewResponse; +import likelion.MZConnent.jwt.principle.UserPrinciple; import likelion.MZConnent.service.review.ReviewService; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.PageRequest; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; @RestController @RequiredArgsConstructor @@ -23,4 +32,32 @@ ResponseEntity getReviewSimpleList(@RequestParam(required = PageContentResponse response = reviewService.getReviewsSimpleList(keyword, page); return ResponseEntity.ok(response); } + + @PostMapping(value="/api/reviews/culture/{cultureId}", consumes = {"multipart/form-data"}) + public ResponseEntity saveReview( + @AuthenticationPrincipal UserPrinciple userPrinciple, + @RequestPart("info") String info, + @RequestPart(value = "reviewImage1", required = true) MultipartFile reviewImage1, + @RequestPart(value = "reviewImage2", required = false) MultipartFile reviewImage2, + @RequestPart(value = "reviewImage3", required = false) MultipartFile reviewImage3, + @RequestPart(value = "reviewImage4", required = false) MultipartFile reviewImage4, + @PathVariable Long cultureId) throws JsonProcessingException { + + try { + ObjectMapper objectMapper = new ObjectMapper(); + SaveReviewRequest request = objectMapper.readValue(info, SaveReviewRequest.class); + + List images = new ArrayList<>(); + if (reviewImage1 != null) images.add(reviewImage1); + if (reviewImage2 != null) images.add(reviewImage2); + if (reviewImage3 != null) images.add(reviewImage3); + if (reviewImage4 != null) images.add(reviewImage4); + + SaveReviewResponse response = reviewService.createReview(userPrinciple.getEmail(), request, images, cultureId); + return ResponseEntity.ok(response); + } catch (IOException e) { + log.error("리뷰 저장 실패", e); + return ResponseEntity.status(500).body(null); + } + } } diff --git a/src/main/java/likelion/MZConnent/dto/review/request/SaveReviewRequest.java b/src/main/java/likelion/MZConnent/dto/review/request/SaveReviewRequest.java new file mode 100644 index 0000000..57a9a32 --- /dev/null +++ b/src/main/java/likelion/MZConnent/dto/review/request/SaveReviewRequest.java @@ -0,0 +1,24 @@ +package likelion.MZConnent.dto.review.request; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +@Slf4j +@Getter +@NoArgsConstructor +public class SaveReviewRequest { + private String title; + private String content; + + @Builder + public SaveReviewRequest(String title, String content, List reviewImageUrls) { + this.title = title; + this.content = content; + } +} diff --git a/src/main/java/likelion/MZConnent/dto/review/response/SaveReviewResponse.java b/src/main/java/likelion/MZConnent/dto/review/response/SaveReviewResponse.java new file mode 100644 index 0000000..b857d79 --- /dev/null +++ b/src/main/java/likelion/MZConnent/dto/review/response/SaveReviewResponse.java @@ -0,0 +1,68 @@ +package likelion.MZConnent.dto.review.response; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.time.LocalDateTime; +import java.util.List; + +@Slf4j +@Getter +@NoArgsConstructor +public class SaveReviewResponse { + private Long reviewId; + private ReviewerDto reviewer; + private CultureDto culture; + private String title; + private String reviewImageUrl1; + private String reviewImageUrl2; + private String reviewImageUrl3; + private String reviewImageUrl4; + private LocalDateTime createdDate; + private int likeCount; + + @Builder + public SaveReviewResponse(Long reviewId, ReviewerDto reviewer, CultureDto culture, String title, String reviewImageUrl1, String reviewImageUrl2, String reviewImageUrl3, String reviewImageUrl4, LocalDateTime createdDate, int likeCount) { + this.reviewId = reviewId; + this.reviewer = reviewer; + this.culture = culture; + this.title = title; + this.reviewImageUrl1 = reviewImageUrl1; + this.reviewImageUrl2 = reviewImageUrl2; + this.reviewImageUrl3 = reviewImageUrl3; + this.reviewImageUrl4 = reviewImageUrl4; + this.createdDate = createdDate; + this.likeCount = likeCount; + } + + @Getter + @NoArgsConstructor + public static class ReviewerDto { + private Long userId; + private String username; + private String profileImage; + + @Builder + public ReviewerDto(Long userId, String username, String profileImage) { + this.userId = userId; + this.username = username; + this.profileImage = profileImage; + } + } + + @Getter + @NoArgsConstructor + public static class CultureDto { + private Long cultureId; + private String cultureName; + + @Builder + public CultureDto(Long cultureId, String cultureName) { + this.cultureId = cultureId; + this.cultureName = cultureName; + } + } + +} diff --git a/src/main/java/likelion/MZConnent/service/review/ReviewService.java b/src/main/java/likelion/MZConnent/service/review/ReviewService.java index 1aafd07..a9b597b 100644 --- a/src/main/java/likelion/MZConnent/service/review/ReviewService.java +++ b/src/main/java/likelion/MZConnent/service/review/ReviewService.java @@ -1,9 +1,16 @@ package likelion.MZConnent.service.review; +import likelion.MZConnent.domain.culture.Culture; +import likelion.MZConnent.domain.member.Member; import likelion.MZConnent.domain.review.Review; import likelion.MZConnent.dto.paging.response.PageContentResponse; +import likelion.MZConnent.dto.review.request.SaveReviewRequest; import likelion.MZConnent.dto.review.response.ReviewsSimpleResponse; +import likelion.MZConnent.dto.review.response.SaveReviewResponse; +import likelion.MZConnent.repository.culture.CultureRepository; +import likelion.MZConnent.repository.member.MemberRepository; import likelion.MZConnent.repository.review.ReviewRepository; +import likelion.MZConnent.service.image.S3ImageService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Page; @@ -11,17 +18,22 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; -import java.util.Collections; +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; -import java.util.stream.Stream; @Service @Slf4j @RequiredArgsConstructor public class ReviewService { private final ReviewRepository reviewRepository; + private final S3ImageService s3ImageService; + private final MemberRepository memberRepository; + private final CultureRepository cultureRepository; private final int PAGE_SIZE = 6; public PageContentResponse getReviewsSimpleList(String keyword, int page) { @@ -43,4 +55,63 @@ public PageContentResponse getReviewsSimpleList(String ke .build(); } + + public SaveReviewResponse createReview(String email, SaveReviewRequest request, List images, Long cultureId) throws IOException { + List imageUrls = uploadImages(images); + + Member member = memberRepository.findByEmail(email).orElseThrow(() -> new IllegalArgumentException("회원 정보를 찾을 수 없습니다.")); + Culture culture = cultureRepository.findById(cultureId).orElseThrow(() -> new IllegalArgumentException("문화 정보를 찾을 수 없습니다.")); + + Review review = buildReview(request, imageUrls, member, culture); + review = reviewRepository.save(review); + + return buildSaveReviewResponse(review, member, culture); + } + + private List uploadImages(List images) throws IOException { + List imageUrls = new ArrayList<>(); + for (MultipartFile image : images) { + String imageUrl = s3ImageService.upload(image, "reviews"); + imageUrls.add(imageUrl); + } + return imageUrls; + } + + private Review buildReview(SaveReviewRequest request, List imageUrls, Member member, Culture culture) { + return Review.builder() + .title(request.getTitle()) + .content(request.getContent()) + .reviewImageUrl1(imageUrls.size() > 0 ? imageUrls.get(0) : null) + .reviewImageUrl2(imageUrls.size() > 1 ? imageUrls.get(1) : null) + .reviewImageUrl3(imageUrls.size() > 2 ? imageUrls.get(2) : null) + .reviewImageUrl4(imageUrls.size() > 3 ? imageUrls.get(3) : null) + .createdDate(LocalDateTime.now()) + .likeCount(0) + .commentCount(0) + .culture(culture) + .member(member) + .build(); + } + + private SaveReviewResponse buildSaveReviewResponse(Review review, Member member, Culture culture) { + return SaveReviewResponse.builder() + .reviewId(review.getReviewId()) + .reviewer(SaveReviewResponse.ReviewerDto.builder() + .userId(member.getId()) + .username(member.getUsername()) + .profileImage(member.getProfileImageUrl()) + .build()) + .culture(SaveReviewResponse.CultureDto.builder() + .cultureId(culture.getCultureId()) + .cultureName(culture.getName()) + .build()) + .title(review.getTitle()) + .reviewImageUrl1(review.getReviewImageUrl1()) + .reviewImageUrl2(review.getReviewImageUrl2()) + .reviewImageUrl3(review.getReviewImageUrl3()) + .reviewImageUrl4(review.getReviewImageUrl4()) + .createdDate(review.getCreatedDate()) + .likeCount(review.getLikeCount()) + .build(); + } } From 0d493a6efcc2417790d8d5070fea915084db3ba9 Mon Sep 17 00:00:00 2001 From: oosedus Date: Mon, 29 Jul 2024 21:56:30 +0900 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=EB=AA=A8=EC=9E=84=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20=EB=AC=B8=ED=99=94=EC=97=90=20clubCount=20?= =?UTF-8?q?=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/likelion/MZConnent/domain/culture/Culture.java | 2 ++ src/main/java/likelion/MZConnent/service/club/ClubService.java | 1 + 2 files changed, 3 insertions(+) diff --git a/src/main/java/likelion/MZConnent/domain/culture/Culture.java b/src/main/java/likelion/MZConnent/domain/culture/Culture.java index 464cce3..622eca1 100644 --- a/src/main/java/likelion/MZConnent/domain/culture/Culture.java +++ b/src/main/java/likelion/MZConnent/domain/culture/Culture.java @@ -8,11 +8,13 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; import java.util.List; @Entity @Getter +@Setter @NoArgsConstructor public class Culture { @Id diff --git a/src/main/java/likelion/MZConnent/service/club/ClubService.java b/src/main/java/likelion/MZConnent/service/club/ClubService.java index 77d5e34..131f899 100644 --- a/src/main/java/likelion/MZConnent/service/club/ClubService.java +++ b/src/main/java/likelion/MZConnent/service/club/ClubService.java @@ -32,6 +32,7 @@ public class ClubService { public CreateClubResponse createClub(CreateClubRequest request, Member member) { Culture culture = cultureRepository.findById(request.getCultureId()).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 문화입니다.")); + culture.setClubCount(culture.getClubCount() + 1); RegionCategory region = regionCategoryRepository.findById(request.getRegionId()).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 지역입니다.")); Club club = Club.builder()