Skip to content

Commit

Permalink
Merge pull request #144 from oduck-team/feature/140
Browse files Browse the repository at this point in the history
주간 인기 애니 조회 #140
  • Loading branch information
FaberJoo authored Dec 9, 2023
2 parents da81904 + 9697c48 commit 691d028
Show file tree
Hide file tree
Showing 18 changed files with 395 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import io.oduck.api.domain.anime.entity.Quarter;
import io.oduck.api.domain.anime.entity.Status;
import io.oduck.api.domain.anime.service.AnimeService;
import io.oduck.api.domain.weekly.dto.WeeklyRes.WeeklyAnimeRes;
import io.oduck.api.domain.weekly.service.WeeklyAnimeService;
import io.oduck.api.global.common.OrderDirection;
import io.oduck.api.global.common.SliceResponse;
import io.oduck.api.global.exception.BadRequestException;
Expand Down Expand Up @@ -36,6 +38,7 @@
public class AnimeController {

private final AnimeService animeService;
private final WeeklyAnimeService weeklyAnimeService;

// 애니 검색 조회
@GetMapping
Expand Down Expand Up @@ -67,6 +70,12 @@ public ResponseEntity<Object> getAnimesBySearchCondition(
return ResponseEntity.ok(res);
}

@GetMapping("/weekly")
public ResponseEntity<?> getWeeklyAnimes() {
List<WeeklyAnimeRes> weeklyAnime = weeklyAnimeService.getWeeklyAnime();
return ResponseEntity.ok(weeklyAnime);
}

// 애니 아이디로 상세 조회
@GetMapping("/{animeId}")
public ResponseEntity<Object> getAnimeById(@PathVariable Long animeId){
Expand Down
35 changes: 32 additions & 3 deletions src/main/java/io/oduck/api/domain/anime/entity/Anime.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.oduck.api.domain.anime.entity;

import io.oduck.api.domain.series.entity.Series;
import io.oduck.api.domain.weekly.entity.WeeklyAnime;
import io.oduck.api.global.audit.BaseEntity;
import io.oduck.api.global.exception.BadRequestException;
import jakarta.persistence.CascadeType;
Expand All @@ -15,6 +16,7 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -35,16 +37,16 @@ public class Anime extends BaseEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false, length = 50)
@Column(nullable = false, length = 100)
private String title;

@Column(nullable = false, length = 600)
@Column(nullable = false, length = 1000)
private String summary;

@Enumerated(EnumType.STRING)
private BroadcastType broadcastType;

@Column(nullable = false)
@Column(nullable = true)
private int episodeCount;

@Column(nullable = true, length = 500)
Expand Down Expand Up @@ -100,32 +102,55 @@ public class Anime extends BaseEntity {
@Builder.Default
private List<AnimeGenre> animeGenres = new ArrayList<>();

@OneToOne(mappedBy = "anime", cascade = CascadeType.PERSIST)
private WeeklyAnime weeklyAnime;

/**
* 비즈니스 메소드
*/
// 조회수 증가
public void increaseViewCount(){
viewCount++;
if (weeklyAnime == null) {
weeklyAnime = WeeklyAnime.createWeeklyAnime(this);
}
weeklyAnime.increaseViewCount();
}

// 리뷰수 증가(짧은 리뷰, 장문 리뷰)
public void increaseReviewCount(){
reviewCount++;
if (weeklyAnime == null) {
weeklyAnime = WeeklyAnime.createWeeklyAnime(this);
}
weeklyAnime.increaseReviewCount();
}

// 리뷰수 감소(짧은 리뷰, 장문 리뷰)
public void decreaseReviewCount(){
reviewCount--;
if (weeklyAnime == null) {
weeklyAnime = WeeklyAnime.createWeeklyAnime(this);
}
weeklyAnime.decreaseReviewCount();
}

// 북마크수 증가
public void increaseBookmarkCount(){
bookmarkCount++;
if (weeklyAnime == null) {
weeklyAnime = WeeklyAnime.createWeeklyAnime(this);
}
weeklyAnime.increaseBookmarkCount();
}

// 북마크수 감소
public void decreaseBookmarkCount(){
bookmarkCount--;
if (weeklyAnime == null) {
weeklyAnime = WeeklyAnime.createWeeklyAnime(this);
}
weeklyAnime.decreaseBookmarkCount();
}

// 애니 공개 전환
Expand Down Expand Up @@ -257,6 +282,10 @@ public void updateAnimeGenre(List<AnimeGenre> animeGenres) {
}
}

public void updateWeeklyAnime(WeeklyAnime weeklyAnime) {
this.weeklyAnime = weeklyAnime;
}

public void update(String title, String summary, BroadcastType broadcastType, int episodeCount,
String thumbnail, int year, Quarter quarter, Rating rating, Status status, boolean isReleased,
List<AnimeOriginalAuthor> animeOriginalAuthors, List<AnimeStudio> animeStudios,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ public void save(PostReq postReq) {
}

@Override
@Transactional(readOnly = true)
@Transactional
public DetailResult getAnimeById(Long animeId) {

Anime anime = animeRepository.findAnimeByConditions(animeId, true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package io.oduck.api.domain.genre.repository;

import io.oduck.api.domain.genre.entity.Genre;
import java.util.List;

public interface GenreRepositoryCustom {

List<Genre> findAllByAnimeId(Long animeId);
boolean existsByName(String name);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package io.oduck.api.domain.genre.repository;

import static io.oduck.api.domain.anime.entity.QAnimeGenre.animeGenre;
import static io.oduck.api.domain.genre.entity.QGenre.genre;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import io.oduck.api.domain.anime.entity.QAnimeGenre;
import io.oduck.api.domain.genre.entity.Genre;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

Expand All @@ -13,6 +18,17 @@ public class GenreRepositoryCustomImpl implements GenreRepositoryCustom{

private final JPAQueryFactory queryFactory;

@Override
public List<Genre> findAllByAnimeId(Long animeId) {
JPAQuery<Genre> genreJPAQuery = queryFactory.select(genre)
.from(genre)
.join(animeGenre).on(animeGenre.anime.id.eq(animeId))
.where(
genre.deletedAt.isNull()
);
return genreJPAQuery.fetch();
}

@Override
public boolean existsByName(String name) {
Integer fetchOne = queryFactory
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,14 @@ public static class ShortReviewResWithTitle implements EntityBased {
private LocalDateTime createdAt;

public static ShortReviewResWithTitle of(ShortReviewDslWithTitle shortReviewDsl) {
Integer score = shortReviewDsl.getScore();
return ShortReviewResWithTitle
.builder()
.reviewId(shortReviewDsl.getReviewId())
.animeId(shortReviewDsl.getAnimeId())
.title(shortReviewDsl.getTitle())
.thumbnail(shortReviewDsl.getThumbnail())
.score(shortReviewDsl.getScore())
.score(score != null ? score : -1)
.content(shortReviewDsl.getContent())
.isSpoiler(shortReviewDsl.getIsSpoiler())
.likeCount(shortReviewDsl.getLikeCount())
Expand All @@ -92,7 +93,7 @@ public static ShortReviewResWithTitle of(ShortReviewDslWithTitle shortReviewDsl)
@Override
public String bringCursor(String property) {
return switch (property) {
case "title" -> this.title + ", " + this.createdAt.toString();
case "title" -> this.title;
case "score" -> this.score.toString() + ", " + this.createdAt.toString();
default -> this.createdAt.toString();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ private BooleanExpression cursorCondition(String cursor, Pageable pageable) {
.or(starRating.score.loe(score)
.and(shortReview.createdAt.lt(scoreCreateAt)));
}
case "title":
if (direction == Direction.ASC) {
return anime.title.gt(cursor);
} else {
return anime.title.lt(cursor);
}
default:
if (direction == Direction.ASC) {
return shortReview.createdAt.gt(LocalDateTime.parse(cursor));
Expand All @@ -160,6 +166,8 @@ private List<Path> sortPath(String property) {
case "score":
path.add(starRating);
path.add(shortReview);
case "title":
path.add(anime);
default:
path.add(shortReview);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,23 @@ public void save(Long memberId, ShortReviewReq shortReviewReq) {

//애니 입력
Anime anime = animeRepository.findByIdForUpdate(shortReviewReq.getAnimeId())
.orElseThrow(
() -> new NotFoundException("Anime")
);
.orElseThrow(
() -> new NotFoundException("Anime")
);

//회원 입력
Member member = memberRepository.findById(memberId)
.orElseThrow(
() -> new NotFoundException("Member")
);
.orElseThrow(
() -> new NotFoundException("Member")
);

ShortReview shortReview = ShortReview
.builder()
.anime(anime)
.member(member)
.content(shortReviewReq.getContent())
.hasSpoiler(shortReviewReq.isHasSpoiler())
.build();
.builder()
.anime(anime)
.member(member)
.content(shortReviewReq.getContent())
.hasSpoiler(shortReviewReq.isHasSpoiler())
.build();

anime.increaseReviewCount();
shortReviewRepository.save(shortReview);
Expand Down Expand Up @@ -95,9 +95,9 @@ public SliceResponse<ShortReviewRes> getShortReviews(Long animeId, String cursor
);

List<ShortReviewRes> res = shortReviews.getContent()
.stream()
.map(ShortReviewRes::of)
.toList();
.stream()
.map(ShortReviewRes::of)
.toList();

return SliceResponse.of(shortReviews, res, sort.getSort());
}
Expand All @@ -106,8 +106,8 @@ public SliceResponse<ShortReviewRes> getShortReviews(Long animeId, String cursor
public ShortReviewCountRes getShortReviewCountByMemberId(Long memberId) {
Long count = shortReviewRepository.countByMemberId(memberId);
return ShortReviewCountRes.builder()
.count(count)
.build();
.count(count)
.build();
}

@Override
Expand All @@ -118,7 +118,7 @@ public SliceResponse<ShortReviewResWithTitle> getShortReviewsByMemberId(Long mem
sort.getSort()
);

if(sort.equals(SortForProfile.TITLE) || sort.equals(SortForProfile.SCORE)){
if(sort.equals(SortForProfile.SCORE)){
sortList = sortList.and(Sort.by(Direction.DESC, "createdAt"));
}

Expand Down Expand Up @@ -146,9 +146,9 @@ public void update(Long memberId, Long reviewId, ShortReviewReq req) {
Long findMemberId = findShortReview.getMember().getId();

Anime findAnime = animeRepository.findByIdForUpdate(req.getAnimeId())
.orElseThrow(
() -> new NotFoundException("Anime")
);
.orElseThrow(
() -> new NotFoundException("Anime")
);
findAnime.decreaseReviewCount();

//리뷰 작성자 인지 확인
Expand All @@ -170,8 +170,8 @@ public void update(Long memberId, Long reviewId, ShortReviewReq req) {

private ShortReview getShortReview(Long reviewId){
return shortReviewRepository.findById(reviewId)
.orElseThrow(
() -> new NotFoundException("shortReview")
);
.orElseThrow(
() -> new NotFoundException("shortReview")
);
}
}
21 changes: 21 additions & 0 deletions src/main/java/io/oduck/api/domain/weekly/dto/WeeklyDsl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.oduck.api.domain.weekly.dto;

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

public class WeeklyDsl {
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class WeeklyAnimeDsl {
private Long animeId;
private String title;
private String thumbnail;
private Long scoreTotal;
private Long scoreCount;
private Double rankScore;
}
}
41 changes: 41 additions & 0 deletions src/main/java/io/oduck/api/domain/weekly/dto/WeeklyRes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package io.oduck.api.domain.weekly.dto;

import io.oduck.api.domain.weekly.dto.WeeklyDsl.WeeklyAnimeDsl;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

public class WeeklyRes {

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public static class WeeklyAnimeRes {
private Long animeId;
private String title;
private String thumbnail;
private List<String> genres;
private Double avgScore;
private Double rankScore;

public static WeeklyAnimeRes of(WeeklyAnimeDsl weeklyAnimeDsl) {

Double avgScore = weeklyAnimeDsl.getScoreCount() == 0 ? 0 : Double.valueOf(weeklyAnimeDsl.getScoreTotal()) / weeklyAnimeDsl.getScoreCount();
return WeeklyAnimeRes.builder()
.animeId(weeklyAnimeDsl.getAnimeId())
.title(weeklyAnimeDsl.getTitle())
.thumbnail(weeklyAnimeDsl.getThumbnail())
.avgScore(avgScore)
.rankScore(weeklyAnimeDsl.getRankScore())
.build();
}

public WeeklyAnimeRes withGenres(List<String> genres) {
this.genres = genres;
return this;
}
}
}
Loading

0 comments on commit 691d028

Please sign in to comment.