1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-07-24 15:49:42 +02:00

feat: Add Households to Mealie (#3970)

This commit is contained in:
Michael Genson 2024-08-22 10:14:32 -05:00 committed by GitHub
parent 0c29cef17d
commit eb170cc7e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
315 changed files with 6975 additions and 3577 deletions

View file

@ -12,7 +12,7 @@ from pydantic import UUID4
from mealie.repos.repository_factory import AllRepositories
from mealie.repos.repository_units import RepositoryUnit
from mealie.schema.group.group_shopping_list import (
from mealie.schema.household.group_shopping_list import (
ShoppingListItemCreate,
ShoppingListMultiPurposeLabelCreate,
ShoppingListMultiPurposeLabelOut,
@ -64,14 +64,15 @@ def get_label_position_from_label_id(label_id: UUID4, label_settings: list[Shopp
raise Exception("Something went wrong when parsing label settings")
def test_repository_pagination(database: AllRepositories, unique_user: TestUser):
def test_repository_pagination(unique_user: TestUser):
database = unique_user.repos
group = database.groups.get_one(unique_user.group_id)
assert group
seeder = SeederService(database, None, group) # type: ignore
seeder = SeederService(AllRepositories(database.session, group_id=group.id))
seeder.seed_foods("en-US")
foods_repo = database.ingredient_foods.by_group(unique_user.group_id) # type: ignore
foods_repo = database.ingredient_foods
query = PaginationQuery(
page=1,
@ -99,14 +100,15 @@ def test_repository_pagination(database: AllRepositories, unique_user: TestUser)
assert result.id not in seen
def test_pagination_response_and_metadata(database: AllRepositories, unique_user: TestUser):
def test_pagination_response_and_metadata(unique_user: TestUser):
database = unique_user.repos
group = database.groups.get_one(unique_user.group_id)
assert group
seeder = SeederService(database, None, group) # type: ignore
seeder = SeederService(AllRepositories(database.session, group_id=group.id))
seeder.seed_foods("en-US")
foods_repo = database.ingredient_foods.by_group(unique_user.group_id) # type: ignore
foods_repo = database.ingredient_foods
# this should get all results
query = PaginationQuery(
@ -128,14 +130,15 @@ def test_pagination_response_and_metadata(database: AllRepositories, unique_user
assert last_page_of_results.items[-1] == all_results.items[-1]
def test_pagination_guides(database: AllRepositories, unique_user: TestUser):
def test_pagination_guides(unique_user: TestUser):
database = unique_user.repos
group = database.groups.get_one(unique_user.group_id)
assert group
seeder = SeederService(database, None, group) # type: ignore
seeder = SeederService(AllRepositories(database.session, group_id=group.id))
seeder.seed_foods("en-US")
foods_repo = database.ingredient_foods.by_group(unique_user.group_id) # type: ignore
foods_repo = database.ingredient_foods
foods_route = (
"/foods" # this doesn't actually have to be accurate, it's just a placeholder to test for query params
)
@ -173,7 +176,8 @@ def test_pagination_guides(database: AllRepositories, unique_user: TestUser):
@pytest.fixture(scope="function")
def query_units(database: AllRepositories, unique_user: TestUser):
def query_units(unique_user: TestUser):
database = unique_user.repos
unit_1 = database.ingredient_units.create(
SaveIngredientUnit(name="test unit 1", group_id=unique_user.group_id, use_abbreviation=True)
)
@ -193,7 +197,7 @@ def query_units(database: AllRepositories, unique_user: TestUser):
)
unit_ids = [unit.id for unit in [unit_1, unit_2, unit_3]]
units_repo = database.ingredient_units.by_group(unique_user.group_id) # type: ignore
units_repo = database.ingredient_units
yield units_repo, unit_1, unit_2, unit_3
@ -211,7 +215,8 @@ def test_pagination_filter_basic(query_units: tuple[RepositoryUnit, IngredientUn
assert unit_results[0].id == unit_2.id
def test_pagination_filter_null(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_null(unique_user: TestUser):
database = unique_user.repos
recipe_not_made_1 = database.recipes.create(
Recipe(
user_id=unique_user.user_id,
@ -237,7 +242,7 @@ def test_pagination_filter_null(database: AllRepositories, unique_user: TestUser
)
)
recipe_repo = database.recipes.by_group(unique_user.group_id) # type: ignore
recipe_repo = database.recipes
query = PaginationQuery(page=1, per_page=-1, query_filter="lastMade IS NONE")
recipe_results = recipe_repo.page_all(query).items
@ -300,7 +305,8 @@ def test_pagination_filter_in(query_units: tuple[RepositoryUnit, IngredientUnit,
assert unit_3.id in result_ids
def test_pagination_filter_in_advanced(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_in_advanced(unique_user: TestUser):
database = unique_user.repos
slug1, slug2 = (random_string(10) for _ in range(2))
tags = [
@ -418,7 +424,8 @@ def test_pagination_filter_like(query_units: tuple[RepositoryUnit, IngredientUni
assert unit_3.id in result_ids
def test_pagination_filter_keyword_namespace_conflict(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_keyword_namespace_conflict(unique_user: TestUser):
database = unique_user.repos
recipe_rating_1 = database.recipes.create(
Recipe(
user_id=unique_user.user_id,
@ -445,7 +452,7 @@ def test_pagination_filter_keyword_namespace_conflict(database: AllRepositories,
)
)
recipe_repo = database.recipes.by_group(unique_user.group_id) # type: ignore
recipe_repo = database.recipes
# "rating" contains the word "in", but we should not parse this as the keyword "IN"
query = PaginationQuery(page=1, per_page=-1, query_filter="rating > 2")
@ -467,7 +474,8 @@ def test_pagination_filter_keyword_namespace_conflict(database: AllRepositories,
assert recipe_rating_3.id in result_ids
def test_pagination_filter_logical_namespace_conflict(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_logical_namespace_conflict(unique_user: TestUser):
database = unique_user.repos
categories = [
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
@ -509,7 +517,7 @@ def test_pagination_filter_logical_namespace_conflict(database: AllRepositories,
# "recipeCategory" has the substring "or" in it, which shouldn't break queries
query = PaginationQuery(page=1, per_page=-1, query_filter=f'recipeCategory.id = "{category_1.id}"')
recipe_results = database.recipes.by_group(unique_user.group_id).page_all(query).items # type: ignore
recipe_results = database.recipes.page_all(query).items
assert len(recipe_results) == 1
recipe_ids = {recipe.id for recipe in recipe_results}
assert recipe_category_0.id not in recipe_ids
@ -616,9 +624,8 @@ def test_pagination_filter_datetimes(
[OrderDirection.asc, OrderDirection.desc],
ids=["ascending", "descending"],
)
def test_pagination_order_by_multiple(
database: AllRepositories, unique_user: TestUser, order_direction: OrderDirection
):
def test_pagination_order_by_multiple(unique_user: TestUser, order_direction: OrderDirection):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
alphabet = ["a", "b", "c", "d", "e"]
@ -676,11 +683,9 @@ def test_pagination_order_by_multiple(
],
)
def test_pagination_order_by_multiple_directions(
database: AllRepositories,
unique_user: TestUser,
order_by_str: str,
order_direction: OrderDirection,
unique_user: TestUser, order_by_str: str, order_direction: OrderDirection
):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
alphabet = ["a", "b", "c", "d", "e"]
@ -726,9 +731,8 @@ def test_pagination_order_by_multiple_directions(
[OrderDirection.asc, OrderDirection.desc],
ids=["order_ascending", "order_descending"],
)
def test_pagination_order_by_nested_model(
database: AllRepositories, unique_user: TestUser, order_direction: OrderDirection
):
def test_pagination_order_by_nested_model(unique_user: TestUser, order_direction: OrderDirection):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
alphabet = ["a", "b", "c", "d", "e"]
@ -758,7 +762,8 @@ def test_pagination_order_by_nested_model(
assert query.items == sorted_foods
def test_pagination_order_by_doesnt_filter(database: AllRepositories, unique_user: TestUser):
def test_pagination_order_by_doesnt_filter(unique_user: TestUser):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
label = database.group_multi_purpose_labels.create(
@ -771,7 +776,7 @@ def test_pagination_order_by_doesnt_filter(database: AllRepositories, unique_use
SaveIngredientFood(name=random_string(), group_id=unique_user.group_id)
)
query = database.ingredient_foods.by_group(unique_user.group_id).page_all(
query = database.ingredient_foods.page_all(
PaginationQuery(
per_page=-1,
query_filter=f"created_at>{current_time.isoformat()}",
@ -800,11 +805,9 @@ def test_pagination_order_by_doesnt_filter(database: AllRepositories, unique_use
],
)
def test_pagination_order_by_nulls(
database: AllRepositories,
unique_user: TestUser,
null_position: OrderByNullPosition,
order_direction: OrderDirection,
unique_user: TestUser, null_position: OrderByNullPosition, order_direction: OrderDirection
):
database = unique_user.repos
current_time = datetime.now(timezone.utc)
label = database.group_multi_purpose_labels.create(
@ -836,7 +839,9 @@ def test_pagination_order_by_nulls(
assert query.items[1] == food_without_label
def test_pagination_shopping_list_items_with_labels(database: AllRepositories, unique_user: TestUser):
def test_pagination_shopping_list_items_with_labels(unique_user: TestUser):
database = unique_user.repos
# create a shopping list and populate it with some items with labels, and some without labels
shopping_list = database.group_shopping_lists.create(
ShoppingListSave(
@ -926,7 +931,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
for mealplan_to_create in [mealplan_today, mealplan_tomorrow]:
data = mealplan_to_create.model_dump()
data["date"] = data["date"].strftime("%Y-%m-%d")
response = api_client.post(api_routes.groups_mealplans, json=data, headers=unique_user.token)
response = api_client.post(api_routes.households_mealplans, json=data, headers=unique_user.token)
assert response.status_code == 201
## Yesterday
@ -935,7 +940,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {yesterday.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -949,7 +954,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {yesterday.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -964,7 +969,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {today.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -978,7 +983,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {today.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -993,7 +998,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -1007,7 +1012,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
@ -1019,7 +1024,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date >= {day_after_tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
assert len(response_json["items"]) == 0
@ -1029,7 +1034,7 @@ def test_pagination_filter_dates(api_client: TestClient, unique_user: TestUser):
"perPage": -1,
"queryFilter": f"date > {day_after_tomorrow.strftime('%Y-%m-%d')}",
}
response = api_client.get(api_routes.groups_mealplans, params=params, headers=unique_user.token)
response = api_client.get(api_routes.households_mealplans, params=params, headers=unique_user.token)
assert response.status_code == 200
response_json = response.json()
assert len(response_json["items"]) == 0
@ -1072,7 +1077,8 @@ def test_pagination_filter_advanced(query_units: tuple[RepositoryUnit, Ingredien
assert unit_3.id not in result_ids
def test_pagination_filter_advanced_frontend_sort(database: AllRepositories, unique_user: TestUser):
def test_pagination_filter_advanced_frontend_sort(unique_user: TestUser):
database = unique_user.repos
categories = [
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
CategorySave(group_id=unique_user.group_id, name=random_string(10)),
@ -1174,7 +1180,7 @@ def test_pagination_filter_advanced_frontend_sort(database: AllRepositories, uni
)
)
repo = database.recipes.by_group(unique_user.group_id) # type: ignore
repo = database.recipes
qf = f'recipeCategory.id IN ["{category_1.id}"] AND tools.id IN ["{tool_1.id}"]'
query = PaginationQuery(page=1, per_page=-1, query_filter=qf)