Skip to content

Commit

Permalink
Merge pull request #43 from BOOK-TALK/#40-search-detail
Browse files Browse the repository at this point in the history
#40 책 검색, 책 상세 API
  • Loading branch information
chanwoo7 authored Aug 10, 2024
2 parents c267ad7 + 95cf066 commit 061423d
Show file tree
Hide file tree
Showing 21 changed files with 595 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.book.backend.domain.detail.controller;

import com.book.backend.domain.openapi.service.RequestValidate;
import com.book.backend.domain.detail.service.DetailService;
import com.book.backend.domain.openapi.dto.request.DetailRequestDto;
import com.book.backend.domain.openapi.dto.response.DetailResponseDto;
import com.book.backend.global.ResponseTemplate;
import com.book.backend.global.log.RequestLogger;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import java.util.LinkedList;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/api/book")
@RequiredArgsConstructor
@Slf4j
public class DetailController {
private final DetailService detailService;
private final RequestValidate requestValidate;
private final ResponseTemplate responseTemplate;

// 도서 상세 (8) API
@Operation(summary="책 상세", description="특정 책 코드를 입력으로 받아 해당 책 상세 정보, 대출 주 연령대, 키워드, 같이 대출한 도서, 추천 도서를 반환합니다.",
parameters = {@Parameter(name = "isbn", description = "책 코드")},
responses = {@ApiResponse(responseCode = "200", content = @Content(schema = @Schema(implementation = DetailResponseDto.class)),
description = DetailResponseDto.description)})
@GetMapping("/detail")
public ResponseEntity<?> search(@RequestParam String isbn, String libCode) throws Exception {
RequestLogger.param(new String[]{"isbn, libCode"}, isbn, libCode);
requestValidate.isValidIsbn(isbn);
requestValidate.isValidLibCode(libCode);

DetailRequestDto requestDto = DetailRequestDto.builder().isbn13(isbn).build();
DetailResponseDto response = detailService.detail(requestDto);

detailService.setLoanAvailable(response, libCode);

return responseTemplate.success(response, HttpStatus.OK);
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/book/backend/domain/detail/dto/BookInfoDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.book.backend.domain.detail.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class BookInfoDto {
private String bookname;
private String authors;
private String publisher;
private String bookImageURL;
private String description;
private String publication_year;
private String isbn13;
private String vol;
private String class_no;
private String class_nm;
private String loanCnt;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.book.backend.domain.detail.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class CoLoanBooksDto {
private String bookname;
private String authors;
private String publisher;
private String publication_year;
private String isbn13;
private String vol;
private String loanCnt;
}
10 changes: 10 additions & 0 deletions src/main/java/com/book/backend/domain/detail/dto/KeywordDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.book.backend.domain.detail.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class KeywordDto {
private String word;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.book.backend.domain.detail.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class LoanHistoryDto {
private String month;
private String loanCnt;
private String ranking;
}
16 changes: 16 additions & 0 deletions src/main/java/com/book/backend/domain/detail/dto/RecommendDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.book.backend.domain.detail.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class RecommendDto {
// 마니아, 다독자
private String bookname;
private String authors;
private String publisher;
private String publication_year;
private String isbn13;
private String vol;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.book.backend.domain.detail.dto;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class Top3LoanUserDto {
private String age;
private String gender;
private String loanCnt;
private String ranking;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.book.backend.domain.detail.service;

import com.book.backend.domain.openapi.dto.request.BookExistRequestDto;
import com.book.backend.domain.openapi.dto.request.DetailRequestDto;
import com.book.backend.domain.openapi.dto.response.BookExistResponseDto;
import com.book.backend.domain.openapi.dto.response.DetailResponseDto;
import com.book.backend.domain.openapi.dto.response.SearchResponseDto;
import com.book.backend.domain.openapi.service.OpenAPI;
import com.book.backend.domain.openapi.service.ResponseParser;
import java.util.LinkedList;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONObject;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
@Slf4j
public class DetailService {
private final OpenAPI openAPI;

public DetailResponseDto detail(DetailRequestDto requestDto) throws Exception {
log.trace("detail()");
String subUrl = "usageAnalysisList";
JSONObject jsonResponse = openAPI.connect(subUrl, requestDto, new SearchResponseDto());
ResponseParser responseParser = new ResponseParser();
return responseParser.detail(jsonResponse);
}

public void setLoanAvailable(DetailResponseDto response, String libCode) throws Exception {
log.trace("setLoanAvailable()");

BookExistRequestDto bookExistRequestDto = BookExistRequestDto.builder()
.libCode(libCode)
.isbn13(response.getBookInfoDto().getIsbn13()).build();
String subUrl = "bookExist";
JSONObject jsonResponse = openAPI.connect(subUrl, bookExistRequestDto, new BookExistResponseDto());
ResponseParser responseParser = new ResponseParser();

response.setLoanAvailable(responseParser.loanAvailable(jsonResponse));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.book.backend.domain.openapi.dto.request;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class BookExistRequestDto implements OpenAPIRequestInterface{
private String libCode;
private String isbn13;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.book.backend.domain.openapi.dto.request;

import lombok.Builder;
import lombok.Getter;

@Getter
@Builder
public class DetailRequestDto implements OpenAPIRequestInterface {
private String isbn13;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.book.backend.domain.openapi.dto.request;

import jakarta.validation.constraints.NotBlank;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Builder
@Setter
public class SearchRequestDto implements OpenAPIRequestInterface {
@NotBlank(message = "검색어를 입력해주세요.")
private String title;
private String author;
private String keyword;
private String pageNo; // 페이지 번호
private String pageSize; // 한 페이지에 담을 요소 수
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.book.backend.domain.openapi.dto.response;

public class BookExistResponseDto implements OpenAPIResponseInterface{
private String loanAvailable;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.book.backend.domain.openapi.dto.response;

import com.book.backend.domain.detail.dto.BookInfoDto;
import com.book.backend.domain.detail.dto.CoLoanBooksDto;
import com.book.backend.domain.detail.dto.Top3LoanUserDto;
import com.book.backend.domain.detail.dto.RecommendDto;
import java.util.LinkedList;
import java.util.List;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;

@Getter
@Builder
@Setter
public class DetailResponseDto implements OpenAPIResponseInterface {
private BookInfoDto bookInfoDto;
private List<Top3LoanUserDto> top3LoanUserDtoList;
private LinkedList<String> keywordDtoList;
private LinkedList<CoLoanBooksDto> coLoanBooksDtoList;
private LinkedList<RecommendDto> recommendResponseDtoList;
private boolean loanAvailable;

public static final String description = "bookInfoDto: 책 상세 정보 | top3LoanUserDtoList: 대출 주 연령대 | "
+ "keywordDtoList: 책 연관 키워드 | coLoanBooksDtoList: 같이 대출한 도서 | recommendResponseDtoList: 추천 도서";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.book.backend.domain.openapi.dto.response;

import com.book.backend.domain.openapi.dto.request.OpenAPIRequestInterface;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Setter
public class SearchResponseDto implements OpenAPIResponseInterface, OpenAPIRequestInterface {
private String bookname;
private String authors;
private String publisher;
private String publication_year;
private String isbn13;
private String vol;
private String bookImageURL;
private String bookDtlUrl;
private String loan_count;

private boolean isLoanAvailable;

public static final String description = "bookname: 책이름 | authors: 작가 옮긴이 | publisher: 출판사 | "
+ "publication_year: 출판년도 | isbn13: 책 바코드 | vol: 권? | "
+ "bookImageURL: 책 표지 URL | bookDtlUrl: 책 상세설명 URL | loan_count: 총? 대출 회수";
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@

import com.book.backend.domain.openapi.dto.request.OpenAPIRequestInterface;
import com.book.backend.domain.openapi.dto.response.OpenAPIResponseInterface;
import com.book.backend.exception.CustomException;
import com.book.backend.exception.ErrorCode;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONObject;
import net.minidev.json.parser.JSONParser;
import org.springframework.beans.factory.annotation.Value;
Expand Down Expand Up @@ -63,7 +60,12 @@ private JSONObject readStreamToJson(InputStreamReader streamResponse, OpenAPIRes

// response JSON 파싱
JSONObject jsonObject = (JSONObject) (new JSONParser()).parse(fullResponse);
return (JSONObject) jsonObject.get("response");
JSONObject response = (JSONObject) jsonObject.get("response");
// API 일일 호출 횟수 초과 에러 (일 최대 500건)
if(response.get("error") != null){
throw new CustomException(ErrorCode.API_CALL_LIMIT_EXCEEDED);
}
return response;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@ public void isValidLibCode(String libCode){
}
}

// pageNo, pageSize
public void isValidPageNum(int num) {
// 1 이상의 숫자인지 확인
if(num < 1) {
throw new CustomException(ErrorCode.INVALID_PAGE_NUM);
}
}

// public void isValidSearchDt(String searchDt) {
// //yyyy-mm-dd 형식인지 확인
Expand Down
Loading

0 comments on commit 061423d

Please sign in to comment.