Skip to content

Commit

Permalink
Merge 41f4ec2 into 1836a2d
Browse files Browse the repository at this point in the history
  • Loading branch information
EunjiShin authored Jul 18, 2024
2 parents 1836a2d + 41f4ec2 commit bc65d0e
Show file tree
Hide file tree
Showing 39 changed files with 419 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.depromeet.spot.application.review;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;

import org.depromeet.spot.application.review.dto.request.CreateReviewRequest;
import org.depromeet.spot.application.review.dto.response.ReviewResponse;
import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

@RestController
@Tag(name = "리뷰")
@RequiredArgsConstructor
@RequestMapping("/api/v1")
public class CreateReviewController {

private final CreateReviewUsecase createReviewUsecase;

@ResponseStatus(HttpStatus.CREATED)
@Operation(summary = "특정 좌석에 신규 리뷰를 추가한다.")
@PostMapping("/seats/{seatId}/members/{memberId}/reviews")
public ReviewResponse create(
@PathVariable @Positive @NotNull final Long seatId,
@PathVariable @Positive @NotNull final Long memberId,
@RequestBody @Valid @NotNull CreateReviewRequest request) {
Review review = createReviewUsecase.create(seatId, memberId, request.toCommand());
return ReviewResponse.from(review);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.depromeet.spot.application.review.dto.request;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;

import org.depromeet.spot.common.exception.review.ReviewException.InvalidReviewDateTimeFormatException;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase.CreateReviewCommand;

public record CreateReviewRequest(
List<String> images, List<String> good, List<String> bad, String content, String dateTime) {

public CreateReviewCommand toCommand() {
return CreateReviewCommand.builder()
.images(images)
.good(good)
.bad(bad)
.content(content)
.dateTime(toLocalDateTime(dateTime))
.build();
}

private LocalDateTime toLocalDateTime(String dateTimeStr) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
try {
return LocalDateTime.parse(dateTimeStr, formatter);
} catch (DateTimeParseException e) {
throw new InvalidReviewDateTimeFormatException();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
@Getter
public enum ReviewErrorCode implements ErrorCode {
REVIEW_NOT_FOUND(HttpStatus.NOT_FOUND, "RV001", "요청한 리뷰를 찾을 수 없습니다."),
INVALID_REVIEW_DATA(HttpStatus.BAD_REQUEST, "RV002", "유효하지 않은 리뷰 데이터입니다.");
INVALID_REVIEW_DATA(HttpStatus.BAD_REQUEST, "RV002", "유효하지 않은 리뷰 데이터입니다."),
INVALID_REVIEW_DATETIME_FORMAT(
HttpStatus.BAD_REQUEST, "RV003", "리뷰 작성일시는 yyyy-MM-dd HH:mm 포맷이어야 합니다.");

private final HttpStatus status;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,14 @@ public InvalidReviewDataException(String str) {
super(ReviewErrorCode.INVALID_REVIEW_DATA.appended(str));
}
}

public static class InvalidReviewDateTimeFormatException extends ReviewException {
public InvalidReviewDateTimeFormatException() {
super(ReviewErrorCode.INVALID_REVIEW_DATETIME_FORMAT);
}

public InvalidReviewDateTimeFormatException(String str) {
super(ReviewErrorCode.INVALID_REVIEW_DATETIME_FORMAT.appended(str));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.depromeet.spot.common.exception.seat;

import org.depromeet.spot.common.exception.ErrorCode;
import org.springframework.http.HttpStatus;

import lombok.Getter;

@Getter
public enum SeatErrorCode implements ErrorCode {
SEAT_NOT_FOUND(HttpStatus.NOT_FOUND, "SEAT001", "요청 좌석이 존재하지 않습니다."),
;

private final HttpStatus status;
private final String code;
private String message;

SeatErrorCode(HttpStatus status, String code, String message) {
this.status = status;
this.code = code;
this.message = message;
}

public SeatErrorCode appended(Object o) {
message = message + " {" + o.toString() + "}";
return this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.depromeet.spot.common.exception.seat;

import org.depromeet.spot.common.exception.BusinessException;

public abstract class SeatException extends BusinessException {

protected SeatException(SeatErrorCode errorCode) {
super(errorCode);
}

public static class SeatNotFoundException extends SeatException {
public SeatNotFoundException() {
super(SeatErrorCode.SEAT_NOT_FOUND);
}

public SeatNotFoundException(Object obj) {
super(SeatErrorCode.SEAT_NOT_FOUND.appended(obj));
}
}
}
25 changes: 23 additions & 2 deletions domain/src/main/java/org/depromeet/spot/domain/review/Review.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import java.time.LocalDateTime;
import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
@Builder
@AllArgsConstructor
public class Review {

private final Long id;
Expand All @@ -18,11 +20,30 @@ public class Review {
private final Long rowId;
private final Long seatNumber;

private final LocalDateTime dateTime; // 시간은 미표기
private final LocalDateTime dateTime;
private final String content;
private final LocalDateTime createdAt;
private final LocalDateTime updatedAt;
private final LocalDateTime deletedAt;
private final List<ReviewImage> images;
private final List<ReviewKeyword> keywords;

public Review addImagesAndKeywords(
List<ReviewImage> newImages, List<ReviewKeyword> newKeywords) {
return new Review(
id,
userId,
stadiumId,
blockId,
seatId,
rowId,
seatNumber,
dateTime,
content,
createdAt,
updatedAt,
deletedAt,
newImages,
newKeywords);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
import lombok.Builder;
import lombok.Getter;

@Builder
@Getter
@Builder
public class ReviewImage {

private final Long id;
private final Long reviewId;
private final String url;
private final LocalDateTime createdAt;
private final LocalDateTime deletedAt;

public static ReviewImage of(Long reviewId, String url) {
return ReviewImage.builder().reviewId(reviewId).url(url).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.depromeet.spot.jpa.review.entity;

import java.time.LocalDateTime;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
Expand All @@ -24,12 +22,8 @@ public class ReviewImageEntity extends BaseEntity {
@Column(name = "url", nullable = false, length = 255)
private String url;

@Column(name = "deleted_at")
private LocalDateTime deletedAt;

public static ReviewImageEntity from(ReviewImage reviewImage) {
return new ReviewImageEntity(
reviewImage.getReviewId(), reviewImage.getUrl(), reviewImage.getDeletedAt());
return new ReviewImageEntity(reviewImage.getReviewId(), reviewImage.getUrl());
}

public ReviewImage toDomain() {
Expand All @@ -38,7 +32,6 @@ public ReviewImage toDomain() {
.reviewId(reviewId)
.url(url)
.createdAt(this.getCreatedAt())
.deletedAt(deletedAt)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.depromeet.spot.jpa.review.repository;

import org.depromeet.spot.jpa.review.entity.ReviewEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReviewJpaRepository extends JpaRepository<ReviewEntity, Long> {}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
@RequiredArgsConstructor
public class ReviewRepositoryImpl implements ReviewRepository {
private final ReviewCustomRepository reviewCustomRepository;
private final ReviewJpaRepository reviewJpaRepository;

@Override
public List<Review> findByBlockId(
Expand Down Expand Up @@ -51,6 +52,12 @@ public List<KeywordCount> findTopKeywordsByBlockId(Long stadiumId, Long blockId,
return reviewCustomRepository.findTopKeywordsByBlockId(stadiumId, blockId, limit);
}

@Override
public Review save(Review review) {
ReviewEntity entity = reviewJpaRepository.save(ReviewEntity.from(review));
return entity.toDomain();
}

private Review fetchReviewDetails(ReviewEntity reviewEntity) {
List<ReviewImageEntity> images =
reviewCustomRepository.findImagesByReviewIds(List.of(reviewEntity.getId()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.depromeet.spot.jpa.review.repository.image;

import org.depromeet.spot.jpa.review.entity.ReviewImageEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ReviewImageJpaRepository extends JpaRepository<ReviewImageEntity, Long> {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.depromeet.spot.jpa.review.repository.image;

import java.util.List;

import org.depromeet.spot.domain.review.ReviewImage;
import org.depromeet.spot.jpa.review.entity.ReviewImageEntity;
import org.depromeet.spot.usecase.port.out.review.ReviewImageRepository;
import org.springframework.stereotype.Repository;

import lombok.RequiredArgsConstructor;

@Repository
@RequiredArgsConstructor
public class ReviewImageRepositoryImpl implements ReviewImageRepository {

private final ReviewImageJpaRepository reviewImageJpaRepository;

@Override
public List<ReviewImage> saveAll(List<ReviewImage> images) {
List<ReviewImageEntity> entities =
reviewImageJpaRepository.saveAll(
images.stream().map(ReviewImageEntity::from).toList());
return entities.stream().map(ReviewImageEntity::toDomain).toList();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.depromeet.spot.jpa.seat.repository;

import org.depromeet.spot.jpa.seat.entity.SeatEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface SeatJpaRepository extends JpaRepository<SeatEntity, Long> {}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import java.util.List;

import org.depromeet.spot.common.exception.seat.SeatException.SeatNotFoundException;
import org.depromeet.spot.domain.seat.Seat;
import org.depromeet.spot.jpa.seat.entity.SeatEntity;
import org.depromeet.spot.usecase.port.out.seat.SeatRepository;
import org.springframework.stereotype.Repository;

Expand All @@ -13,9 +15,17 @@
public class SeatRepositoryImpl implements SeatRepository {

private final SeatJdbcRepository seatJdbcRepository;
private final SeatJpaRepository seatJpaRepository;

@Override
public void saveAll(List<Seat> seats) {
seatJdbcRepository.createSeats(seats);
}

@Override
public Seat findById(Long seatId) {
SeatEntity entity =
seatJpaRepository.findById(seatId).orElseThrow(SeatNotFoundException::new);
return entity.toDomain();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public interface UpdateMemberUsecase {

Member updateProfile(Long memberId, UpdateProfileCommand command);

void updateLevel(Long memberId, long reviewCnt);

@Builder
record UpdateProfileCommand(String profileImage, String nickname, Long teamId) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.depromeet.spot.usecase.port.in.review;

import java.time.LocalDateTime;
import java.util.List;

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

import lombok.Builder;

public interface CreateReviewUsecase {

Review create(Long seatId, Long memberId, CreateReviewCommand command);

@Builder
record CreateReviewCommand(
List<String> images,
List<String> good,
List<String> bad,
LocalDateTime dateTime,
String content) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.depromeet.spot.usecase.port.in.seat;

import org.depromeet.spot.domain.seat.Seat;

public interface ReadSeatUsecase {

Seat findById(Long seatId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.depromeet.spot.usecase.port.out.review;

import java.util.List;

import org.depromeet.spot.domain.review.ReviewImage;

public interface ReviewImageRepository {

List<ReviewImage> saveAll(List<ReviewImage> images);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,6 @@ List<Review> findByBlockId(
Long countByUserId(Long userId, Integer year, Integer month);

List<KeywordCount> findTopKeywordsByBlockId(Long stadiumId, Long blockId, int limit);

Review save(Review review);
}
Loading

0 comments on commit bc65d0e

Please sign in to comment.