Coverage for opt/mealie/lib/python3.12/site-packages/mealie/db/models/group/group.py: 84%

55 statements  

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

1from typing import TYPE_CHECKING 

2 

3import sqlalchemy as sa 

4import sqlalchemy.orm as orm 

5from pydantic import ConfigDict 

6from sqlalchemy.orm import Mapped, mapped_column 

7 

8from mealie.db.models.labels import MultiPurposeLabel 

9 

10from .._model_base import BaseMixins, SqlAlchemyBase 

11from .._model_utils.auto_init import auto_init 

12from .._model_utils.guid import GUID 

13from ..household.cookbook import CookBook 

14from ..household.invite_tokens import GroupInviteToken 

15from ..household.mealplan import GroupMealPlan 

16from ..household.webhooks import GroupWebhooksModel 

17from ..recipe.category import Category, group_to_categories 

18from ..server.task import ServerTaskModel 

19from .preferences import GroupPreferencesModel 

20 

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

22 from ..household import Household 

23 from ..household.events import GroupEventNotifierModel 

24 from ..household.recipe_action import GroupRecipeAction 

25 from ..household.shopping_list import ShoppingList 

26 from ..recipe import IngredientFoodModel, IngredientUnitModel, RecipeModel, Tag, Tool 

27 from ..users import User 

28 from .exports import GroupDataExportsModel 

29 from .report import ReportModel 

30 

31 

32class Group(SqlAlchemyBase, BaseMixins): 

33 __tablename__ = "groups" 

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

35 name: Mapped[str] = mapped_column(sa.String, index=True, nullable=False, unique=True) 

36 slug: Mapped[str | None] = mapped_column(sa.String, index=True, unique=True) 

37 households: Mapped[list["Household"]] = orm.relationship("Household", back_populates="group") 

38 users: Mapped[list["User"]] = orm.relationship("User", back_populates="group") 

39 categories: Mapped[list[Category]] = orm.relationship(Category, secondary=group_to_categories, single_parent=True) 

40 

41 invite_tokens: Mapped[list[GroupInviteToken]] = orm.relationship( 

42 GroupInviteToken, back_populates="group", cascade="all, delete-orphan" 

43 ) 

44 preferences: Mapped[GroupPreferencesModel] = orm.relationship( 

45 GroupPreferencesModel, 

46 back_populates="group", 

47 uselist=False, 

48 single_parent=True, 

49 cascade="all, delete-orphan", 

50 ) 

51 

52 # Recipes 

53 recipes: Mapped[list["RecipeModel"]] = orm.relationship("RecipeModel", back_populates="group") 

54 

55 # CRUD From Others 

56 common_args = { 

57 "back_populates": "group", 

58 "cascade": "all, delete-orphan", 

59 "single_parent": True, 

60 } 

61 

62 labels: Mapped[list[MultiPurposeLabel]] = orm.relationship(MultiPurposeLabel, **common_args) 

63 

64 mealplans: Mapped[list[GroupMealPlan]] = orm.relationship( 

65 GroupMealPlan, order_by="GroupMealPlan.date", **common_args 

66 ) 

67 webhooks: Mapped[list[GroupWebhooksModel]] = orm.relationship(GroupWebhooksModel, **common_args) 

68 recipe_actions: Mapped[list["GroupRecipeAction"]] = orm.relationship("GroupRecipeAction", **common_args) 

69 cookbooks: Mapped[list[CookBook]] = orm.relationship(CookBook, **common_args) 

70 server_tasks: Mapped[list["ServerTaskModel"]] = orm.relationship("ServerTaskModel", **common_args) 

71 data_exports: Mapped[list["GroupDataExportsModel"]] = orm.relationship("GroupDataExportsModel", **common_args) 

72 shopping_lists: Mapped[list["ShoppingList"]] = orm.relationship("ShoppingList", **common_args) 

73 group_reports: Mapped[list["ReportModel"]] = orm.relationship("ReportModel", **common_args) 

74 group_event_notifiers: Mapped[list["GroupEventNotifierModel"]] = orm.relationship( 

75 "GroupEventNotifierModel", **common_args 

76 ) 

77 

78 # Owned Models 

79 ingredient_units: Mapped[list["IngredientUnitModel"]] = orm.relationship("IngredientUnitModel", **common_args) 

80 ingredient_foods: Mapped[list["IngredientFoodModel"]] = orm.relationship("IngredientFoodModel", **common_args) 

81 tools: Mapped[list["Tool"]] = orm.relationship("Tool", **common_args) 

82 tags: Mapped[list["Tag"]] = orm.relationship("Tag", **common_args) 

83 model_config = ConfigDict( 

84 exclude={ 

85 "households", 

86 "users", 

87 "webhooks", 

88 "recipe_actions", 

89 "shopping_lists", 

90 "cookbooks", 

91 "preferences", 

92 "invite_tokens", 

93 "mealplans", 

94 "data_exports", 

95 } 

96 ) 

97 

98 @auto_init() 

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

100 pass