Coverage for opt/mealie/lib/python3.12/site-packages/mealie/db/models/household/mealplan.py: 90%

47 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 03:04 +0000

1import datetime 

2from typing import TYPE_CHECKING, Optional 

3 

4from sqlalchemy import Column, Date, ForeignKey, String, Table, UniqueConstraint, orm 

5from sqlalchemy.ext.associationproxy import AssociationProxy, association_proxy 

6from sqlalchemy.orm import Mapped, mapped_column 

7 

8from mealie.db.models.recipe.tag import Tag, plan_rules_to_tags 

9 

10from .._model_base import BaseMixins, SqlAlchemyBase 

11from .._model_utils.auto_init import auto_init 

12from .._model_utils.guid import GUID 

13from ..recipe.category import Category, plan_rules_to_categories 

14 

15if TYPE_CHECKING: 15 ↛ 16line 15 didn't jump to line 16 because the condition on line 15 was never true

16 from ..group import Group 

17 from ..recipe import RecipeModel 

18 from ..users import User 

19 from .household import Household 

20 

21plan_rules_to_households = Table( 

22 "plan_rules_to_households", 

23 SqlAlchemyBase.metadata, 

24 Column("group_plan_rule_id", GUID, ForeignKey("group_meal_plan_rules.id"), index=True), 

25 Column("household_id", GUID, ForeignKey("households.id"), index=True), 

26 UniqueConstraint("group_plan_rule_id", "household_id", name="group_plan_rule_id_household_id_key"), 

27) 

28 

29 

30class GroupMealPlanRules(BaseMixins, SqlAlchemyBase): 

31 __tablename__ = "group_meal_plan_rules" 

32 

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

34 group_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("groups.id"), nullable=False, index=True) 

35 household_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("households.id"), index=True) 

36 

37 day: Mapped[str] = mapped_column( 

38 String, nullable=False, default="unset" 

39 ) # "MONDAY", "TUESDAY", "WEDNESDAY", etc... 

40 entry_type: Mapped[str] = mapped_column( 

41 String, nullable=False, default="" 

42 ) # "breakfast", "lunch", "dinner", "side" 

43 query_filter_string: Mapped[str] = mapped_column(String, nullable=False, default="") 

44 

45 # Old filters - deprecated in favor of query filter strings 

46 categories: Mapped[list[Category]] = orm.relationship(Category, secondary=plan_rules_to_categories) 

47 tags: Mapped[list[Tag]] = orm.relationship(Tag, secondary=plan_rules_to_tags) 

48 households: Mapped[list["Household"]] = orm.relationship("Household", secondary=plan_rules_to_households) 

49 

50 @auto_init() 

51 def __init__(self, **_) -> None: 

52 pass 

53 

54 

55class GroupMealPlan(SqlAlchemyBase, BaseMixins): 

56 __tablename__ = "group_meal_plans" 

57 

58 date: Mapped[datetime.date] = mapped_column(Date, index=True, nullable=False) 

59 entry_type: Mapped[str] = mapped_column(String, index=True, nullable=False) 

60 title: Mapped[str] = mapped_column(String, index=True, nullable=False) 

61 text: Mapped[str] = mapped_column(String, nullable=False) 

62 

63 group_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("groups.id"), index=True) 

64 group: Mapped[Optional["Group"]] = orm.relationship("Group", back_populates="mealplans") 

65 household_id: AssociationProxy[GUID] = association_proxy("user", "household_id") 

66 household: AssociationProxy["Household"] = association_proxy("user", "household") 

67 user_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("users.id"), index=True) 

68 user: Mapped[Optional["User"]] = orm.relationship("User", back_populates="mealplans") 

69 

70 recipe_id: Mapped[GUID | None] = mapped_column(GUID, ForeignKey("recipes.id"), index=True) 

71 recipe: Mapped[Optional["RecipeModel"]] = orm.relationship( 

72 "RecipeModel", back_populates="meal_entries", uselist=False 

73 ) 

74 

75 @auto_init() 

76 def __init__(self, **_) -> None: 

77 pass