Skip to content

Commit

Permalink
[Deploy] PROD Manual Deploy (#139)
Browse files Browse the repository at this point in the history
* fix: local profile에서 loki 비활성화 (#136)

* [BSVR-194] 리뷰 등록 어드민 API + 관련 작업들 (#137)

* feat: controller 추가

* feat: 어드민 리뷰 등록 서비스 코드 추가

* feat: 어드민 리뷰 생성 로직 수정

* fix: member, blockRow에서 발생하는 N+1 수정

* refactor: image, keyword 처리 로직을 클래스로 분리

* refactor: 클래스명 컨벤션에 맞게 level usecase 수정

* perf: value별 레벨 조회에 캐시 적용

* feat: content NotBlank 처리
  • Loading branch information
EunjiShin authored Aug 15, 2024
1 parent 60bb9b6 commit c0f20ea
Show file tree
Hide file tree
Showing 30 changed files with 364 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import org.depromeet.spot.application.member.dto.response.LevelUpDialogInfo;
import org.depromeet.spot.application.member.dto.response.LevelUpTableResponse;
import org.depromeet.spot.domain.member.Level;
import org.depromeet.spot.usecase.port.in.member.LevelUsecase;
import org.depromeet.spot.usecase.port.in.member.level.ReadLevelUsecase;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -26,20 +26,20 @@
@RequestMapping("/api/v1/levels")
public class ReadLevelController {

private final LevelUsecase levelUsecase;
private final ReadLevelUsecase readLevelUsecase;

@GetMapping("/info")
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "레벨업 조건 테이블 조회 API")
public List<LevelUpTableResponse> getLevelUpTable() {
return levelUsecase.findAllLevels().stream().map(LevelUpTableResponse::from).toList();
return readLevelUsecase.findAllLevels().stream().map(LevelUpTableResponse::from).toList();
}

@GetMapping("/up/info")
@ResponseStatus(HttpStatus.OK)
@Operation(summary = "레벨업 다이얼로그 조회 API")
public LevelUpDialogInfo getLevelUpDialogInfo(@RequestParam @NotNull @Positive int nextLevel) {
Level level = levelUsecase.findLevelUpDialogInfo(nextLevel);
Level level = readLevelUsecase.findLevelUpDialogInfo(nextLevel);
return LevelUpDialogInfo.from(level);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package org.depromeet.spot.application.review;

import java.util.List;

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

import org.depromeet.spot.application.common.annotation.CurrentMember;
import org.depromeet.spot.application.review.dto.request.CreateAdminReviewRequest;
import org.depromeet.spot.application.review.dto.request.CreateReviewRequest;
import org.depromeet.spot.application.review.dto.response.BaseReviewResponse;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase;
Expand All @@ -14,14 +18,18 @@
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.RequestPart;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@Tag(name = "리뷰")
@RequiredArgsConstructor
Expand All @@ -43,4 +51,19 @@ public BaseReviewResponse create(
createReviewUsecase.create(blockId, seatNumber, memberId, request.toCommand());
return BaseReviewResponse.from(result);
}

@CurrentMember
@ResponseStatus(HttpStatus.CREATED)
@Operation(summary = "[어드민] 특정 열에 신규 리뷰를 추가한다.")
@PostMapping(value = "/stadiums/{stadiumId}/blocks/{blockCode}/rows/{rowNumber}/reviews")
public void createAll(
@PathVariable @Positive @NotNull final long stadiumId,
@PathVariable @Positive @NotNull final String blockCode,
@PathVariable @Positive @NotNull final int rowNumber,
@Parameter(hidden = true) Long memberId,
@RequestPart @Valid CreateAdminReviewRequest data,
@RequestPart @Size(min = 1, max = 3) List<MultipartFile> images) {
createReviewUsecase.createAdmin(
stadiumId, blockCode, rowNumber, memberId, data.toCommand(images));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
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 jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;

import org.depromeet.spot.common.exception.review.ReviewException.InvalidReviewDateTimeFormatException;
import org.depromeet.spot.common.exception.review.ReviewException.InvalidReviewKeywordsException;
import org.depromeet.spot.usecase.port.in.review.CreateReviewUsecase.CreateAdminReviewCommand;
import org.springframework.web.multipart.MultipartFile;

public record CreateAdminReviewRequest(
Integer seatNumber,
List<String> good,
List<String> bad,
@NotBlank String content,
@NotNull String dateTime) {

public CreateAdminReviewCommand toCommand(List<MultipartFile> images) {
checkHasKeyword();
return CreateAdminReviewCommand.builder()
.bad(bad)
.good(good)
.images(images)
.content(content)
.seatNumber(seatNumber)
.dateTime(toLocalDateTime(dateTime))
.build();
}

private void checkHasKeyword() {
if ((this.good == null || good.isEmpty()) && (bad == null || bad.isEmpty())) {
throw new InvalidReviewKeywordsException();
}
}

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();
}
}
}
1 change: 0 additions & 1 deletion application/src/main/resources/logback-spring.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<springProfile name="local">
<root level="INFO">
<appender-ref ref="CONSOLE_APPENDER"/>
<appender-ref ref="LOKI_APPENDER"/>
</root>
</springProfile>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public enum CacheType {
SECTION_SEATS("sectionSeatsCache", 100L, 60 * 60 * 24L),
BLOCK_SEATS("blockSeatsCache", 1_000L, 60 * 60 * 24L),
LEVEL_INFO("levelsCache", 1L, 60 * 60 * 1L),
LEVEL_VALUE_INFO("levelValuesCache", 6L, 60 * 60 * 1L),
;

private final String name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ public interface BlockRowJpaRepository extends JpaRepository<BlockRowEntity, Lon

@Query(
"select r from BlockRowEntity r "
+ "join fetch r.block b "
+ "where b.stadiumId = :stadiumId and b.code = :blockCode and r.number = :rowNumber")
BlockRowEntity findByBlockAndNumber(
@Param("stadiumId") Long stadiumId,
@Param("blockCode") String blockCode,
@Param("rowNumber") int rowNumber);

@Query(
"select r from BlockRowEntity r "
+ "join BlockEntity b on b.id = r.block.id "
+ "where r.block.stadiumId = :stadiumId "
+ "and r.block.code = :code "
+ "order by r.number asc")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,11 @@ public List<BlockRow> findAllByBlock(Long blockId) {
blockRowJpaRepository.findAllByBlockIdOrderByNumberAsc(blockId);
return entities.stream().map(BlockRowEntity::toDomain).toList();
}

@Override
public BlockRow findBy(long stadiumId, String blockCode, int rowNumber) {
BlockRowEntity entity =
blockRowJpaRepository.findByBlockAndNumber(stadiumId, blockCode, rowNumber);
return entity.toDomain();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
public interface MemberJpaRepository extends JpaRepository<MemberEntity, Long> {
Optional<MemberEntity> findByIdToken(String idToken);

@Query("select m from MemberEntity m " + "join fetch m.level l " + "where m.id = :id")
Optional<MemberEntity> findByIdWithLevel(@Param("id") Long id);

boolean existsByNickname(String nickname);

@Modifying
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ public boolean existsByNickname(String nickname) {
@Override
public Member findById(Long memberId) {
MemberEntity entity =
memberJpaRepository.findById(memberId).orElseThrow(MemberNotFoundException::new);
memberJpaRepository
.findByIdWithLevel(memberId)
.orElseThrow(MemberNotFoundException::new);
return entity.toDomain();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,7 @@ public class ReviewEntity extends BaseEntity {
private BlockRowEntity row;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(
name = "seat_id",
nullable = false,
foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
@JoinColumn(name = "seat_id", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
private SeatEntity seat;

@Column(name = "date_time", nullable = false)
Expand All @@ -96,14 +93,20 @@ public class ReviewEntity extends BaseEntity {
private List<ReviewKeywordEntity> keywords;

public static ReviewEntity from(Review review) {
SeatEntity seatEntity;
if (review.getSeat() == null) {
seatEntity = null;
} else {
seatEntity = SeatEntity.withSeat(review.getSeat());
}
ReviewEntity entity =
new ReviewEntity(
MemberEntity.withMember(review.getMember()),
StadiumEntity.withStadium(review.getStadium()),
SectionEntity.withSection(review.getSection()),
BlockEntity.withBlock(review.getBlock()),
BlockRowEntity.withBlockRow(review.getRow()),
SeatEntity.withSeat(review.getSeat()),
seatEntity,
review.getDateTime(),
review.getContent(),
new ArrayList<>(),
Expand All @@ -114,12 +117,12 @@ public static ReviewEntity from(Review review) {
entity.images =
review.getImages().stream()
.map(image -> ReviewImageEntity.from(image, entity))
.collect(Collectors.toList());
.toList();

entity.keywords =
review.getKeywords().stream()
.map(keyword -> ReviewKeywordEntity.from(keyword, entity))
.collect(Collectors.toList());
.toList();

return entity;
}
Expand All @@ -133,7 +136,7 @@ public Review toDomain() {
.section(this.section.toDomain())
.block(this.block.toDomain())
.row(this.row.toDomain())
.seat(this.seat.toDomain())
.seat((this.seat == null) ? null : this.seat.toDomain())
.dateTime(this.dateTime)
.content(this.content)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public static SeatEntity from(Seat seat) {
}

public static SeatEntity withSeat(Seat seat) {
if (seat == null) return null;
return new SeatEntity(seat);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;

import org.depromeet.spot.common.exception.section.SectionException.SectionNotFoundException;
import org.depromeet.spot.domain.section.Section;
import org.depromeet.spot.infrastructure.jpa.section.entity.SectionEntity;
import org.depromeet.spot.usecase.port.out.section.SectionRepository;
Expand Down Expand Up @@ -37,4 +38,11 @@ public void saveAll(List<Section> sections) {
public boolean existsInStadium(Long stadiumId, Long sectionId) {
return sectionJpaRepository.existsByStadiumIdAndId(stadiumId, sectionId);
}

@Override
public Section findById(Long id) {
SectionEntity entity =
sectionJpaRepository.findById(id).orElseThrow(SectionNotFoundException::new);
return entity.toDomain();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@
public interface ReadBlockRowUsecase {

List<BlockRow> findAllByBlock(Long blockId);

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

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.depromeet.spot.usecase.port.in.member.level;

import java.util.List;

import org.depromeet.spot.domain.member.Level;

public interface ReadLevelUsecase {

Level findInitialLevel();

Level findByValue(int value);

List<Level> findAllLevels();

Level findLevelUpDialogInfo(int nextLevel);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@
import org.depromeet.spot.domain.member.Member;
import org.depromeet.spot.domain.review.Review;
import org.depromeet.spot.domain.seat.Seat;
import org.springframework.web.multipart.MultipartFile;

import lombok.Builder;

public interface CreateReviewUsecase {
CreateReviewResult create(
Long blockId, Integer seatNumber, Long memberId, CreateReviewCommand command);

void createAdmin(
long stadiumId,
String blockCode,
int rowNumber,
Long memberId,
CreateAdminReviewCommand command);

@Builder
record CreateReviewCommand(
List<String> images,
Expand All @@ -21,5 +29,14 @@ record CreateReviewCommand(
String content,
LocalDateTime dateTime) {}

@Builder
record CreateAdminReviewCommand(
List<MultipartFile> images,
List<String> good,
List<String> bad,
String content,
Integer seatNumber,
LocalDateTime dateTime) {}

record CreateReviewResult(Review review, Member member, Seat seat) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public interface SectionReadUsecase {

void checkIsExistsInStadium(Long stadiumId, Long sectionId);

Section findById(Long id);

@Getter
@AllArgsConstructor
class StadiumSections {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public interface BlockRowRepository {
void createAll(List<BlockRow> rows);

List<BlockRow> findAllByBlock(Long blockId);

BlockRow findBy(long stadiumId, String blockCode, int rowNumber);
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ public interface SectionRepository {
void saveAll(List<Section> sections);

boolean existsInStadium(Long stadiumId, Long sectionId);

Section findById(Long id);
}
Loading

0 comments on commit c0f20ea

Please sign in to comment.