2 Commits
Author SHA1 Message Date
Esa Kataja e647bc7811 Add review model and CRUD endpoints for managing song reviews 2025-05-05 18:32:39 +03:00
Esa Kataja bf7c969629 CHANGE sql schema 2025-05-05 18:30:22 +03:00
3 changed files with 109 additions and 4 deletions
+2 -2
View File
@@ -91,7 +91,7 @@ CREATE TABLE Review (
song_id INTEGER NOT NULL, -- Foreign Key -> Song.id
score_song INTEGER NOT NULL, -- Score (1-100) for song quality
score_show INTEGER NOT NULL, -- Score (1-100) for the stage show
score_wardrobe INTEGER NOT NULL, -- Score (1-100) for wardrobe/costumes
score_costume INTEGER NOT NULL, -- Score (1-100) for wardrobe/costumes
text_review VARCHAR, -- Optional textual comments (nullable)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Timestamp when the review was created
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- Timestamp when the review was last modified
@@ -102,7 +102,7 @@ CREATE TABLE Review (
-- Ensure scores are within the valid range (1-100)
CHECK (score_song >= 1 AND score_song <= 100),
CHECK (score_show >= 1 AND score_show <= 100),
CHECK (score_wardrobe >= 1 AND score_wardrobe <= 100),
CHECK (score_costume >= 1 AND score_costume <= 100),
-- Ensure each user can only submit one review per song
UNIQUE (user_id, song_id)
+41
View File
@@ -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"],
)
+66 -2
View File
@@ -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]