pytest edit shopping list recipes
This commit is contained in:
parent
262387da3e
commit
a51eb7a2cb
@ -52,12 +52,14 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
if not r:
|
if not r:
|
||||||
raise ValueError(_("You must supply a recipe or mealplan"))
|
raise ValueError(_("You must supply a recipe or mealplan"))
|
||||||
|
|
||||||
created_by = created_by or getattr(mealplan, 'created_by', None) or getattr(list_recipe, 'created_by', None)
|
|
||||||
if not created_by:
|
if not created_by:
|
||||||
raise ValueError(_("You must supply a created_by"))
|
raise ValueError(_("You must supply a created_by"))
|
||||||
|
|
||||||
if type(servings) not in [int, float]:
|
try:
|
||||||
|
servings = float(servings)
|
||||||
|
except ValueError:
|
||||||
servings = getattr(mealplan, 'servings', 1.0)
|
servings = getattr(mealplan, 'servings', 1.0)
|
||||||
|
|
||||||
servings_factor = servings / r.servings
|
servings_factor = servings / r.servings
|
||||||
|
|
||||||
shared_users = list(created_by.get_shopping_share())
|
shared_users = list(created_by.get_shopping_share())
|
||||||
@ -68,6 +70,7 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings)
|
list_recipe = ShoppingListRecipe.objects.create(recipe=r, mealplan=mealplan, servings=servings)
|
||||||
created = True
|
created = True
|
||||||
|
|
||||||
|
related_step_ing = []
|
||||||
if servings == 0 and not created:
|
if servings == 0 and not created:
|
||||||
list_recipe.delete()
|
list_recipe.delete()
|
||||||
return []
|
return []
|
||||||
@ -79,7 +82,6 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
|
if exclude_onhand := created_by.userpreference.mealplan_autoexclude_onhand:
|
||||||
ingredients = ingredients.exclude(food__on_hand=True)
|
ingredients = ingredients.exclude(food__on_hand=True)
|
||||||
|
|
||||||
related_step_ing = []
|
|
||||||
if related := created_by.userpreference.mealplan_autoinclude_related:
|
if related := created_by.userpreference.mealplan_autoinclude_related:
|
||||||
# TODO: add levels of related recipes to use when auto-adding mealplans
|
# TODO: add levels of related recipes to use when auto-adding mealplans
|
||||||
related_recipes = r.get_related_recipes()
|
related_recipes = r.get_related_recipes()
|
||||||
@ -128,6 +130,8 @@ def list_from_recipe(list_recipe=None, recipe=None, mealplan=None, servings=None
|
|||||||
|
|
||||||
if not created and list_recipe.servings != servings:
|
if not created and list_recipe.servings != servings:
|
||||||
update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True))
|
update_ingredients = set(ingredients.values_list('id', flat=True)) - set(add_ingredients.values_list('id', flat=True))
|
||||||
|
list_recipe.servings = servings
|
||||||
|
list_recipe.save()
|
||||||
for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients):
|
for sle in ShoppingListEntry.objects.filter(list_recipe=list_recipe, ingredient__id__in=update_ingredients):
|
||||||
sle.amount = sle.ingredient.amount * Decimal(servings_factor)
|
sle.amount = sle.ingredient.amount * Decimal(servings_factor)
|
||||||
sle.save()
|
sle.save()
|
||||||
|
@ -10,7 +10,7 @@ from django.utils import timezone
|
|||||||
from django_scopes import scopes_disabled
|
from django_scopes import scopes_disabled
|
||||||
from pytest_factoryboy import LazyFixture, register
|
from pytest_factoryboy import LazyFixture, register
|
||||||
|
|
||||||
from cookbook.models import ShoppingListEntry
|
from cookbook.models import Ingredient, ShoppingListEntry
|
||||||
from cookbook.tests.factories import RecipeFactory
|
from cookbook.tests.factories import RecipeFactory
|
||||||
|
|
||||||
SHOPPING_LIST_URL = 'api:shoppinglistentry-list'
|
SHOPPING_LIST_URL = 'api:shoppinglistentry-list'
|
||||||
@ -82,7 +82,69 @@ def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
|
|||||||
assert r.status_code == 405
|
assert r.status_code == 405
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("recipe, sle_count", [
|
||||||
|
({}, 10),
|
||||||
|
({'steps__recipe_count': 1}, 20), # shopping list from recipe with StepRecipe
|
||||||
|
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19), # shopping list from recipe with food recipe
|
||||||
|
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29), # shopping list from recipe with StepRecipe and food recipe
|
||||||
|
], indirect=['recipe'])
|
||||||
|
def test_shopping_recipe_edit(request, recipe, sle_count, u1_s1, u2_s1):
|
||||||
|
with scopes_disabled(): # TODO take out
|
||||||
|
|
||||||
|
user = auth.get_user(u1_s1)
|
||||||
|
user2 = auth.get_user(u2_s1)
|
||||||
|
user.userpreference.mealplan_autoinclude_related = True
|
||||||
|
user.userpreference.shopping_share.add(user2)
|
||||||
|
user.userpreference.save()
|
||||||
|
|
||||||
|
r = u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
||||||
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
|
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
|
||||||
|
all_ing = [x['ingredient'] for x in r]
|
||||||
|
keep_ing = [x['ingredient'] for x in r[2:]] # TODO change this to remove 1 from each third
|
||||||
|
list_recipe = r[0]['list_recipe']
|
||||||
|
amount_sum = sum([x['amount'] for x in r])
|
||||||
|
|
||||||
|
# test modifying shopping list as different user
|
||||||
|
# test increasing servings size of recipe shopping list
|
||||||
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
|
{'list_recipe': list_recipe, 'servings': 2*recipe.servings},
|
||||||
|
content_type='application/json'
|
||||||
|
)
|
||||||
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
|
assert sum([x['amount'] for x in r]) == amount_sum * 2
|
||||||
|
assert len(r) == sle_count
|
||||||
|
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
|
# testing decreasing servings size of recipe shopping list
|
||||||
|
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
|
{'list_recipe': list_recipe, 'servings': .5 * recipe.servings},
|
||||||
|
content_type='application/json'
|
||||||
|
)
|
||||||
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
|
assert sum([x['amount'] for x in r]) == amount_sum * .5
|
||||||
|
assert len(r) == sle_count
|
||||||
|
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
|
# test removing 2 items from shopping list
|
||||||
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
|
{'list_recipe': list_recipe, 'ingredients': keep_ing},
|
||||||
|
content_type='application/json'
|
||||||
|
)
|
||||||
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
|
assert len(r) == sle_count - 2
|
||||||
|
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - 2
|
||||||
|
|
||||||
|
# add all ingredients to existing shopping list - don't change serving size
|
||||||
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
|
{'list_recipe': list_recipe, 'ingredients': all_ing},
|
||||||
|
content_type='application/json'
|
||||||
|
)
|
||||||
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
|
assert sum([x['amount'] for x in r]) == amount_sum * .5
|
||||||
|
assert len(r) == sle_count
|
||||||
|
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
|
|
||||||
# TODO test creating shopping list from recipe that includes recipes from multiple users
|
# TODO test creating shopping list from recipe that includes recipes from multiple users
|
||||||
# TODO test create shopping list from recipe, excluding ingredients
|
|
||||||
# TODO meal plan recipe with all the user preferences tested
|
# TODO meal plan recipe with all the user preferences tested
|
||||||
# TODO shopping list from recipe with different servings
|
|
||||||
|
@ -661,10 +661,15 @@ class RecipeViewSet(viewsets.ModelViewSet):
|
|||||||
def shopping(self, request, pk):
|
def shopping(self, request, pk):
|
||||||
obj = self.get_object()
|
obj = self.get_object()
|
||||||
ingredients = request.data.get('ingredients', None)
|
ingredients = request.data.get('ingredients', None)
|
||||||
servings = request.data.get('servings', obj.servings)
|
servings = request.data.get('servings', None)
|
||||||
list_recipe = request.data.get('list_recipe', None)
|
list_recipe = ShoppingListRecipe.objects.filter(id=request.data.get('list_recipe', None)).first()
|
||||||
|
if servings is None:
|
||||||
|
servings = getattr(list_recipe, 'servings', obj.servings)
|
||||||
|
# created_by needs to be sticky to original creator as it is 'their' shopping list
|
||||||
|
# changing shopping list created_by can shift some items to new owner which may not share in the other direction
|
||||||
|
created_by = getattr(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), 'created_by', request.user)
|
||||||
content = {'msg': _(f'{obj.name} was added to the shopping list.')}
|
content = {'msg': _(f'{obj.name} was added to the shopping list.')}
|
||||||
list_from_recipe(list_recipe=list_recipe, recipe=obj, ingredients=ingredients, servings=servings, space=request.space, created_by=request.user)
|
list_from_recipe(list_recipe=list_recipe, recipe=obj, ingredients=ingredients, servings=servings, space=request.space, created_by=created_by)
|
||||||
|
|
||||||
return Response(content, status=status.HTTP_204_NO_CONTENT)
|
return Response(content, status=status.HTTP_204_NO_CONTENT)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user