Coverage for src/app/modules/reviews/services.py: 100%
43 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-24 08:34 +0000
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-24 08:34 +0000
1import logging
2from statistics import mean
4from app.modules.reviews.repository import ReviewRepository
6logger = logging.getLogger(__name__)
9class ReviewService:
10 def __init__(self, repo: ReviewRepository):
11 self.repo = repo
13 def create_review(self, card_id: int, rating: int):
14 logger.debug("create_review called: card_id=%s rating=%s", card_id, rating)
16 if rating < 1 or rating > 5:
17 logger.warning(
18 "create_review validation failed: rating out of range (1-5): %s for card_id=%s",
19 rating,
20 card_id,
21 )
22 raise ValueError("Rating must be 1–5")
24 try:
25 review = self.repo.create(card_id, rating)
26 logger.info(
27 "Review created: card_id=%s rating=%s review_id=%s",
28 card_id,
29 rating,
30 getattr(review, "id", None),
31 )
32 return review
33 except Exception:
34 logger.exception("Error creating review for card_id=%s rating=%s", card_id, rating)
35 raise
37 def compute_deck_score(self, deck_id: int):
38 logger.debug("compute_deck_score called: deck_id=%s", deck_id)
39 try:
40 reviews = self.repo.get_by_deck(deck_id)
41 except Exception:
42 logger.exception("Failed to fetch reviews for deck_id=%s", deck_id)
43 raise
45 if not reviews:
46 logger.info("No reviews found for deck_id=%s; returning zeroed score", deck_id)
47 return {"deck_id": deck_id, "average_score": 0.0, "review_count": 0}
49 scores = [r.rating for r in reviews]
50 average = round(mean(scores), 2)
51 count = len(scores)
52 logger.info(
53 "Computed deck score: deck_id=%s average_score=%s review_count=%s",
54 deck_id,
55 average,
56 count,
57 )
59 return {"deck_id": deck_id, "average_score": average, "review_count": count}
61 def delete_deck_reviews(self, deck_id: int):
62 logger.debug("delete_deck_reviews called: deck_id=%s", deck_id)
63 try:
64 result = self.repo.delete_by_deck(deck_id)
65 logger.info(
66 "Deleted reviews for deck_id=%s result=%s",
67 deck_id,
68 getattr(result, "deleted_count", result),
69 )
70 return result
71 except Exception:
72 logger.exception("Failed to delete reviews for deck_id=%s", deck_id)
73 raise