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
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 03:04 +0000
1import datetime
2from typing import TYPE_CHECKING, Optional
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
8from mealie.db.models.recipe.tag import Tag, plan_rules_to_tags
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
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
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)
30class GroupMealPlanRules(BaseMixins, SqlAlchemyBase):
31 __tablename__ = "group_meal_plan_rules"
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)
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="")
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)
50 @auto_init()
51 def __init__(self, **_) -> None:
52 pass
55class GroupMealPlan(SqlAlchemyBase, BaseMixins):
56 __tablename__ = "group_meal_plans"
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)
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")
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 )
75 @auto_init()
76 def __init__(self, **_) -> None:
77 pass