Skip to content

Commit

Permalink
[BSVR-257] 리뷰 수정 API 업데이트 - 요청 필드 추가, nullable 처리 (#185)
Browse files Browse the repository at this point in the history
* feat: spring 디폴트 프로필 local로 변경

* feat: UpdateReviewRequest에 stadiumId, rowNumber, reviewType 추가

* feat: UpdateReviewCommand에 stadiumId, rowNumber, reviewType 추가

* refactor: findByBlockIdAndSeatNumber 메서드 이름 변경

* feat: block id와 number로 BlockRow 엔티티 조회해오는 repository 메서드 구현

* feat: 리팩토링 위한 ReviewLocationInfo 도메인 생성

* feat: ReviewDataProcessor에 업데이트 로직 이관

* feat: ReviewDataProcessor에 업데이트된 리뷰 생성 로직 이관

* feat: processReviewDetails 메서드 reviewCreationProcessor로 리팩토링

* feat: ReviewKeywordProcessor에 업데이트쪽 updateBlockTopKeywords 메서드 이동

* feat: Processor를 적용해 UpdatteReviewService 리팩토링

* refactor: 더이상 사용하지 않는 UpdateReviewService 필드 삭제
  • Loading branch information
pminsung12 authored Sep 8, 2024
1 parent 1687b42 commit 586fcbd
Show file tree
Hide file tree
Showing 17 changed files with 240 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,34 @@

import org.depromeet.spot.common.exception.review.ReviewException.InvalidReviewDateTimeFormatException;
import org.depromeet.spot.common.exception.review.ReviewException.InvalidReviewKeywordsException;
import org.depromeet.spot.domain.review.Review.ReviewType;
import org.depromeet.spot.usecase.port.in.review.UpdateReviewUsecase.UpdateReviewCommand;

public record UpdateReviewRequest(
@NotNull Long stadiumId,
@NotNull Long blockId,
@NotNull Integer seatNumber,
Integer rowNumber,
Integer seatNumber,
@Size(min = 1, max = 3) List<String> images,
List<String> good,
List<String> bad,
String content,
@NotNull String dateTime) {
@NotNull String dateTime,
ReviewType reviewType) {

public UpdateReviewCommand toCommand() {
validateGoodAndBad();
return UpdateReviewCommand.builder()
.stadiumId(stadiumId)
.blockId(blockId)
.rowNumber(rowNumber)
.seatNumber(seatNumber)
.images(images)
.good(good)
.bad(bad)
.content(content)
.dateTime(toLocalDateTime(dateTime))
.reviewType(reviewType)
.build();
}

Expand Down
2 changes: 1 addition & 1 deletion application/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ server:
spring:
# 서브모듈 profile
profiles:
active: dev
active: local
group:
local:
- jpa
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.depromeet.spot.domain.review;

import org.depromeet.spot.domain.block.Block;
import org.depromeet.spot.domain.block.BlockRow;
import org.depromeet.spot.domain.seat.Seat;
import org.depromeet.spot.domain.section.Section;

public record ReviewLocationInfo(Section section, Block block, BlockRow row, Seat seat) {}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public interface BlockRowJpaRepository extends JpaRepository<BlockRowEntity, Lon
"select r from BlockRowEntity r "
+ "join fetch r.block b "
+ "where b.stadiumId = :stadiumId and b.code = :blockCode and r.number = :rowNumber")
BlockRowEntity findByBlockAndNumber(
BlockRowEntity findByCodeAndNumber(
@Param("stadiumId") Long stadiumId,
@Param("blockCode") String blockCode,
@Param("rowNumber") int rowNumber);
Expand All @@ -28,4 +28,6 @@ BlockRowEntity findByBlockAndNumber(
+ "order by r.number asc")
List<BlockRowEntity> findAllByStadiumAndBlock(
@Param("stadiumId") Long stadiumId, @Param("code") String code);

BlockRowEntity findByBlockIdAndNumber(Long blockId, Integer number);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ public List<BlockRow> findAllByBlock(Long blockId) {
@Override
public BlockRow findBy(long stadiumId, String blockCode, int rowNumber) {
BlockRowEntity entity =
blockRowJpaRepository.findByBlockAndNumber(stadiumId, blockCode, rowNumber);
blockRowJpaRepository.findByCodeAndNumber(stadiumId, blockCode, rowNumber);
return entity.toDomain();
}

@Override
public BlockRow findBy(Long blockId, Integer rowNumber) {
BlockRowEntity entity = blockRowJpaRepository.findByBlockIdAndNumber(blockId, rowNumber);
return entity.toDomain();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ public Seat findById(Long seatId) {
}

@Override
public Seat findByIdWith(Long seatId) {
public Seat findByBlockIdAndSeatNumber(Long seatId) {
SeatEntity entity =
seatJpaRepository.findByIdWith(seatId).orElseThrow(SeatNotFoundException::new);
return entity.toDomain();
}

@Override
public Seat findByIdWith(Long blockId, Integer seatNumber) {
public Seat findByBlockIdAndSeatNumber(Long blockId, Integer seatNumber) {
SeatEntity entity =
seatJpaRepository
.findByIdWith(blockId, seatNumber)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.List;

import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.domain.review.Review.ReviewType;

import lombok.Builder;

Expand All @@ -16,13 +17,16 @@ public interface UpdateReviewUsecase {

@Builder
record UpdateReviewCommand(
Long stadiumId,
Long blockId,
Integer rowNumber,
Integer seatNumber,
List<String> images,
List<String> good,
List<String> bad,
String content,
LocalDateTime dateTime) {}
LocalDateTime dateTime,
ReviewType reviewType) {}

record UpdateReviewResult(Review review) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ public interface BlockRowRepository {
List<BlockRow> findAllByBlock(Long blockId);

BlockRow findBy(long stadiumId, String blockCode, int rowNumber);

BlockRow findBy(Long blockId, Integer rowNumber);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ public interface SeatRepository {

Seat findById(Long seatId);

Seat findByIdWith(Long seatId);
Seat findByBlockIdAndSeatNumber(Long seatId);

Seat findByIdWith(Long blockId, Integer seatNumber);
Seat findByBlockIdAndSeatNumber(Long blockId, Integer seatNumber);

Map<BlockRow, List<Seat>> findSeatsGroupByRowInBlock(Block block);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.depromeet.spot.usecase.service.review;

import java.util.List;
import java.util.Map;

import org.depromeet.spot.domain.member.Member;
Expand Down Expand Up @@ -41,7 +40,8 @@ public CreateReviewResult create(Long blockId, Long memberId, CreateReviewComman

Review review = reviewCreationProcessor.createReview(blockId, member, command);

Map<Long, Keyword> keywordMap = processReviewDetails(review, command);
Map<Long, Keyword> keywordMap =
reviewCreationProcessor.processReviewDetails(review, command);

Review savedReview = reviewRepository.save(review);
reviewKeywordProcessor.updateBlockTopKeywords(savedReview);
Expand Down Expand Up @@ -69,30 +69,13 @@ public void createAdmin(
reviewCreationProcessor.createAdminReview(
stadiumId, blockCode, rowNumber, member, command);

Map<Long, Keyword> keywordMap = processAdminReviewDetails(review, command);
Map<Long, Keyword> keywordMap =
reviewCreationProcessor.processAdminReviewDetails(review, command);

Review savedReview = reviewRepository.save(review);
reviewKeywordProcessor.updateBlockTopKeywords(savedReview);
savedReview.setKeywordMap(keywordMap);

memberLevelProcessor.calculateAndUpdateMemberLevel(member);
}

private Map<Long, Keyword> processReviewDetails(Review review, CreateReviewCommand command) {
Map<Long, Keyword> keywordMap =
reviewKeywordProcessor.processKeywords(review, command.good(), command.bad());
review.setKeywordMap(keywordMap);
reviewImageProcessor.processImages(review, command.images());
return keywordMap;
}

private Map<Long, Keyword> processAdminReviewDetails(
Review review, CreateAdminReviewCommand command) {
Map<Long, Keyword> keywordMap =
reviewKeywordProcessor.processKeywords(review, command.good(), command.bad());
review.setKeywordMap(keywordMap);
List<String> imageUrls = reviewImageProcessor.getImageUrl(command.images());
reviewImageProcessor.processImages(review, imageUrls);
return keywordMap;
}
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
package org.depromeet.spot.usecase.service.review;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.depromeet.spot.common.exception.review.ReviewException.UnauthorizedReviewModificationException;
import org.depromeet.spot.domain.member.Member;
import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.domain.review.image.ReviewImage;
import org.depromeet.spot.domain.review.keyword.Keyword;
import org.depromeet.spot.domain.review.keyword.ReviewKeyword;
import org.depromeet.spot.domain.seat.Seat;
import org.depromeet.spot.usecase.port.in.review.UpdateReviewUsecase;
import org.depromeet.spot.usecase.port.out.review.BlockTopKeywordRepository;
import org.depromeet.spot.usecase.port.out.review.KeywordRepository;
import org.depromeet.spot.usecase.port.out.review.ReviewRepository;
import org.depromeet.spot.usecase.port.out.seat.SeatRepository;
import org.depromeet.spot.usecase.service.review.processor.ReviewCreationProcessor;
import org.depromeet.spot.usecase.service.review.processor.ReviewDataProcessor;
import org.depromeet.spot.usecase.service.review.processor.ReviewKeywordProcessor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -33,33 +25,28 @@
public class UpdateReviewService implements UpdateReviewUsecase {

private final ReviewRepository reviewRepository;
private final SeatRepository seatRepository;
private final KeywordRepository keywordRepository;
private final BlockTopKeywordRepository blockTopKeywordRepository;
private final ReviewDataProcessor reviewDataProcessor;
private final ReviewKeywordProcessor reviewKeywordProcessor;
private final ReviewCreationProcessor reviewCreationProcessor;

public UpdateReviewResult updateReview(
Long memberId, Long reviewId, UpdateReviewCommand command) {
// 1. review id로 조회
Review existingReview = reviewRepository.findById(reviewId);

if (!existingReview.getMember().getId().equals(memberId)) {
throw new UnauthorizedReviewModificationException();
}

Member member = existingReview.getMember();
Seat seat = seatRepository.findByIdWith(command.blockId(), command.seatNumber());

// 새로운 Review 객체 생성
Review updatedReview = createUpdatedReview(reviewId, member, seat, command, existingReview);
// 2. 새로운 Review 객체 생성
Review updatedReview = reviewCreationProcessor.updateReviewData(existingReview, command);

// keyword와 image 처리
Map<Long, Keyword> keywordMap =
processKeywords(updatedReview, command.good(), command.bad());
processImages(updatedReview, command.images());
reviewCreationProcessor.processReviewDetails(updatedReview, command);

// 저장 및 blockTopKeyword 업데이트
Review savedReview = reviewRepository.save(updatedReview);
updateBlockTopKeywords(existingReview, savedReview);

reviewKeywordProcessor.updateBlockTopKeywords(existingReview, savedReview);
savedReview.setKeywordMap(keywordMap);

return new UpdateReviewResult(savedReview);
Expand All @@ -74,86 +61,4 @@ public void updateLikesCount(Review review) {
public void updateScrapsCount(Review review) {
reviewRepository.updateScrapsCount(review.getId(), review.getScrapsCount());
}

private Review createUpdatedReview(
Long reviewId,
Member member,
Seat seat,
UpdateReviewCommand command,
Review savedReview) {
return Review.builder()
.id(reviewId)
.member(member)
.stadium(seat.getStadium())
.section(seat.getSection())
.block(seat.getBlock())
.row(seat.getRow())
.seat(seat)
.dateTime(command.dateTime())
.content(command.content())
.likesCount(savedReview.getLikesCount())
.build();
}

private Map<Long, Keyword> processKeywords(
Review review, List<String> goodKeywords, List<String> badKeywords) {
Map<Long, Keyword> keywordMap = new HashMap<>();
processKeywordList(review, goodKeywords, true, keywordMap);
processKeywordList(review, badKeywords, false, keywordMap);

return keywordMap;
}

private void processKeywordList(
Review review,
List<String> keywordContents,
boolean isPositive,
Map<Long, Keyword> keywordMap) {
for (String content : keywordContents) {
Keyword keyword =
keywordRepository
.findByContent(content)
.orElseGet(
() ->
keywordRepository.save(
Keyword.create(null, content, isPositive)));

ReviewKeyword reviewKeyword = ReviewKeyword.create(null, keyword.getId());
review.addKeyword(reviewKeyword);
keywordMap.put(keyword.getId(), keyword);
}
}

private void processImages(Review review, List<String> imageUrls) {
for (String url : imageUrls) {
ReviewImage image = ReviewImage.create(null, review, url);
review.addImage(image);
}
}

private void updateBlockTopKeywords(Review oldReview, Review newReview) {
Set<Long> oldKeywordIds =
oldReview.getKeywords().stream()
.map(ReviewKeyword::getKeywordId)
.collect(Collectors.toSet());
Set<Long> newKeywordIds =
newReview.getKeywords().stream()
.map(ReviewKeyword::getKeywordId)
.collect(Collectors.toSet());

List<Long> decrementIds =
oldKeywordIds.stream()
.filter(id -> !newKeywordIds.contains(id))
.collect(Collectors.toList());

List<Long> incrementIds =
newKeywordIds.stream()
.filter(id -> !oldKeywordIds.contains(id))
.collect(Collectors.toList());

if (!decrementIds.isEmpty() || !incrementIds.isEmpty()) {
blockTopKeywordRepository.batchUpdateCounts(
newReview.getBlock().getId(), incrementIds, decrementIds);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package org.depromeet.spot.usecase.service.review.processor;

import java.util.Map;

import org.depromeet.spot.domain.member.Member;
import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.domain.review.keyword.Keyword;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase.CreateAdminReviewCommand;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase.CreateReviewCommand;
import org.depromeet.spot.usecase.port.in.review.UpdateReviewUsecase.UpdateReviewCommand;

public interface ReviewCreationProcessor {
Review createReview(Long blockId, Member member, CreateReviewCommand command);
Expand All @@ -14,4 +18,12 @@ Review createAdminReview(
int rowNumber,
Member member,
CreateAdminReviewCommand command);

Map<Long, Keyword> processReviewDetails(Review review, CreateReviewCommand command);

Map<Long, Keyword> processReviewDetails(Review review, UpdateReviewCommand command);

Map<Long, Keyword> processAdminReviewDetails(Review review, CreateAdminReviewCommand command);

Review updateReviewData(Review existingReview, UpdateReviewCommand command);
}
Loading

0 comments on commit 586fcbd

Please sign in to comment.