update
This commit is contained in:
@ -5,6 +5,7 @@ from django.contrib.postgres.aggregates import ArrayAgg
|
|||||||
from django.db.models import F, OuterRef, Q, Subquery, Value
|
from django.db.models import F, OuterRef, Q, Subquery, Value
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from cookbook.helper.HelperFunctions import Round, str2bool
|
from cookbook.helper.HelperFunctions import Round, str2bool
|
||||||
from cookbook.models import (Ingredient, ShoppingListEntry, ShoppingListRecipe,
|
from cookbook.models import (Ingredient, ShoppingListEntry, ShoppingListRecipe,
|
||||||
@ -52,6 +53,7 @@ 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(ShoppingListEntry.objects.filter(list_recipe=list_recipe).first(), '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"))
|
||||||
|
|
||||||
|
@ -94,17 +94,19 @@ def update_food_inheritance(sender, instance=None, created=False, **kwargs):
|
|||||||
@receiver(post_save, sender=MealPlan)
|
@receiver(post_save, sender=MealPlan)
|
||||||
def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs):
|
def auto_add_shopping(sender, instance=None, created=False, weak=False, **kwargs):
|
||||||
user = instance.get_owner()
|
user = instance.get_owner()
|
||||||
if not created or not user.userpreference.mealplan_autoadd_shopping:
|
if not user.userpreference.mealplan_autoadd_shopping:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if not created and instance.shoppinglistrecipe_set.exists():
|
||||||
|
for x in instance.shoppinglistrecipe_set.all():
|
||||||
|
if instance.servings != x.servings:
|
||||||
|
list_recipe = list_from_recipe(list_recipe=x, servings=instance.servings, space=instance.space)
|
||||||
|
elif created:
|
||||||
# if creating a mealplan - perform shopping list activities
|
# if creating a mealplan - perform shopping list activities
|
||||||
space = instance.space
|
|
||||||
if user.userpreference.mealplan_autoadd_shopping:
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'mealplan': instance,
|
'mealplan': instance,
|
||||||
'space': space,
|
'space': instance.space,
|
||||||
'created_by': user,
|
'created_by': user,
|
||||||
'servings': instance.servings
|
'servings': instance.servings
|
||||||
}
|
}
|
||||||
|
|
||||||
list_recipe = list_from_recipe(**kwargs)
|
list_recipe = list_from_recipe(**kwargs)
|
||||||
|
@ -11,12 +11,27 @@ from django_scopes import scopes_disabled
|
|||||||
from pytest_factoryboy import LazyFixture, register
|
from pytest_factoryboy import LazyFixture, register
|
||||||
|
|
||||||
from cookbook.models import Ingredient, ShoppingListEntry
|
from cookbook.models import Ingredient, ShoppingListEntry
|
||||||
from cookbook.tests.factories import RecipeFactory
|
from cookbook.tests.factories import MealPlanFactory, RecipeFactory, UserFactory
|
||||||
|
|
||||||
SHOPPING_LIST_URL = 'api:shoppinglistentry-list'
|
SHOPPING_LIST_URL = 'api:shoppinglistentry-list'
|
||||||
SHOPPING_RECIPE_URL = 'api:recipe-shopping'
|
SHOPPING_RECIPE_URL = 'api:recipe-shopping'
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def user2(request, u1_s1):
|
||||||
|
try:
|
||||||
|
params = request.param # request.param is a magic variable
|
||||||
|
except AttributeError:
|
||||||
|
params = {}
|
||||||
|
user = auth.get_user(u1_s1)
|
||||||
|
user.userpreference.mealplan_autoadd_shopping = True
|
||||||
|
user.userpreference.mealplan_autoinclude_related = True
|
||||||
|
key = list(params)[0]
|
||||||
|
setattr(user.userpreference, key, params[key])
|
||||||
|
user.userpreference.save
|
||||||
|
return u1_s1
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def recipe(request, space_1, u1_s1):
|
def recipe(request, space_1, u1_s1):
|
||||||
try:
|
try:
|
||||||
@ -88,25 +103,34 @@ def test_shopping_recipe_method(request, arg, recipe, sle_count, u1_s1, u2_s1):
|
|||||||
({'steps__food_recipe_count': {'step': 0, 'count': 1}}, 19), # shopping list from recipe with food recipe
|
({'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
|
({'steps__food_recipe_count': {'step': 0, 'count': 1}, 'steps__recipe_count': 1}, 29), # shopping list from recipe with StepRecipe and food recipe
|
||||||
], indirect=['recipe'])
|
], indirect=['recipe'])
|
||||||
def test_shopping_recipe_edit(request, recipe, sle_count, u1_s1, u2_s1):
|
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
||||||
with scopes_disabled(): # TODO take out
|
def test_shopping_recipe_edit(request, recipe, sle_count, use_mealplan, u1_s1, u2_s1):
|
||||||
|
# tests editing shopping list via recipe or mealplan
|
||||||
user = auth.get_user(u1_s1)
|
user = auth.get_user(u1_s1)
|
||||||
user2 = auth.get_user(u2_s1)
|
user2 = auth.get_user(u2_s1)
|
||||||
user.userpreference.mealplan_autoinclude_related = True
|
user.userpreference.mealplan_autoinclude_related = True
|
||||||
|
user.userpreference.mealplan_autoadd_shopping = True
|
||||||
user.userpreference.shopping_share.add(user2)
|
user.userpreference.shopping_share.add(user2)
|
||||||
user.userpreference.save()
|
user.userpreference.save()
|
||||||
|
|
||||||
r = u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
if use_mealplan:
|
||||||
|
mealplan = MealPlanFactory(space=recipe.space, created_by=user, servings=recipe.servings, recipe=recipe)
|
||||||
|
else:
|
||||||
|
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}))
|
||||||
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
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
|
assert [x['created_by']['id'] for x in r].count(user.id) == sle_count
|
||||||
all_ing = [x['ingredient'] for x in r]
|
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
|
keep_ing = all_ing[1:-1] # remove first and last element
|
||||||
|
del keep_ing[int(len(keep_ing)/2)] # remove a middle element
|
||||||
list_recipe = r[0]['list_recipe']
|
list_recipe = r[0]['list_recipe']
|
||||||
amount_sum = sum([x['amount'] for x in r])
|
amount_sum = sum([x['amount'] for x in r])
|
||||||
|
|
||||||
# test modifying shopping list as different user
|
# test modifying shopping list as different user
|
||||||
# test increasing servings size of recipe shopping list
|
# test increasing servings size of recipe shopping list
|
||||||
|
if use_mealplan:
|
||||||
|
mealplan.servings = 2*recipe.servings
|
||||||
|
mealplan.save()
|
||||||
|
else:
|
||||||
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
{'list_recipe': list_recipe, 'servings': 2*recipe.servings},
|
{'list_recipe': list_recipe, 'servings': 2*recipe.servings},
|
||||||
content_type='application/json'
|
content_type='application/json'
|
||||||
@ -117,6 +141,10 @@ def test_shopping_recipe_edit(request, recipe, sle_count, u1_s1, u2_s1):
|
|||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
# testing decreasing servings size of recipe shopping list
|
# testing decreasing servings size of recipe shopping list
|
||||||
|
if use_mealplan:
|
||||||
|
mealplan.servings = .5 * recipe.servings
|
||||||
|
mealplan.save()
|
||||||
|
else:
|
||||||
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
u1_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
{'list_recipe': list_recipe, 'servings': .5 * recipe.servings},
|
{'list_recipe': list_recipe, 'servings': .5 * recipe.servings},
|
||||||
content_type='application/json'
|
content_type='application/json'
|
||||||
@ -132,8 +160,8 @@ def test_shopping_recipe_edit(request, recipe, sle_count, u1_s1, u2_s1):
|
|||||||
content_type='application/json'
|
content_type='application/json'
|
||||||
)
|
)
|
||||||
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
r = json.loads(u1_s1.get(reverse(SHOPPING_LIST_URL)).content)
|
||||||
assert len(r) == sle_count - 2
|
assert len(r) == sle_count - 3
|
||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - 2
|
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count - 3
|
||||||
|
|
||||||
# add all ingredients to existing shopping list - don't change serving size
|
# add all ingredients to existing shopping list - don't change serving size
|
||||||
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
u2_s1.put(reverse(SHOPPING_RECIPE_URL, args={recipe.id}),
|
||||||
@ -146,5 +174,27 @@ def test_shopping_recipe_edit(request, recipe, sle_count, u1_s1, u2_s1):
|
|||||||
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
assert len(json.loads(u2_s1.get(reverse(SHOPPING_LIST_URL)).content)) == sle_count
|
||||||
|
|
||||||
|
|
||||||
|
# auto add shopping, no
|
||||||
|
# auto include related, no
|
||||||
|
# auto ignore onhand
|
||||||
|
# ignore shopping food
|
||||||
|
@pytest.mark.parametrize("user2, sle_count", [
|
||||||
|
({'mealplan_autoadd_shopping': False}, 0),
|
||||||
|
({'mealplan_autoinclude_related': False}, 9),
|
||||||
|
({'mealplan_autoexclude_onhand': True}, 27), # shopping list from recipe with StepRecipe
|
||||||
|
], indirect=['user2'])
|
||||||
|
@pytest.mark.parametrize("use_mealplan", [(False), (True), ])
|
||||||
|
@pytest.mark.parametrize("recipe", [({'steps__recipe_count': 1})], indirect=['recipe'])
|
||||||
|
def test_shopping_recipe_userpreference(request, recipe, sle_count, use_mealplan, user2):
|
||||||
|
with scopes_disabled():
|
||||||
|
user = auth.get_user(user2)
|
||||||
|
# setup recipe with 10 ingredients, 1 step recipe with 10 ingredients, 1 food onhand, 1 food ignore shopping
|
||||||
|
recipe.step.all()
|
||||||
|
|
||||||
|
|
||||||
|
def test_shopping_recipe_mixed_authors(request, user2):
|
||||||
|
assert 1 == 1
|
||||||
|
|
||||||
|
|
||||||
# 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 meal plan recipe with all the user preferences tested
|
# TODO meal plan recipe with all the user preferences tested
|
||||||
|
@ -195,7 +195,7 @@ class MealPlanFactory(factory.django.DjangoModelFactory):
|
|||||||
space = factory.SubFactory(SpaceFactory)
|
space = factory.SubFactory(SpaceFactory)
|
||||||
|
|
||||||
class Params:
|
class Params:
|
||||||
has_recipe = False
|
has_recipe = True
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = 'cookbook.MealPlan'
|
model = 'cookbook.MealPlan'
|
||||||
|
Reference in New Issue
Block a user