Coverage for opt/mealie/lib/python3.12/site-packages/mealie/db/models/users/user_to_recipe.py: 90%
38 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 03:04 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 03:04 +0000
1from typing import TYPE_CHECKING
3from sqlalchemy import Boolean, Column, Float, ForeignKey, UniqueConstraint, event
4from sqlalchemy.engine.base import Connection
5from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy
6from sqlalchemy.orm import Mapped, mapped_column, relationship
7from sqlalchemy.orm.session import Session
9from .._model_base import BaseMixins, SqlAlchemyBase
10from .._model_utils.auto_init import auto_init
11from .._model_utils.guid import GUID
13if TYPE_CHECKING: 13 ↛ 14line 13 didn't jump to line 14 because the condition on line 13 was never true
14 from ..recipe import RecipeModel
17class UserToRecipe(SqlAlchemyBase, BaseMixins):
18 __tablename__ = "users_to_recipes"
19 __table_args__ = (UniqueConstraint("user_id", "recipe_id", name="user_id_recipe_id_rating_key"),)
20 id: Mapped[GUID] = mapped_column(GUID, primary_key=True, default=GUID.generate)
22 user_id = Column(GUID, ForeignKey("users.id"), index=True, primary_key=True)
23 recipe: Mapped["RecipeModel"] = relationship("RecipeModel")
24 recipe_id = Column(GUID, ForeignKey("recipes.id"), index=True, primary_key=True)
25 group_id: AssociationProxy[GUID] = association_proxy("recipe", "group_id")
26 household_id: AssociationProxy[GUID] = association_proxy("recipe", "household_id")
28 rating = Column(Float, index=True, nullable=True)
29 is_favorite = Column(Boolean, index=True, nullable=False)
31 @auto_init()
32 def __init__(self, **_) -> None:
33 pass
36def update_recipe_rating(session: Session, target: UserToRecipe):
37 from mealie.db.models.recipe.recipe import RecipeModel
39 recipe = session.query(RecipeModel).filter(RecipeModel.id == target.recipe_id).first()
40 if not recipe: 40 ↛ 41line 40 didn't jump to line 41 because the condition on line 40 was never true
41 return
43 recipe.rating = -1 # this will trigger the recipe to re-calculate the rating
46@event.listens_for(UserToRecipe, "after_insert")
47@event.listens_for(UserToRecipe, "after_update")
48@event.listens_for(UserToRecipe, "after_delete")
49def update_recipe_rating_on_insert_or_delete(_, connection: Connection, target: UserToRecipe):
50 session = Session(bind=connection)
52 update_recipe_rating(session, target)
53 session.commit()