mirror of
https://github.com/mealie-recipes/mealie.git
synced 2026-02-17 05:13:10 -05:00
feat: Add Households to Mealie (#3970)
This commit is contained in:
@@ -1,158 +1,19 @@
|
||||
# This file is auto-generated by gen_schema_exports.py
|
||||
from .group import GroupAdminUpdate
|
||||
from .group_events import (
|
||||
GroupEventNotifierCreate,
|
||||
GroupEventNotifierOptions,
|
||||
GroupEventNotifierOptionsOut,
|
||||
GroupEventNotifierOptionsSave,
|
||||
GroupEventNotifierOut,
|
||||
GroupEventNotifierPrivate,
|
||||
GroupEventNotifierSave,
|
||||
GroupEventNotifierUpdate,
|
||||
GroupEventPagination,
|
||||
)
|
||||
from .group_exports import GroupDataExport
|
||||
from .group_migration import DataMigrationCreate, SupportedMigrations
|
||||
from .group_permissions import SetPermissions
|
||||
from .group_preferences import (
|
||||
CreateGroupPreferences,
|
||||
ReadGroupPreferences,
|
||||
UpdateGroupPreferences,
|
||||
)
|
||||
from .group_recipe_action import (
|
||||
CreateGroupRecipeAction,
|
||||
GroupRecipeActionOut,
|
||||
GroupRecipeActionPagination,
|
||||
GroupRecipeActionType,
|
||||
SaveGroupRecipeAction,
|
||||
)
|
||||
from .group_preferences import CreateGroupPreferences, ReadGroupPreferences, UpdateGroupPreferences
|
||||
from .group_seeder import SeederConfig
|
||||
from .group_shopping_list import (
|
||||
ShoppingListAddRecipeParams,
|
||||
ShoppingListCreate,
|
||||
ShoppingListItemBase,
|
||||
ShoppingListItemCreate,
|
||||
ShoppingListItemOut,
|
||||
ShoppingListItemPagination,
|
||||
ShoppingListItemRecipeRefCreate,
|
||||
ShoppingListItemRecipeRefOut,
|
||||
ShoppingListItemRecipeRefUpdate,
|
||||
ShoppingListItemsCollectionOut,
|
||||
ShoppingListItemUpdate,
|
||||
ShoppingListItemUpdateBulk,
|
||||
ShoppingListMultiPurposeLabelCreate,
|
||||
ShoppingListMultiPurposeLabelOut,
|
||||
ShoppingListMultiPurposeLabelUpdate,
|
||||
ShoppingListOut,
|
||||
ShoppingListPagination,
|
||||
ShoppingListRecipeRefOut,
|
||||
ShoppingListRemoveRecipeParams,
|
||||
ShoppingListSave,
|
||||
ShoppingListSummary,
|
||||
ShoppingListUpdate,
|
||||
)
|
||||
from .group_statistics import GroupStatistics, GroupStorage
|
||||
from .invite_token import (
|
||||
CreateInviteToken,
|
||||
EmailInitationResponse,
|
||||
EmailInvitation,
|
||||
ReadInviteToken,
|
||||
SaveInviteToken,
|
||||
)
|
||||
from .webhook import (
|
||||
CreateWebhook,
|
||||
ReadWebhook,
|
||||
SaveWebhook,
|
||||
WebhookPagination,
|
||||
WebhookType,
|
||||
)
|
||||
from .group_statistics import GroupStorage
|
||||
|
||||
__all__ = [
|
||||
"GroupEventNotifierCreate",
|
||||
"GroupEventNotifierOptions",
|
||||
"GroupEventNotifierOptionsOut",
|
||||
"GroupEventNotifierOptionsSave",
|
||||
"GroupEventNotifierOut",
|
||||
"GroupEventNotifierPrivate",
|
||||
"GroupEventNotifierSave",
|
||||
"GroupEventNotifierUpdate",
|
||||
"GroupEventPagination",
|
||||
"CreateGroupRecipeAction",
|
||||
"GroupRecipeActionOut",
|
||||
"GroupRecipeActionPagination",
|
||||
"GroupRecipeActionType",
|
||||
"SaveGroupRecipeAction",
|
||||
"CreateWebhook",
|
||||
"ReadWebhook",
|
||||
"SaveWebhook",
|
||||
"WebhookPagination",
|
||||
"WebhookType",
|
||||
"GroupDataExport",
|
||||
"CreateGroupPreferences",
|
||||
"ReadGroupPreferences",
|
||||
"UpdateGroupPreferences",
|
||||
"GroupStatistics",
|
||||
"GroupStorage",
|
||||
"DataMigrationCreate",
|
||||
"SupportedMigrations",
|
||||
"SeederConfig",
|
||||
"CreateInviteToken",
|
||||
"EmailInitationResponse",
|
||||
"EmailInvitation",
|
||||
"ReadInviteToken",
|
||||
"SaveInviteToken",
|
||||
"SetPermissions",
|
||||
"ShoppingListAddRecipeParams",
|
||||
"ShoppingListCreate",
|
||||
"ShoppingListItemBase",
|
||||
"ShoppingListItemCreate",
|
||||
"ShoppingListItemOut",
|
||||
"ShoppingListItemPagination",
|
||||
"ShoppingListItemRecipeRefCreate",
|
||||
"ShoppingListItemRecipeRefOut",
|
||||
"ShoppingListItemRecipeRefUpdate",
|
||||
"ShoppingListItemUpdate",
|
||||
"ShoppingListItemUpdateBulk",
|
||||
"ShoppingListItemsCollectionOut",
|
||||
"ShoppingListMultiPurposeLabelCreate",
|
||||
"ShoppingListMultiPurposeLabelOut",
|
||||
"ShoppingListMultiPurposeLabelUpdate",
|
||||
"ShoppingListOut",
|
||||
"ShoppingListPagination",
|
||||
"ShoppingListRecipeRefOut",
|
||||
"ShoppingListRemoveRecipeParams",
|
||||
"ShoppingListSave",
|
||||
"ShoppingListSummary",
|
||||
"ShoppingListUpdate",
|
||||
"GroupAdminUpdate",
|
||||
"CreateWebhook",
|
||||
"ReadWebhook",
|
||||
"SaveWebhook",
|
||||
"WebhookPagination",
|
||||
"WebhookType",
|
||||
"GroupAdminUpdate",
|
||||
"CreateGroupPreferences",
|
||||
"ReadGroupPreferences",
|
||||
"UpdateGroupPreferences",
|
||||
"SetPermissions",
|
||||
"DataMigrationCreate",
|
||||
"SupportedMigrations",
|
||||
"SeederConfig",
|
||||
"GroupDataExport",
|
||||
"CreateInviteToken",
|
||||
"EmailInitationResponse",
|
||||
"EmailInvitation",
|
||||
"ReadInviteToken",
|
||||
"SaveInviteToken",
|
||||
"GroupStatistics",
|
||||
"GroupStorage",
|
||||
"GroupEventNotifierCreate",
|
||||
"GroupEventNotifierOptions",
|
||||
"GroupEventNotifierOptionsOut",
|
||||
"GroupEventNotifierOptionsSave",
|
||||
"GroupEventNotifierOut",
|
||||
"GroupEventNotifierPrivate",
|
||||
"GroupEventNotifierSave",
|
||||
"GroupEventNotifierUpdate",
|
||||
"GroupEventPagination",
|
||||
]
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
from pydantic import UUID4, ConfigDict
|
||||
from sqlalchemy.orm import joinedload
|
||||
from sqlalchemy.orm.interfaces import LoaderOption
|
||||
|
||||
from mealie.db.models.group import GroupEventNotifierModel
|
||||
from mealie.schema._mealie import MealieModel
|
||||
from mealie.schema.response.pagination import PaginationBase
|
||||
|
||||
# =============================================================================
|
||||
# Group Events Notifier Options
|
||||
|
||||
|
||||
class GroupEventNotifierOptions(MealieModel):
|
||||
"""
|
||||
These events are in-sync with the EventTypes found in the EventBusService.
|
||||
If you modify this, make sure to update the EventBusService as well.
|
||||
"""
|
||||
|
||||
test_message: bool = False
|
||||
webhook_task: bool = False
|
||||
|
||||
recipe_created: bool = False
|
||||
recipe_updated: bool = False
|
||||
recipe_deleted: bool = False
|
||||
|
||||
user_signup: bool = False
|
||||
|
||||
data_migrations: bool = False
|
||||
data_export: bool = False
|
||||
data_import: bool = False
|
||||
|
||||
mealplan_entry_created: bool = False
|
||||
|
||||
shopping_list_created: bool = False
|
||||
shopping_list_updated: bool = False
|
||||
shopping_list_deleted: bool = False
|
||||
|
||||
cookbook_created: bool = False
|
||||
cookbook_updated: bool = False
|
||||
cookbook_deleted: bool = False
|
||||
|
||||
tag_created: bool = False
|
||||
tag_updated: bool = False
|
||||
tag_deleted: bool = False
|
||||
|
||||
category_created: bool = False
|
||||
category_updated: bool = False
|
||||
category_deleted: bool = False
|
||||
|
||||
|
||||
class GroupEventNotifierOptionsSave(GroupEventNotifierOptions):
|
||||
notifier_id: UUID4
|
||||
|
||||
|
||||
class GroupEventNotifierOptionsOut(GroupEventNotifierOptions):
|
||||
id: UUID4
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
# =======================================================================
|
||||
# Notifiers
|
||||
|
||||
|
||||
class GroupEventNotifierCreate(MealieModel):
|
||||
name: str
|
||||
apprise_url: str | None = None
|
||||
|
||||
|
||||
class GroupEventNotifierSave(GroupEventNotifierCreate):
|
||||
enabled: bool = True
|
||||
group_id: UUID4
|
||||
options: GroupEventNotifierOptions = GroupEventNotifierOptions()
|
||||
|
||||
|
||||
class GroupEventNotifierUpdate(GroupEventNotifierSave):
|
||||
id: UUID4
|
||||
apprise_url: str | None = None
|
||||
|
||||
|
||||
class GroupEventNotifierOut(MealieModel):
|
||||
id: UUID4
|
||||
name: str
|
||||
enabled: bool
|
||||
group_id: UUID4
|
||||
options: GroupEventNotifierOptionsOut
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@classmethod
|
||||
def loader_options(cls) -> list[LoaderOption]:
|
||||
return [joinedload(GroupEventNotifierModel.options)]
|
||||
|
||||
|
||||
class GroupEventPagination(PaginationBase):
|
||||
items: list[GroupEventNotifierOut]
|
||||
|
||||
|
||||
class GroupEventNotifierPrivate(GroupEventNotifierOut):
|
||||
apprise_url: str
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
@@ -1,10 +0,0 @@
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.schema._mealie import MealieModel
|
||||
|
||||
|
||||
class SetPermissions(MealieModel):
|
||||
user_id: UUID4
|
||||
can_manage: bool = False
|
||||
can_invite: bool = False
|
||||
can_organize: bool = False
|
||||
@@ -7,15 +7,6 @@ from mealie.schema._mealie import MealieModel
|
||||
|
||||
class UpdateGroupPreferences(MealieModel):
|
||||
private_group: bool = True
|
||||
first_day_of_week: int = 0
|
||||
|
||||
# Recipe Defaults
|
||||
recipe_public: bool = True
|
||||
recipe_show_nutrition: bool = False
|
||||
recipe_show_assets: bool = False
|
||||
recipe_landscape_view: bool = False
|
||||
recipe_disable_comments: bool = False
|
||||
recipe_disable_amount: bool = True
|
||||
|
||||
|
||||
class CreateGroupPreferences(UpdateGroupPreferences):
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import UUID4, ConfigDict
|
||||
|
||||
from mealie.schema._mealie import MealieModel
|
||||
from mealie.schema.response.pagination import PaginationBase
|
||||
|
||||
|
||||
class GroupRecipeActionType(Enum):
|
||||
link = "link"
|
||||
post = "post"
|
||||
|
||||
|
||||
class CreateGroupRecipeAction(MealieModel):
|
||||
action_type: GroupRecipeActionType
|
||||
title: str
|
||||
url: str
|
||||
|
||||
model_config = ConfigDict(use_enum_values=True)
|
||||
|
||||
|
||||
class SaveGroupRecipeAction(CreateGroupRecipeAction):
|
||||
group_id: UUID4
|
||||
|
||||
|
||||
class GroupRecipeActionOut(SaveGroupRecipeAction):
|
||||
id: UUID4
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class GroupRecipeActionPagination(PaginationBase):
|
||||
items: list[GroupRecipeActionOut]
|
||||
@@ -1,285 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import UUID4, ConfigDict, field_validator, model_validator
|
||||
from sqlalchemy.orm import joinedload, selectinload
|
||||
from sqlalchemy.orm.interfaces import LoaderOption
|
||||
|
||||
from mealie.db.models.group import (
|
||||
ShoppingList,
|
||||
ShoppingListItem,
|
||||
ShoppingListMultiPurposeLabel,
|
||||
ShoppingListRecipeReference,
|
||||
)
|
||||
from mealie.db.models.recipe import IngredientFoodModel, RecipeModel
|
||||
from mealie.schema._mealie import MealieModel
|
||||
from mealie.schema._mealie.types import NoneFloat
|
||||
from mealie.schema.labels.multi_purpose_label import MultiPurposeLabelSummary
|
||||
from mealie.schema.recipe.recipe import RecipeSummary
|
||||
from mealie.schema.recipe.recipe_ingredient import (
|
||||
IngredientFood,
|
||||
IngredientUnit,
|
||||
RecipeIngredient,
|
||||
RecipeIngredientBase,
|
||||
)
|
||||
from mealie.schema.response.pagination import PaginationBase
|
||||
|
||||
|
||||
class ShoppingListItemRecipeRefCreate(MealieModel):
|
||||
recipe_id: UUID4
|
||||
recipe_quantity: float = 0
|
||||
"""the quantity of this item in a single recipe (scale == 1)"""
|
||||
|
||||
recipe_scale: NoneFloat = 1
|
||||
"""the number of times this recipe has been added"""
|
||||
|
||||
recipe_note: str | None = None
|
||||
"""the original note from the recipe"""
|
||||
|
||||
@field_validator("recipe_quantity", mode="before")
|
||||
@classmethod
|
||||
def default_none_to_zero(cls, v):
|
||||
return 0 if v is None else v
|
||||
|
||||
|
||||
class ShoppingListItemRecipeRefUpdate(ShoppingListItemRecipeRefCreate):
|
||||
id: UUID4
|
||||
shopping_list_item_id: UUID4
|
||||
|
||||
|
||||
class ShoppingListItemRecipeRefOut(ShoppingListItemRecipeRefUpdate):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class ShoppingListItemBase(RecipeIngredientBase):
|
||||
shopping_list_id: UUID4
|
||||
checked: bool = False
|
||||
position: int = 0
|
||||
|
||||
quantity: float = 1
|
||||
|
||||
food_id: UUID4 | None = None
|
||||
label_id: UUID4 | None = None
|
||||
unit_id: UUID4 | None = None
|
||||
|
||||
is_food: bool = False
|
||||
extras: dict | None = {}
|
||||
|
||||
@field_validator("extras", mode="before")
|
||||
def convert_extras_to_dict(cls, v):
|
||||
if isinstance(v, dict):
|
||||
return v
|
||||
|
||||
return {x.key_name: x.value for x in v} if v else {}
|
||||
|
||||
|
||||
class ShoppingListItemCreate(ShoppingListItemBase):
|
||||
id: UUID4 | None = None
|
||||
"""The unique id of the item to create. If not supplied, one will be generated."""
|
||||
recipe_references: list[ShoppingListItemRecipeRefCreate] = []
|
||||
|
||||
@field_validator("id", mode="before")
|
||||
def validate_id(cls, v):
|
||||
v = v or None
|
||||
if not v or isinstance(v, UUID):
|
||||
return v
|
||||
|
||||
try:
|
||||
return UUID(v)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
class ShoppingListItemUpdate(ShoppingListItemBase):
|
||||
recipe_references: list[ShoppingListItemRecipeRefCreate | ShoppingListItemRecipeRefUpdate] = []
|
||||
|
||||
|
||||
class ShoppingListItemUpdateBulk(ShoppingListItemUpdate):
|
||||
"""Only used for bulk update operations where the shopping list item id isn't already supplied"""
|
||||
|
||||
id: UUID4
|
||||
|
||||
|
||||
class ShoppingListItemOut(ShoppingListItemBase):
|
||||
id: UUID4
|
||||
|
||||
food: IngredientFood | None = None
|
||||
label: MultiPurposeLabelSummary | None = None
|
||||
unit: IngredientUnit | None = None
|
||||
|
||||
recipe_references: list[ShoppingListItemRecipeRefOut] = []
|
||||
|
||||
created_at: datetime | None = None
|
||||
update_at: datetime | None = None
|
||||
|
||||
@model_validator(mode="after")
|
||||
def populate_missing_label(self):
|
||||
# if we're missing a label, but the food has a label, use that as the label
|
||||
if (not self.label) and (self.food and self.food.label):
|
||||
self.label = self.food.label
|
||||
self.label_id = self.label.id
|
||||
|
||||
return self
|
||||
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@classmethod
|
||||
def loader_options(cls) -> list[LoaderOption]:
|
||||
return [
|
||||
selectinload(ShoppingListItem.extras),
|
||||
selectinload(ShoppingListItem.food).joinedload(IngredientFoodModel.extras),
|
||||
selectinload(ShoppingListItem.food).joinedload(IngredientFoodModel.label),
|
||||
joinedload(ShoppingListItem.label),
|
||||
joinedload(ShoppingListItem.unit),
|
||||
selectinload(ShoppingListItem.recipe_references),
|
||||
]
|
||||
|
||||
|
||||
class ShoppingListItemsCollectionOut(MealieModel):
|
||||
"""Container for bulk shopping list item changes"""
|
||||
|
||||
created_items: list[ShoppingListItemOut] = []
|
||||
updated_items: list[ShoppingListItemOut] = []
|
||||
deleted_items: list[ShoppingListItemOut] = []
|
||||
|
||||
|
||||
class ShoppingListMultiPurposeLabelCreate(MealieModel):
|
||||
shopping_list_id: UUID4
|
||||
label_id: UUID4
|
||||
position: int = 0
|
||||
|
||||
|
||||
class ShoppingListMultiPurposeLabelUpdate(ShoppingListMultiPurposeLabelCreate):
|
||||
id: UUID4
|
||||
|
||||
|
||||
class ShoppingListMultiPurposeLabelOut(ShoppingListMultiPurposeLabelUpdate):
|
||||
label: MultiPurposeLabelSummary
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@classmethod
|
||||
def loader_options(cls) -> list[LoaderOption]:
|
||||
return [joinedload(ShoppingListMultiPurposeLabel.label)]
|
||||
|
||||
|
||||
class ShoppingListItemPagination(PaginationBase):
|
||||
items: list[ShoppingListItemOut]
|
||||
|
||||
|
||||
class ShoppingListCreate(MealieModel):
|
||||
name: str | None = None
|
||||
extras: dict | None = {}
|
||||
|
||||
created_at: datetime | None = None
|
||||
update_at: datetime | None = None
|
||||
|
||||
@field_validator("extras", mode="before")
|
||||
def convert_extras_to_dict(cls, v):
|
||||
if isinstance(v, dict):
|
||||
return v
|
||||
|
||||
return {x.key_name: x.value for x in v} if v else {}
|
||||
|
||||
|
||||
class ShoppingListRecipeRefOut(MealieModel):
|
||||
id: UUID4
|
||||
shopping_list_id: UUID4
|
||||
recipe_id: UUID4
|
||||
recipe_quantity: float
|
||||
"""the number of times this recipe has been added"""
|
||||
|
||||
recipe: RecipeSummary
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@classmethod
|
||||
def loader_options(cls) -> list[LoaderOption]:
|
||||
return [
|
||||
selectinload(ShoppingListRecipeReference.recipe).joinedload(RecipeModel.recipe_category),
|
||||
selectinload(ShoppingListRecipeReference.recipe).joinedload(RecipeModel.tags),
|
||||
selectinload(ShoppingListRecipeReference.recipe).joinedload(RecipeModel.tools),
|
||||
]
|
||||
|
||||
|
||||
class ShoppingListSave(ShoppingListCreate):
|
||||
group_id: UUID4
|
||||
user_id: UUID4
|
||||
|
||||
|
||||
class ShoppingListSummary(ShoppingListSave):
|
||||
id: UUID4
|
||||
recipe_references: list[ShoppingListRecipeRefOut]
|
||||
label_settings: list[ShoppingListMultiPurposeLabelOut]
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@classmethod
|
||||
def loader_options(cls) -> list[LoaderOption]:
|
||||
return [
|
||||
selectinload(ShoppingList.extras),
|
||||
selectinload(ShoppingList.recipe_references)
|
||||
.joinedload(ShoppingListRecipeReference.recipe)
|
||||
.joinedload(RecipeModel.recipe_category),
|
||||
selectinload(ShoppingList.recipe_references)
|
||||
.joinedload(ShoppingListRecipeReference.recipe)
|
||||
.joinedload(RecipeModel.tags),
|
||||
selectinload(ShoppingList.recipe_references)
|
||||
.joinedload(ShoppingListRecipeReference.recipe)
|
||||
.joinedload(RecipeModel.tools),
|
||||
selectinload(ShoppingList.label_settings).joinedload(ShoppingListMultiPurposeLabel.label),
|
||||
]
|
||||
|
||||
|
||||
class ShoppingListPagination(PaginationBase):
|
||||
items: list[ShoppingListSummary]
|
||||
|
||||
|
||||
class ShoppingListUpdate(ShoppingListSave):
|
||||
id: UUID4
|
||||
list_items: list[ShoppingListItemOut] = []
|
||||
|
||||
|
||||
class ShoppingListOut(ShoppingListUpdate):
|
||||
recipe_references: list[ShoppingListRecipeRefOut] = []
|
||||
label_settings: list[ShoppingListMultiPurposeLabelOut] = []
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
@field_validator("recipe_references", "label_settings", mode="before")
|
||||
def default_none_to_empty_list(cls, v):
|
||||
return v or []
|
||||
|
||||
@classmethod
|
||||
def loader_options(cls) -> list[LoaderOption]:
|
||||
return [
|
||||
selectinload(ShoppingList.extras),
|
||||
selectinload(ShoppingList.list_items).joinedload(ShoppingListItem.extras),
|
||||
selectinload(ShoppingList.list_items)
|
||||
.joinedload(ShoppingListItem.food)
|
||||
.joinedload(IngredientFoodModel.extras),
|
||||
selectinload(ShoppingList.list_items)
|
||||
.joinedload(ShoppingListItem.food)
|
||||
.joinedload(IngredientFoodModel.label),
|
||||
selectinload(ShoppingList.list_items).joinedload(ShoppingListItem.label),
|
||||
selectinload(ShoppingList.list_items).joinedload(ShoppingListItem.unit),
|
||||
selectinload(ShoppingList.list_items).joinedload(ShoppingListItem.recipe_references),
|
||||
selectinload(ShoppingList.recipe_references)
|
||||
.joinedload(ShoppingListRecipeReference.recipe)
|
||||
.joinedload(RecipeModel.recipe_category),
|
||||
selectinload(ShoppingList.recipe_references)
|
||||
.joinedload(ShoppingListRecipeReference.recipe)
|
||||
.joinedload(RecipeModel.tags),
|
||||
selectinload(ShoppingList.recipe_references)
|
||||
.joinedload(ShoppingListRecipeReference.recipe)
|
||||
.joinedload(RecipeModel.tools),
|
||||
selectinload(ShoppingList.label_settings).joinedload(ShoppingListMultiPurposeLabel.label),
|
||||
]
|
||||
|
||||
|
||||
class ShoppingListAddRecipeParams(MealieModel):
|
||||
recipe_increment_quantity: float = 1
|
||||
recipe_ingredients: list[RecipeIngredient] | None = None
|
||||
"""optionally override which ingredients are added from the recipe"""
|
||||
|
||||
|
||||
class ShoppingListRemoveRecipeParams(MealieModel):
|
||||
recipe_decrement_quantity: float = 1
|
||||
@@ -2,14 +2,6 @@ from mealie.pkgs.stats import fs_stats
|
||||
from mealie.schema._mealie import MealieModel
|
||||
|
||||
|
||||
class GroupStatistics(MealieModel):
|
||||
total_recipes: int
|
||||
total_users: int
|
||||
total_categories: int
|
||||
total_tags: int
|
||||
total_tools: int
|
||||
|
||||
|
||||
class GroupStorage(MealieModel):
|
||||
used_storage_bytes: int
|
||||
used_storage_str: str
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import ConfigDict
|
||||
|
||||
from mealie.schema._mealie import MealieModel
|
||||
|
||||
|
||||
class CreateInviteToken(MealieModel):
|
||||
uses: int
|
||||
|
||||
|
||||
class SaveInviteToken(MealieModel):
|
||||
uses_left: int
|
||||
group_id: UUID
|
||||
token: str
|
||||
|
||||
|
||||
class ReadInviteToken(MealieModel):
|
||||
token: str
|
||||
uses_left: int
|
||||
group_id: UUID
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class EmailInvitation(MealieModel):
|
||||
email: str
|
||||
token: str
|
||||
|
||||
|
||||
class EmailInitationResponse(MealieModel):
|
||||
success: bool
|
||||
error: str | None = None
|
||||
@@ -1,62 +0,0 @@
|
||||
import datetime
|
||||
import enum
|
||||
from uuid import UUID
|
||||
|
||||
from isodate import parse_time
|
||||
from pydantic import UUID4, ConfigDict, field_validator
|
||||
|
||||
from mealie.schema._mealie import MealieModel
|
||||
from mealie.schema._mealie.datetime_parse import parse_datetime
|
||||
from mealie.schema.response.pagination import PaginationBase
|
||||
|
||||
|
||||
class WebhookType(str, enum.Enum):
|
||||
mealplan = "mealplan"
|
||||
|
||||
|
||||
class CreateWebhook(MealieModel):
|
||||
enabled: bool = True
|
||||
name: str = ""
|
||||
url: str = ""
|
||||
|
||||
webhook_type: WebhookType = WebhookType.mealplan
|
||||
scheduled_time: datetime.time
|
||||
|
||||
@field_validator("scheduled_time", mode="before")
|
||||
@classmethod
|
||||
def validate_scheduled_time(cls, v):
|
||||
"""
|
||||
Validator accepts both datetime and time values from external sources.
|
||||
DateTime types are parsed and converted to time objects without timezones
|
||||
|
||||
type: time is treated as a UTC value
|
||||
type: datetime is treated as a value with a timezone
|
||||
"""
|
||||
parser_funcs = [
|
||||
lambda x: parse_datetime(x).astimezone(datetime.timezone.utc).time(),
|
||||
parse_time,
|
||||
]
|
||||
|
||||
if isinstance(v, datetime.time):
|
||||
return v
|
||||
|
||||
for parser_func in parser_funcs:
|
||||
try:
|
||||
return parser_func(v)
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
raise ValueError(f"Invalid scheduled time: {v}")
|
||||
|
||||
|
||||
class SaveWebhook(CreateWebhook):
|
||||
group_id: UUID
|
||||
|
||||
|
||||
class ReadWebhook(SaveWebhook):
|
||||
id: UUID4
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
|
||||
class WebhookPagination(PaginationBase):
|
||||
items: list[ReadWebhook]
|
||||
Reference in New Issue
Block a user