Feature/automated meal planner (#939)

* cleanup oversized buttons

* add get all by category function to reciep repos

* fix shopping-list can_merge logic

* use randomized data for testing

* add random getter to repository for meal-planner

* add stub route for random meals

* cleanup global namespace

* add rules database type

* fix type

* add plan rules schema

* test plan rules methods

* add mealplan rules controller

* add new repository

* update frontend types

* formatting

* fix regression

* update autogenerated types

* add api class for mealplan rules

* add tests and fix bugs

* fix data returns

* proof of concept rules editor

* add tag support

* remove old group categories

* add tag support

* implement random by rules api

* change snack to sides

* remove incorrect typing

* split repo for custom methods

* fix query and use and_ clause

* use repo function

* remove old test

* update changelog
This commit is contained in:
Hayden
2022-02-07 19:03:11 -09:00
committed by GitHub
parent 40d1f586cd
commit d1024e272d
43 changed files with 1153 additions and 175 deletions

View File

@@ -0,0 +1,29 @@
import random
from pydantic import UUID4
from mealie.repos.repository_factory import AllRepositories
from mealie.schema.recipe.recipe import Recipe, RecipeCategory
from mealie.services._base_service import BaseService
class MealPlanService(BaseService):
def __init__(self, group_id: UUID4, repos: AllRepositories):
self.group_id = group_id
self.repos = repos
def get_random_recipe(self, categories: list[RecipeCategory] = None) -> Recipe:
"""get_random_recipe returns a single recipe matching a specific criteria of
categories. if no categories are provided, a single recipe is returned from the
entire recipe databas.
Note that the recipe must contain ALL categories in the list provided.
Args:
categories (list[RecipeCategory], optional): [description]. Defaults to None.
Returns:
Recipe: [description]
"""
recipes = self.repos.recipes.by_group(self.group_id).get_by_categories(categories)
return random.choice(recipes)

View File

@@ -23,15 +23,26 @@ class ShoppingListService:
can_merge checks if the two items can be merged together.
"""
# If no food or units are present check against the notes field.
if not all([item1.food, item1.unit, item2.food, item2.unit]):
# Check if foods are equal
foods_is_none = item1.food_id is None and item2.food_id is None
foods_not_none = not foods_is_none
foods_equal = item1.food_id == item2.food_id
# Check if units are equal
units_is_none = item1.unit_id is None and item2.unit_id is None
units_not_none = not units_is_none
units_equal = item1.unit_id == item2.unit_id
# Check if Notes are equal
if foods_is_none and units_is_none:
return item1.note == item2.note
# If the items have the same food and unit they can be merged.
if item1.unit == item2.unit and item1.food == item2.food:
return True
if foods_not_none and units_not_none:
return foods_equal and units_equal
if foods_not_none:
return foods_equal
# Otherwise Assume They Can't Be Merged
return False
def consolidate_list_items(self, item_list: list[ShoppingListItemOut]) -> list[ShoppingListItemOut]: