This commit is contained in:
smilerz
2021-12-13 15:06:04 -06:00
parent 6d1476b2d8
commit c32a96fd6f
4 changed files with 105 additions and 51 deletions

View File

@ -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"))

View File

@ -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)

View File

@ -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

View File

@ -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'