Coverage for opt/mealie/lib/python3.12/site-packages/mealie/db/models/users/user_to_recipe.py: 69%

38 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-25 15:48 +0000

1from typing import TYPE_CHECKING 1a

2 

3from sqlalchemy import Boolean, Column, Float, ForeignKey, UniqueConstraint, event 1a

4from sqlalchemy.engine.base import Connection 1a

5from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy 1a

6from sqlalchemy.orm import Mapped, mapped_column, relationship 1a

7from sqlalchemy.orm.session import Session 1a

8 

9from .._model_base import BaseMixins, SqlAlchemyBase 1a

10from .._model_utils.auto_init import auto_init 1a

11from .._model_utils.guid import GUID 1a

12 

13if TYPE_CHECKING: 13 ↛ 14line 13 didn't jump to line 14 because the condition on line 13 was never true1a

14 from ..recipe import RecipeModel 

15 

16 

17class UserToRecipe(SqlAlchemyBase, BaseMixins): 1a

18 __tablename__ = "users_to_recipes" 1a

19 __table_args__ = (UniqueConstraint("user_id", "recipe_id", name="user_id_recipe_id_rating_key"),) 1a

20 id: Mapped[GUID] = mapped_column(GUID, primary_key=True, default=GUID.generate) 1a

21 

22 user_id = Column(GUID, ForeignKey("users.id"), index=True, primary_key=True) 1a

23 recipe: Mapped["RecipeModel"] = relationship("RecipeModel") 1a

24 recipe_id = Column(GUID, ForeignKey("recipes.id"), index=True, primary_key=True) 1a

25 group_id: AssociationProxy[GUID] = association_proxy("recipe", "group_id") 1a

26 household_id: AssociationProxy[GUID] = association_proxy("recipe", "household_id") 1a

27 

28 rating = Column(Float, index=True, nullable=True) 1a

29 is_favorite = Column(Boolean, index=True, nullable=False) 1a

30 

31 @auto_init() 1a

32 def __init__(self, **_) -> None: 1a

33 pass 

34 

35 

36def update_recipe_rating(session: Session, target: UserToRecipe): 1a

37 from mealie.db.models.recipe.recipe import RecipeModel 

38 

39 recipe = session.query(RecipeModel).filter(RecipeModel.id == target.recipe_id).first() 

40 if not recipe: 

41 return 

42 

43 recipe.rating = -1 # this will trigger the recipe to re-calculate the rating 

44 

45 

46@event.listens_for(UserToRecipe, "after_insert") 1a

47@event.listens_for(UserToRecipe, "after_update") 1a

48@event.listens_for(UserToRecipe, "after_delete") 1a

49def update_recipe_rating_on_insert_or_delete(_, connection: Connection, target: UserToRecipe): 1a

50 session = Session(bind=connection) 

51 

52 update_recipe_rating(session, target) 

53 session.commit()