Skip to content

Commit

Permalink
Merge pull request #38 from BOOK-TALK/#26-genre-api
Browse files Browse the repository at this point in the history
#26 genre api
  • Loading branch information
chanwoo7 authored Aug 8, 2024
2 parents 0aa1047 + 5ff6c64 commit 95bbf4d
Show file tree
Hide file tree
Showing 12 changed files with 388 additions and 89 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.book.backend.domain.book.controller;

import com.book.backend.domain.book.service.BookRequestValidate;
import com.book.backend.domain.book.service.BookService;

import com.book.backend.domain.openapi.service.RequestValidate;
import com.book.backend.domain.openapi.dto.request.CustomHotTrendRequestDto;

import com.book.backend.domain.openapi.dto.request.HotTrendRequestDto;
import com.book.backend.domain.openapi.dto.request.KeywordRequestDto;
import com.book.backend.domain.openapi.dto.response.CustomHotTrendResponseDto;
Expand Down Expand Up @@ -35,7 +38,7 @@
@Slf4j
public class BookController {
private final BookService bookService;
private final RequestValidate requestValidate;
private final BookRequestValidate bookRequestValidate;
private final ResponseTemplate responseTemplate;

// 마니아(4), 다독자(5) 추천 API
Expand All @@ -46,7 +49,7 @@ public class BookController {
@GetMapping("/recommend")
public ResponseEntity<?> recommend(@RequestParam String isbn) throws Exception {
RequestLogger.param(new String[]{"isbn"}, isbn);
requestValidate.isValidIsbn(isbn);
bookRequestValidate.isValidIsbn(isbn);

RecommendRequestDto requestDto = RecommendRequestDto.builder().isbn13(isbn).build();
LinkedList<RecommendResponseDto> response = bookService.recommend(requestDto);
Expand All @@ -63,9 +66,11 @@ public ResponseEntity<?> recommend(@RequestParam String isbn) throws Exception {
responses = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = HotTrendResponseDto.class)),
description = HotTrendResponseDto.description)})
@GetMapping("/hotTrend")

