Skip to content

Commit

Permalink
Merge branch 'develop' into feature/98
Browse files Browse the repository at this point in the history
  • Loading branch information
FaberJoo committed Nov 10, 2023
2 parents 4a206fc + 452c135 commit 54f6c1f
Show file tree
Hide file tree
Showing 19 changed files with 608 additions and 94 deletions.
20 changes: 20 additions & 0 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,26 @@ include::{snippets}/postAnime/success/http-response.adoc[]

==== 실패시

=== GET api/v1/oduckdmin/animes
.curl-request
include::{snippets}/getAdminAnimes/success/curl-request.adoc[]

.http-request
include::{snippets}/getAdminAnimes/success/http-request.adoc[]

.query-parameters
include::{snippets}/getAdminAnimes/success/query-parameters.adoc[]

.http-response
include::{snippets}/getAdminAnimes/success/http-response.adoc[]

.response-body
include::{snippets}/getAdminAnimes/success/response-body.adoc[]

.response-fields
include::{snippets}/getAdminAnimes/success/response-fields.adoc[]


=== PATCH api/v1/oduckdmin/animes/:id
.curl-request
include::{snippets}/patchAnime/success/curl-request.adoc[]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package io.oduck.api.domain.admin.controller;

import static io.oduck.api.domain.admin.dto.AdminReq.SearchFilter;

import io.oduck.api.domain.admin.dto.AdminReq;
import io.oduck.api.domain.admin.dto.AdminReq.QueryType;
import io.oduck.api.domain.admin.dto.AdminRes;
import io.oduck.api.domain.anime.dto.AnimeReq;
import io.oduck.api.domain.anime.service.AnimeService;
import io.oduck.api.domain.genre.dto.GenreReq;
Expand All @@ -16,7 +21,12 @@
import io.oduck.api.domain.voiceActor.dto.VoiceActorReq;
import io.oduck.api.domain.voiceActor.dto.VoiceActorRes;
import io.oduck.api.domain.voiceActor.service.VoiceActorService;
import io.oduck.api.global.common.OrderDirection;
import io.oduck.api.global.common.PageResponse;
import io.oduck.api.global.exception.BadRequestException;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -29,6 +39,7 @@
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Validated
Expand All @@ -54,17 +65,51 @@ public ResponseEntity<Object> postAnime(@RequestBody @Valid AnimeReq.PostReq req
return ResponseEntity.ok().build();
}

// 관리자 애니 조회 (isReleased = false도 조회)
// @GetMapping("/animes")
// public ResponseEntity<Object> getAnimes(
// Pageable pageable, String query, SearchCondition condition
// ){
//
// //TODO: 애니 조회 로직 구현.
// Page<GetAnime> res = adminAnimeService.getAnimes(pageable, query, condition);
// return ResponseEntity
// .ok(PageResponse.of(null));
// }
// 관리자 애니 조회
@GetMapping("/animes")
public ResponseEntity<Object> getAnimes(
@RequestParam(required = false) String query,
QueryType queryType,
@RequestParam(required = false, defaultValue = "latest") AdminReq.Sort sort,
@RequestParam(required = false, defaultValue = "DESC") OrderDirection order,
@RequestParam(required = false, defaultValue = "1") int page,
@RequestParam(required = false, defaultValue = "20") @Min(1) @Max(100) int size,
SearchFilter searchFilter
){

validateQueryLength(query, 50);

int validatedPage = validatePage(page);

PageResponse<AdminRes.SearchResult> res = animeService.getPageByCondition(
query,
queryType,
validatedPage,
size,
sort,
order,
searchFilter
);

return ResponseEntity.ok(res);
}

private void validateQueryLength(String query, int maxLength) {
if(query != null) {
if(query.length() > maxLength){
throw new BadRequestException("글자수는 50자를 넘을 수 없습니다.");
}
}
}

private int validatePage(int page) {
// 클라이언트는 페이지 번호를 1부터 시작, 서버에서는 0부터 시작
if(page <= 1) {
return 0;
}else {
return page - 1;
}
}

//애니 관련 수정
@PatchMapping("/animes/{animeId}")
Expand All @@ -77,7 +122,6 @@ public ResponseEntity<Object> patchAnime(
return ResponseEntity.noContent().build();
}


