Skip to content

Commit

Permalink
Merge pull request #130 from kucc/exp
Browse files Browse the repository at this point in the history
Main: v.0.1.6 배포 - 도서 검색 및 도서 정보 조회 API 리팩토링
  • Loading branch information
smreosms13 authored Dec 29, 2024
2 parents f74bb56 + 46fc073 commit 39d75a2
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 34 deletions.
8 changes: 4 additions & 4 deletions src/domain/schemas/book_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ class DomainResGetBook(BaseModel):
updated_at: datetime = Field(title="update_at", description="수정일시", example=datetime.now())


class DomainResGetBookList(BaseModel):
class DomainResGetBookItem(BaseModel):
book_id: int = Field(title="book_id", description="책 ID", example=1, gt=0)
book_title: str = Field(title="book_title", description="책 제목", example="FastAPI Tutorial")
category_name: str = Field(title="category_name", description="카테고리 이름", example="웹")
image_url: str | None = Field(title="image_url", description="책 이미지 링크", example="https://example.com/img")
book_status: bool = Field(title="book_stauts", description="책 상태", example=True)
created_at: datetime = Field(title="create_at", description="생성일시", example=datetime.now())
updated_at: datetime = Field(title="update_at", description="수정일시", example=datetime.now())
loanable: bool | None = Field(title="loan_status", description="대출 상태", example=False)
loanable: bool = Field(title="loan_status", description="대출 상태", example=False)


class DomainResGetBookListWithTotal(BaseModel):
data: list[DomainResGetBookList]
class DomainResGetBookList(BaseModel):
data: list[DomainResGetBookItem]
total: int = Field(description="Book 객체의 총 요소 개수")


Expand Down
93 changes: 68 additions & 25 deletions src/domain/services/book_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from domain.schemas.book_schemas import (
DomainReqGetBook,
DomainResGetBook,
DomainResGetBookItem,
DomainResGetBookList,
DomainResGetBookListWithTotal,
)
from repositories.models import Book, Loan

Expand All @@ -19,7 +19,7 @@ async def service_search_books(
page: int,
limit: int,
db: Session
) -> DomainResGetBookListWithTotal:
) -> DomainResGetBookList:
if not search and is_loanable is None:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
Expand Down Expand Up @@ -74,7 +74,7 @@ async def service_search_books(
stmt = stmt.where(or_(latest_loan_subq == True, latest_loan_subq.is_(None)))


print(stmt) # 디버깅용
# print(stmt) # 디버깅용
try:
books = (
db.execute(
Expand Down Expand Up @@ -113,20 +113,23 @@ async def service_search_books(
for book in books:
(book_id, book_title, category_name, image_url, book_status, created_at, updated_at, loan_status) = book

# loan_status == None이면 True
loanable = True if loan_status is None else loan_status

search_books.append(
DomainResGetBookList(
DomainResGetBookItem(
book_id=book_id,
book_title=book_title,
category_name=category_name,
image_url=image_url,
book_status=book_status,
created_at=created_at,
updated_at=updated_at,
loanable=loan_status # loan_status의 값을 inverse 없이 바로 적용
loanable=loanable
)
)

response = DomainResGetBookListWithTotal(
response = DomainResGetBookList(
data=search_books,
total=total
)
Expand Down Expand Up @@ -155,7 +158,6 @@ async def service_read_book(request_data: DomainReqGetBook, db: Session):
loanable = False
break


response = DomainResGetBook(
book_id=book.id,
book_title=book.book_title,
Expand All @@ -177,44 +179,85 @@ async def service_read_book(request_data: DomainReqGetBook, db: Session):
)
return response


async def service_read_books(page: int, limit: int, db: Session):
offset = (page - 1) * limit # Calculate offset based on the page number
latest_loan_subq = (
select(Loan.return_status)
.where(and_(Loan.book_id == Book.id, Loan.is_deleted == False))
.order_by(Loan.updated_at.desc())
.limit(1)
).scalar_subquery()

stmt = (
select(Book)
.where(
Book.is_deleted == False
select(
Book.id,
Book.book_title,
Book.category_name,
Book.image_url,
Book.book_status,
Book.created_at,
Book.updated_at,
latest_loan_subq.label("loan_status"),
)
.order_by(Book.updated_at.desc())
.limit(limit)
.offset(offset)
.where(and_(Book.is_deleted == False, Book.book_status == True))
)
try:
books = db.execute(stmt).scalars().all()
books = (
db.execute(
stmt
.order_by(Book.updated_at.desc(), Book.id.asc())
.limit(limit)
.offset(offset)
).all()
)

if not books:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Books not found"
)

# Get total count using the same stmt conditions
count_stmt = stmt.with_only_columns(func.count())
total = db.execute(count_stmt).scalar_one()

if ceil(total/limit) < page:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Page is out of range"
)

except HTTPException as e:
raise e

except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Unexpected error occurred during retrieve: {str(e)}",
) from e

response = [
DomainResGetBookList(
book_id=book.id,
book_title=book.book_title,
category_name=book.category_name,
image_url=book.image_url,
book_status=book.book_status,
created_at=book.created_at,
updated_at=book.updated_at
result = []
for book in books:
(book_id, book_title, category_name, image_url, book_status, created_at, updated_at, loan_status) = book

loanable = True if loan_status is None else loan_status

result.append(
DomainResGetBookItem(
book_id=book_id,
book_title=book_title,
category_name=category_name,
image_url=image_url,
book_status=book_status,
created_at=created_at,
updated_at=updated_at,
loanable=loanable
)
)
for book in books
]

response = DomainResGetBookList(
data=result,
total=total
)
return response
5 changes: 3 additions & 2 deletions src/routes/books_route.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,9 @@ async def get_books(
):
domain_res = await service_read_books(page, limit, db)
result = RouteResGetBookList(
data=domain_res,
count=len(domain_res)
data=domain_res.data,
count=len(domain_res.data),
total=domain_res.total
)

return result
6 changes: 3 additions & 3 deletions src/routes/response/book_response.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from pydantic import BaseModel, Field

from domain.schemas.book_schemas import DomainResGetBookList
from domain.schemas.book_schemas import DomainResGetBookItem


class RouteResGetBookList(BaseModel):
data: list[DomainResGetBookList]
data: list[DomainResGetBookItem]
count: int = Field(description="data 배열의 요소 개수")
total: int = Field(description="data 배열의 총 요소 개수")
total: int = Field(description="객체의 총 요소 개수")


class RouteResGetBook(BaseModel):
Expand Down

0 comments on commit 39d75a2

Please sign in to comment.