public ResponseEntity<?> hotTrend() throws Exception {
LocalDate yesterday = LocalDate.now().minusDays(1);
HotTrendRequestDto requestDto = HotTrendRequestDto.builder().searchDt(yesterday.toString()).build();

LinkedList<HotTrendResponseDto> response = bookService.hotTrend(requestDto);

return responseTemplate.success(response, HttpStatus.OK);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.book.backend.domain.book.service;

import com.book.backend.exception.CustomException;
import com.book.backend.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class BookRequestValidate {

public void isValidSearchDt(String searchDt) {
//yyyy-mm-dd 형식인지 확인
if(!searchDt.matches("^\\d{4}-\\d{2}-\\d{2}$")) {
throw new CustomException(ErrorCode.INVALID_SEARCH_DT_FORMAT);
}
}

public void isValidIsbn(String isbn) {
// 숫자로 구성된 13자리 ISBN
if(!(isbn.matches("^[0-9]*$") && isbn.length() == 13)) {
throw new CustomException(ErrorCode.INVALID_ISBN);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,43 +1,102 @@
package com.book.backend.domain.genre.controller;

import com.book.backend.domain.book.entity.Book;
import com.book.backend.domain.genre.service.GenreRequestValidate;
import com.book.backend.domain.genre.service.GenreService;
import com.book.backend.domain.openapi.dto.request.LoanTrendRequestDto;
import com.book.backend.domain.openapi.dto.response.LoanTrendResponseDto;
import com.book.backend.global.ResponseTemplate;
import com.book.backend.global.log.RequestLogger;
import jakarta.validation.constraints.Pattern;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.LinkedList;

@RestController
@RequestMapping("/api/genre")
@RequiredArgsConstructor
@Slf4j
public class GenreController {
private final GenreService genreService;
private final GenreRequestValidate genreRequestValidate;
private final ResponseTemplate responseTemplate;

/**
* 대주제 KDC 번호(1자리) 입력 시 저장된 책 목록 리턴
* 일주일 인기순 - 중주제 KDC 번호(2자리) 입력 시 1주일 인기순 도서 목록 리턴
*/
@GetMapping("/main")
public List<Book> findBooksByMainKdcNum(@RequestParam @Pattern(regexp = "\\d") Integer kdcNum) {
RequestLogger.param(new String[]{"대주제 KDC 번호"}, kdcNum);
@GetMapping("/aWeekTrend")
public ResponseEntity<?> aWeekTrend(@RequestParam String subKdc,
@RequestParam(required = false) Integer maxSize) throws Exception {
RequestLogger.param(new String[]{"kdcNum"}, subKdc);
genreRequestValidate.isValidSubKdc(subKdc);

List<Book> books = genreService.findBooksByMainKdcNum(kdcNum);
return ResponseEntity.ok(books).getBody();
LoanTrendRequestDto requestDto = LoanTrendRequestDto.builder().dtl_kdc(subKdc).build();
LinkedList<LoanTrendResponseDto> response = genreService.periodToNowTrend(requestDto, 7, maxSize);

return responseTemplate.success(response, HttpStatus.OK);
}

/**
* 한달 인기순 - 중주제 KDC 번호(2자리) 입력 시 1개월 인기순 도서 목록 리턴
*/
@GetMapping("/aMonthTrend")
public ResponseEntity<?> aMonthTrend(@RequestParam String subKdc,
@RequestParam(required = false) Integer maxSize) throws Exception {
RequestLogger.param(new String[]{"kdcNum"}, subKdc);
genreRequestValidate.isValidSubKdc(subKdc);

LoanTrendRequestDto requestDto = LoanTrendRequestDto.builder().dtl_kdc(subKdc).build();
LinkedList<LoanTrendResponseDto> response = genreService.periodToNowTrend(requestDto, 30, maxSize);

return responseTemplate.success(response, HttpStatus.OK);
}

/**
* N월 M주차 - 중주제 KDC 번호(2자리) 입력시 N월 M주차 인기 도서 목록 리턴
* - (월요일 또는 화요일이면 저번 주로, 아니면 이번 주로 계산)
*/
@GetMapping("/thisWeekTrend")
public ResponseEntity<?> thisWeekTrend(@RequestParam String subKdc,
@RequestParam(required = false) Integer maxSize) throws Exception {
RequestLogger.param(new String[]{"kdcNum"}, subKdc);
genreRequestValidate.isValidSubKdc(subKdc);

LoanTrendRequestDto requestDto = LoanTrendRequestDto.builder().dtl_kdc(subKdc).build();
LinkedList<LoanTrendResponseDto> response = genreService.thisWeekTrend(requestDto, maxSize);

return responseTemplate.success(response, HttpStatus.OK);
}

/**
* 무작위순 - 중주제 KDC 번호(2자리) 입력 시 랜덤한 도서 목록 리턴
*/
@GetMapping("/random")
public ResponseEntity<?> random(@RequestParam String subKdc,
@RequestParam(required = false) Integer maxSize) throws Exception {
RequestLogger.param(new String[]{"kdcNum"}, subKdc);
genreRequestValidate.isValidSubKdc(subKdc);

LoanTrendRequestDto requestDto = LoanTrendRequestDto.builder().dtl_kdc(subKdc).build();
LinkedList<LoanTrendResponseDto> response = genreService.random(requestDto, maxSize);

return responseTemplate.success(response, HttpStatus.OK);
}

/**
* 중주제 KDC 번호(2자리) 입력 시 저장된 책 목록 리턴
* 신작 인기순 - 중주제 KDC 번호(2자리) 입력 시 3년 내 출판된 인기 도서 목록 리턴
*/
@GetMapping("/sub")
public List<Book> findBooksBySubKdcNum(@RequestParam @Pattern(regexp = "\\d{2}") Integer kdcNum) {
RequestLogger.param(new String[] {"중주제 KDC 번호"}, kdcNum);
@GetMapping("/newTrend")
public ResponseEntity<?> newTrend(@RequestParam String subKdc,
@RequestParam(required = false) Integer maxSize) throws Exception {
RequestLogger.param(new String[]{"kdcNum"}, subKdc);
genreRequestValidate.isValidSubKdc(subKdc);

LoanTrendRequestDto requestDto = LoanTrendRequestDto.builder().dtl_kdc(subKdc).build();
LinkedList<LoanTrendResponseDto> response = genreService.newTrend(requestDto, maxSize);

List<Book> books = genreService.findBooksBySubKdcNum(kdcNum);
return ResponseEntity.ok(books).getBody();
return responseTemplate.success(response, HttpStatus.OK);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.book.backend.domain.genre.service;

import com.book.backend.exception.CustomException;
import com.book.backend.exception.ErrorCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

@Component
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class GenreRequestValidate {

public void isValidMainKdc(String kdc) {
// 한 자리 숫자로 구성된 KDC 번호
if(!(kdc.matches("\\d"))) {
throw new CustomException(ErrorCode.INVALID_MAIN_KDC);
}
}

public void isValidSubKdc(String kdc) {
// 두 자리 숫자로 구성된 KDC 번호
if(!(kdc.matches("\\d{2}"))) {
throw new CustomException(ErrorCode.INVALID_MAIN_KDC);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.book.backend.domain.genre.service;

import com.book.backend.domain.openapi.dto.response.LoanTrendResponseDto;
import com.book.backend.domain.openapi.service.ResponseParser;
import lombok.RequiredArgsConstructor;
import net.minidev.json.JSONObject;
import org.springframework.stereotype.Component;

import java.util.LinkedList;

@Component
@RequiredArgsConstructor
public class GenreResponseParser {
private final ResponseParser responseParser;

public LinkedList<LoanTrendResponseDto> periodTrend(JSONObject jsonResponse, Integer maxSize) {
LinkedList<LoanTrendResponseDto> loanTrendResponseList = responseParser.loanTrend(jsonResponse);
LinkedList<LoanTrendResponseDto> responseList = new LinkedList<>();

for (LoanTrendResponseDto response : loanTrendResponseList) {
if (maxSize != null && responseList.size() >= maxSize) {
break;
}
responseList.add(response);
}
return responseList;
}

public LinkedList<LoanTrendResponseDto> random(JSONObject jsonResponse, int resultSize, Integer maxSize) {
LinkedList<LoanTrendResponseDto> loanTrendResponseList = responseParser.loanTrend(jsonResponse);
LinkedList<LoanTrendResponseDto> responseList = new LinkedList<>();

// TODO: #26 PR 병합되면 랜덤 로직 추가
for (LoanTrendResponseDto response : loanTrendResponseList) {
if (maxSize != null && responseList.size() >= maxSize) {
break;
}
responseList.add(response);
}
return responseList;
}

public LinkedList<LoanTrendResponseDto> newTrend(JSONObject jsonResponse, int currentYear, Integer maxSize) {
LinkedList<LoanTrendResponseDto> loanTrendResponseList = responseParser.loanTrend(jsonResponse);
LinkedList<LoanTrendResponseDto> responseList = new LinkedList<>();

for (LoanTrendResponseDto response : loanTrendResponseList) {
if (maxSize != null && responseList.size() >= maxSize) {
break;
}

int publication_year;
try {
publication_year = Integer.parseInt(response.getPublication_year());
} catch (NumberFormatException e) {
continue;
}

if (publication_year >= currentYear - 2) {
responseList.add(response);
}
}
return responseList;
}
}
Loading

0 comments on commit 95bbf4d

Please sign in to comment.