From e647bc781149dd3e995c86440201d682186a1b39 Mon Sep 17 00:00:00 2001 From: Esa Kataja Date: Mon, 5 May 2025 18:32:39 +0300 Subject: [PATCH] Add review model and CRUD endpoints for managing song reviews --- src/models/review.py | 41 ++++++++++++++++++++++++++ src/routes/reviews.py | 68 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 src/models/review.py diff --git a/src/models/review.py b/src/models/review.py new file mode 100644 index 0000000..e2053fe --- /dev/null +++ b/src/models/review.py @@ -0,0 +1,41 @@ +from pydantic import BaseModel, Field +from datetime import datetime + + +class ReviewBase(BaseModel): + song_id: int = Field(description="ID of the song", examples=[1]) + user_id: int = Field(description="ID of the user", examples=[1]) + score_song: int = Field( + gt=0, le=100, description="Score given by the user", examples=[1] + ) + score_show: int = Field( + gt=0, le=100, description="Score given by the user", examples=[1] + ) + score_costume: int = Field( + gt=0, le=100, description="Score given by the user", examples=[1] + ) + text_review: str | None = Field( + default=None, description="Comment given by the user", examples=["comment"] + ) + + +class ReviewIn(ReviewBase): + pass + + +class ReviewSearch(BaseModel): + song_id: int = Field(description="ID of the song", examples=[1]) + user_id: int = Field(description="ID of the user", examples=[1]) + + +class ReviewOut(ReviewBase): + created_at: datetime = Field( + default_factory=datetime.now, + description="Creation timestamp", + examples=["2025-01-01T00:00:00.000Z"], + ) + updated_at: datetime = Field( + default_factory=datetime.now, + description="Last update timestamp", + examples=["2025-01-01T00:00:00.000Z"], + ) diff --git a/src/routes/reviews.py b/src/routes/reviews.py index 3386eff..aee98a0 100644 --- a/src/routes/reviews.py +++ b/src/routes/reviews.py @@ -1,3 +1,67 @@ -from fastapi import APIRouter +from fastapi import APIRouter, HTTPException -router = APIRouter(prefix="/songs", tags=["songs"]) +from models.review import ReviewOut, ReviewSearch, ReviewIn +from lib.db import get_connection + +router = APIRouter(prefix="/reviews", tags=["reviews"]) + + +@router.get("/all", response_model=list[ReviewOut]) +async def list_reviews(): + with get_connection() as conn: + reviews = conn.execute("SELECT * FROM Review").fetchdf() + if reviews.empty: + raise HTTPException(status_code=404, detail="Reviews not found") + return reviews.to_dict(orient="records") + + +@router.get("/", response_model=ReviewOut) +async def get_review(review_id: ReviewSearch): + with get_connection() as conn: + review = conn.execute( + "SELECT * FROM Review WHERE song_id = ? AND user_id = ?", + (review_id.song_id, review_id.user_id), + ).fetchdf() + if review.empty: + raise HTTPException(status_code=404, detail="Review not found") + return review.to_dict(orient="records")[0] + + +@router.post("/", response_model=ReviewOut) +async def create_review(review: ReviewIn): + with get_connection() as conn: + review = conn.execute( + "INSERT INTO Review (user_id, song_id, score_song, score_show, score_costume, text_review) VALUES (?, ?, ?, ?, ?, ?)", + ( + review.user_id, + review.song_id, + review.score_song, + review.score_show, + review.score_costume, + review.text_review, + ), + ).fetchdf() + if review.empty: + raise HTTPException(status_code=404, detail="Review not found") + return review.to_dict(orient="records")[0] + + +@router.put("/", response_model=ReviewOut) +async def update_review(review: ReviewIn): + with get_connection() as conn: + review = conn.execute( + "UPDATE Review SET user_id = ?, song_id = ?, score_song = ?, score_show = ?, score_costume = ?, text_review = ? WHERE song_id = ? AND user_id = ?", + ( + review.user_id, + review.song_id, + review.score_song, + review.score_show, + review.score_costume, + review.text_review, + review.song_id, + review.user_id, + ), + ).fetchdf() + if review.empty: + raise HTTPException(status_code=404, detail="Review not found") + return review.to_dict(orient="records")[0]