// 애니 삭제
@DeleteMapping("/animes/{animeId}")
public ResponseEntity<Object> deleteAnime(@PathVariable Long animeId) {
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/io/oduck/api/domain/admin/dto/AdminReq.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.oduck.api.domain.admin.dto;

import io.oduck.api.domain.anime.entity.Status;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Getter;

public class AdminReq {

@Getter
@AllArgsConstructor
public static class SearchFilter {
private List<Integer> years;
private List<Status> statuses;
private Boolean isReleased;
}

@Getter
@AllArgsConstructor
public enum QueryType {
TITLE("title"),
SERIES("series"),
ID("id");

private final String type;
}

@Getter
@AllArgsConstructor
public enum Sort {
LATEST("createdAt"),
SERIES("series"),
TITLE("title"),
BOOKMARK_COUNT("bookmarkCount"),
SCORE_TOTAL("starRatingScoreTotal"),
SCORE_COUNT("starRatingCount"),
REVIEW_COUNT("reviewCount"),
VIEW_COUNT("viewCount");

private final String sort;
}
}
57 changes: 57 additions & 0 deletions src/main/java/io/oduck/api/domain/admin/dto/AdminRes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.oduck.api.domain.admin.dto;

import io.oduck.api.domain.anime.entity.Quarter;
import io.oduck.api.domain.anime.entity.Status;
import java.time.LocalDateTime;
import lombok.Getter;

public class AdminRes {

@Getter
public static class SearchResult {
private Long id;
private String title;
private String thumbnail;
private int year;
private Quarter quarter;
private Boolean isReleased;
private Status status;
private LocalDateTime createdAt;
private Long seriesId;
private String seriesTitle;
private Long bookmarkCount;
private Long starRatingScoreTotal;
private Long starRatingCount;
private double starRatingAvg;
private Long reviewCount;
private Long viewCount;

public SearchResult(Long id, String title, String thumbnail, int year, Quarter quarter,
boolean isReleased, Status status, LocalDateTime createdAt, Long seriesId, String seriesTitle,
Long bookmarkCount, Long starRatingScoreTotal, Long starRatingCount, Long reviewCount, Long viewCount) {
this.id = id;
this.title = title;
this.thumbnail = thumbnail;
this.year = year;
this.quarter = quarter;
this.isReleased = isReleased;
this.status = status;
this.createdAt = createdAt;
this.seriesId = seriesId;
this.seriesTitle = seriesTitle;
this.bookmarkCount = bookmarkCount;
this.starRatingScoreTotal = starRatingScoreTotal;
this.starRatingCount = starRatingCount;
this.starRatingAvg = calculateAvg(starRatingScoreTotal, starRatingCount);
this.reviewCount = reviewCount;
this.viewCount = viewCount;
}

private double calculateAvg(Long starRatingScoreTotal, Long starRatingCount) {
if(starRatingCount <= 0) {
return 0;
}
return starRatingScoreTotal / starRatingCount;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.oduck.api.domain.anime.dto.SearchFilterDsl;
import io.oduck.api.domain.anime.entity.BroadcastType;
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.global.common.OrderDirection;
import io.oduck.api.global.common.SliceResponse;
Expand Down Expand Up @@ -57,9 +58,11 @@ public ResponseEntity<Object> getAnimesBySearchCondition(
List<Quarter> quarters = searchFilter.getQuarters();
validateDuplicateQuarters(quarters);

SearchFilterDsl searchFilterDsl = new SearchFilterDsl(genreIds, broadcastTypes, episodeCountEnums, years, quarters);
List<Status> statuses = searchFilter.getStatuses();

SliceResponse<AnimeRes.SearchResult> res = animeService.getAnimesByCondition(query, cursor, sort,
SearchFilterDsl searchFilterDsl = new SearchFilterDsl(genreIds, broadcastTypes, episodeCountEnums, years, quarters, statuses);

SliceResponse<AnimeRes.SearchResult> res = animeService.getSliceByCondition(query, cursor, sort,
order, size, searchFilterDsl);
return ResponseEntity.ok(res);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import io.oduck.api.domain.anime.entity.BroadcastType;
import io.oduck.api.domain.anime.entity.Quarter;
import io.oduck.api.domain.anime.entity.Status;
import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
Expand All @@ -16,9 +17,10 @@ public class SearchFilterDsl {
List<EpisodeCountEnum> episodeCountEnums;
List<Integer> years;
List<Quarter> quarters;
List<Status> statuses;

public SearchFilterDsl(List<Long> genreIds, List<BroadcastType> broadcastTypes,
List<EpisodeCountEnum> episodeCountEnums, List<Integer> years, List<Quarter> quarters) {
List<EpisodeCountEnum> episodeCountEnums, List<Integer> years, List<Quarter> quarters, List<Status> statuses) {
this.genreIds = genreIds;
this.broadcastTypes = broadcastTypes;
this.episodeCountEnums = episodeCountEnums;
Expand All @@ -29,5 +31,7 @@ public SearchFilterDsl(List<Long> genreIds, List<BroadcastType> broadcastTypes,
.collect(Collectors.toList());

this.quarters = quarters;

this.statuses = statuses;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package io.oduck.api.domain.anime.repository;

import io.oduck.api.domain.admin.dto.AdminReq.QueryType;
import io.oduck.api.domain.admin.dto.AdminReq.SearchFilter;
import io.oduck.api.domain.admin.dto.AdminRes;
import io.oduck.api.domain.anime.dto.SearchFilterDsl;
import io.oduck.api.global.common.PageResponse;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;

import static io.oduck.api.domain.anime.dto.AnimeRes.SearchResult;

public interface AnimeRepositoryCustom {
Slice<SearchResult> findAnimesByCondition(String query, String cursor, Pageable pageable, SearchFilterDsl searchFilterDsl);
Slice<SearchResult> findSliceByCondition(String query, String cursor, Pageable pageable, SearchFilterDsl searchFilterDsl);

PageResponse<AdminRes.SearchResult> findPageByCondition(String query, QueryType queryType,
Pageable pageable, SearchFilter searchFilter);
}
Loading

0 comments on commit 54f6c1f

Please sign in to comment.