diff --git a/cookbook/admin.py b/cookbook/admin.py index 3110431c..cd0acf9e 100644 --- a/cookbook/admin.py +++ b/cookbook/admin.py @@ -15,7 +15,7 @@ from .models import (BookmarkletImport, Comment, CookLog, Food, FoodInheritField Recipe, RecipeBook, RecipeBookEntry, RecipeImport, SearchPreference, ShareLink, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, - TelegramBot, Unit, UserFile, UserPreference, ViewLog, Automation, UserSpace, UnitConversion, NutritionType, FoodNutrition) + TelegramBot, Unit, UserFile, UserPreference, ViewLog, Automation, UserSpace, UnitConversion, FoodPropertyType, FoodProperty) class CustomUserAdmin(UserAdmin): @@ -327,18 +327,18 @@ class ShareLinkAdmin(admin.ModelAdmin): admin.site.register(ShareLink, ShareLinkAdmin) -class NutritionTypeAdmin(admin.ModelAdmin): +class FoodPropertyTypeAdmin(admin.ModelAdmin): list_display = ('id', 'name') -admin.site.register(NutritionType, NutritionTypeAdmin) +admin.site.register(FoodPropertyType, FoodPropertyTypeAdmin) -class FoodNutritionAdmin(admin.ModelAdmin): - list_display = ('id', 'food_amount', 'food_unit', 'food', 'nutrition_amount', 'nutrition_type') +class FoodPropertyAdmin(admin.ModelAdmin): + list_display = ('id', 'food_amount', 'food_unit', 'food', 'property_amount', 'property_type') -admin.site.register(FoodNutrition, FoodNutritionAdmin) +admin.site.register(FoodProperty, FoodPropertyAdmin) class NutritionInformationAdmin(admin.ModelAdmin): diff --git a/cookbook/helper/food_property_helper.py b/cookbook/helper/food_property_helper.py new file mode 100644 index 00000000..5cbe5f50 --- /dev/null +++ b/cookbook/helper/food_property_helper.py @@ -0,0 +1,29 @@ +from cookbook.models import FoodPropertyType + + +def calculate_recipe_properties(recipe): + ingredients = [] + computed_properties = {} + + for s in recipe.steps.all(): + ingredients += s.ingredients.all() + + for fpt in FoodPropertyType.objects.filter(space=recipe.space).all(): # TODO is this safe or should I require the request context? + computed_properties[fpt.id] = {'name': fpt.name, 'food_values': {}, 'total_value': 0} + + # TODO unit conversion support + + for i in ingredients: + for p in i.food.foodproperty_set.all(): + computed_properties[p.property_type.id]['total_value'] += (i.amount / p.food_amount) * p.property_amount + computed_properties[p.property_type.id]['food_values'][i.food.id] = add_or_create(computed_properties[p.property_type.id]['food_values'], i.food.id, (i.amount / p.food_amount) * p.property_amount) + + return computed_properties + +# small dict helper to add to existing key or create new, probably a better way of doing this +def add_or_create(d, key, value): + if key in d: + d[key] += value + else: + d[key] = value + return d diff --git a/cookbook/migrations/0189_unit_base_unit_unitconversion_foodpropertytype_and_more.py b/cookbook/migrations/0189_unit_base_unit_unitconversion_foodpropertytype_and_more.py new file mode 100644 index 00000000..b2b0467c --- /dev/null +++ b/cookbook/migrations/0189_unit_base_unit_unitconversion_foodpropertytype_and_more.py @@ -0,0 +1,73 @@ +# Generated by Django 4.1.7 on 2023-03-25 05:48 + +import cookbook.models +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django_prometheus.models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('cookbook', '0188_space_no_sharing_limit'), + ] + + operations = [ + migrations.AddField( + model_name='unit', + name='base_unit', + field=models.TextField(blank=True, default=None, max_length=256, null=True), + ), + migrations.CreateModel( + name='UnitConversion', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('base_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('converted_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('base_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_base_relation', to='cookbook.unit')), + ('converted_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_converted_relation', to='cookbook.unit')), + ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(django_prometheus.models.ExportModelOperationsMixin('unit_conversion'), models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='FoodPropertyType', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128)), + ('unit', models.CharField(blank=True, max_length=64, null=True)), + ('icon', models.CharField(blank=True, max_length=16, null=True)), + ('description', models.CharField(blank=True, max_length=512, null=True)), + ('category', models.CharField(choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'PRICE')], max_length=64)), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.CreateModel( + name='FoodProperty', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('food_amount', models.DecimalField(decimal_places=2, default=0, max_digits=32)), + ('nutrition_amount', models.DecimalField(decimal_places=4, default=0, max_digits=32)), + ('food', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')), + ('food_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.unit')), + ('nutrition_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.foodpropertytype')), + ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), + ], + bases=(models.Model, cookbook.models.PermissionModelMixin), + ), + migrations.AddConstraint( + model_name='foodpropertytype', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='nutrition_type_unique_name_per_space'), + ), + migrations.AddConstraint( + model_name='foodproperty', + constraint=models.UniqueConstraint(fields=('food', 'nutrition_type', 'space'), name='food_nutrition_unique_per_space'), + ), + ] diff --git a/cookbook/migrations/0189_unitconversion.py b/cookbook/migrations/0189_unitconversion.py deleted file mode 100644 index 257ab0f3..00000000 --- a/cookbook/migrations/0189_unitconversion.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 4.1.7 on 2023-02-24 19:47 - -import cookbook.models -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import django_prometheus.models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('cookbook', '0188_space_no_sharing_limit'), - ] - - operations = [ - migrations.CreateModel( - name='UnitConversion', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('base_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), - ('converted_amount', models.DecimalField(decimal_places=16, default=0, max_digits=32)), - ('created_at', models.DateTimeField(auto_now_add=True)), - ('updated_at', models.DateTimeField(auto_now=True)), - ('base_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='base_unit', to='cookbook.unit')), - ('converted_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='converted_unit', to='cookbook.unit')), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), - ('food', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')), - ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), - ], - bases=(django_prometheus.models.ExportModelOperationsMixin('unit_conversion'), models.Model, cookbook.models.PermissionModelMixin), - ), - ] diff --git a/cookbook/migrations/0190_nutritiontype_foodnutrition.py b/cookbook/migrations/0190_nutritiontype_foodnutrition.py deleted file mode 100644 index dd69466c..00000000 --- a/cookbook/migrations/0190_nutritiontype_foodnutrition.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 4.1.7 on 2023-02-24 20:15 - -import cookbook.models -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('cookbook', '0189_unitconversion'), - ] - - operations = [ - migrations.CreateModel( - name='NutritionType', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128)), - ('unit', models.CharField(blank=True, max_length=64, null=True)), - ('icon', models.CharField(blank=True, max_length=16, null=True)), - ('description', models.CharField(blank=True, max_length=512, null=True)), - ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), - ], - bases=(models.Model, cookbook.models.PermissionModelMixin), - ), - migrations.CreateModel( - name='FoodNutrition', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('food_amount', models.DecimalField(decimal_places=2, default=0, max_digits=32)), - ('nutrition_amount', models.DecimalField(decimal_places=4, default=0, max_digits=32)), - ('food', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.food')), - ('food_unit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.unit')), - ('nutrition_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='cookbook.nutritiontype')), - ('space', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='cookbook.space')), - ], - bases=(models.Model, cookbook.models.PermissionModelMixin), - ), - ] diff --git a/cookbook/migrations/0190_remove_foodproperty_food_nutrition_unique_per_space_and_more.py b/cookbook/migrations/0190_remove_foodproperty_food_nutrition_unique_per_space_and_more.py new file mode 100644 index 00000000..58d78468 --- /dev/null +++ b/cookbook/migrations/0190_remove_foodproperty_food_nutrition_unique_per_space_and_more.py @@ -0,0 +1,44 @@ +# Generated by Django 4.1.7 on 2023-03-25 06:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('cookbook', '0189_unit_base_unit_unitconversion_foodpropertytype_and_more'), + ] + + operations = [ + migrations.RemoveConstraint( + model_name='foodproperty', + name='food_nutrition_unique_per_space', + ), + migrations.RemoveConstraint( + model_name='foodpropertytype', + name='nutrition_type_unique_name_per_space', + ), + migrations.RenameField( + model_name='foodproperty', + old_name='nutrition_amount', + new_name='property_amount', + ), + migrations.RenameField( + model_name='foodproperty', + old_name='nutrition_type', + new_name='property_type', + ), + migrations.AlterField( + model_name='foodpropertytype', + name='category', + field=models.CharField(blank=True, choices=[('NUTRITION', 'Nutrition'), ('ALLERGEN', 'Allergen'), ('PRICE', 'PRICE')], max_length=64, null=True), + ), + migrations.AddConstraint( + model_name='foodproperty', + constraint=models.UniqueConstraint(fields=('food', 'property_type', 'space'), name='food_property_unique_per_space'), + ), + migrations.AddConstraint( + model_name='foodpropertytype', + constraint=models.UniqueConstraint(fields=('space', 'name'), name='food_property_type_unique_name_per_space'), + ), + ] diff --git a/cookbook/migrations/0191_foodnutrition_food_nutrition_unique_per_space_and_more.py b/cookbook/migrations/0191_foodnutrition_food_nutrition_unique_per_space_and_more.py deleted file mode 100644 index c1c9d9db..00000000 --- a/cookbook/migrations/0191_foodnutrition_food_nutrition_unique_per_space_and_more.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.7 on 2023-02-24 21:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('cookbook', '0190_nutritiontype_foodnutrition'), - ] - - operations = [ - migrations.AddConstraint( - model_name='foodnutrition', - constraint=models.UniqueConstraint(fields=('food', 'nutrition_type', 'space'), name='food_nutrition_unique_per_space'), - ), - migrations.AddConstraint( - model_name='nutritiontype', - constraint=models.UniqueConstraint(fields=('space', 'name'), name='nutrition_type_unique_name_per_space'), - ), - ] diff --git a/cookbook/migrations/0192_alter_unitconversion_base_unit_and_more.py b/cookbook/migrations/0192_alter_unitconversion_base_unit_and_more.py deleted file mode 100644 index 41da9e56..00000000 --- a/cookbook/migrations/0192_alter_unitconversion_base_unit_and_more.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 4.1.7 on 2023-02-26 06:30 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('cookbook', '0191_foodnutrition_food_nutrition_unique_per_space_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='unitconversion', - name='base_unit', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_base_unit', to='cookbook.unit'), - ), - migrations.AlterField( - model_name='unitconversion', - name='converted_unit', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_converted_unit', to='cookbook.unit'), - ), - ] diff --git a/cookbook/migrations/0193_alter_unitconversion_base_unit_and_more.py b/cookbook/migrations/0193_alter_unitconversion_base_unit_and_more.py deleted file mode 100644 index 8037f98f..00000000 --- a/cookbook/migrations/0193_alter_unitconversion_base_unit_and_more.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 4.1.7 on 2023-02-26 07:03 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('cookbook', '0192_alter_unitconversion_base_unit_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='unitconversion', - name='base_unit', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_base_relation', to='cookbook.unit'), - ), - migrations.AlterField( - model_name='unitconversion', - name='converted_unit', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='unit_conversion_converted_relation', to='cookbook.unit'), - ), - ] diff --git a/cookbook/migrations/0194_unit_base_unit.py b/cookbook/migrations/0194_unit_base_unit.py deleted file mode 100644 index f9e93df0..00000000 --- a/cookbook/migrations/0194_unit_base_unit.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.7 on 2023-03-15 14:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('cookbook', '0193_alter_unitconversion_base_unit_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='unit', - name='base_unit', - field=models.TextField(blank=True, default=None, max_length=256, null=True), - ), - ] diff --git a/cookbook/models.py b/cookbook/models.py index 82813cb8..198a0834 100644 --- a/cookbook/models.py +++ b/cookbook/models.py @@ -683,8 +683,6 @@ class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, Permiss order = models.IntegerField(default=0) original_text = models.CharField(max_length=512, null=True, blank=True, default=None) - original_text = models.CharField(max_length=512, null=True, blank=True, default=None) - space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') @@ -740,11 +738,19 @@ class Step(ExportModelOperationsMixin('step'), models.Model, PermissionModelMixi indexes = (GinIndex(fields=["search_vector"]),) -class NutritionType(models.Model, PermissionModelMixin): +class FoodPropertyType(models.Model, PermissionModelMixin): + NUTRITION = 'NUTRITION' + ALLERGEN = 'ALLERGEN' + PRICE = 'PRICE' + name = models.CharField(max_length=128) unit = models.CharField(max_length=64, blank=True, null=True) icon = models.CharField(max_length=16, blank=True, null=True) description = models.CharField(max_length=512, blank=True, null=True) + category = models.CharField(max_length=64, choices=((NUTRITION, _('Nutrition')), (ALLERGEN, _('Allergen')), (PRICE, _('PRICE'))), null=True, blank=True) + + # TODO show if empty property? + # TODO formatting property? space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') @@ -754,26 +760,26 @@ class NutritionType(models.Model, PermissionModelMixin): class Meta: constraints = [ - models.UniqueConstraint(fields=['space', 'name'], name='nutrition_type_unique_name_per_space') + models.UniqueConstraint(fields=['space', 'name'], name='food_property_type_unique_name_per_space') ] -class FoodNutrition(models.Model, PermissionModelMixin): +class FoodProperty(models.Model, PermissionModelMixin): food_amount = models.DecimalField(default=0, decimal_places=2, max_digits=32) food_unit = models.ForeignKey(Unit, on_delete=models.CASCADE) food = models.ForeignKey(Food, on_delete=models.CASCADE) - nutrition_amount = models.DecimalField(default=0, decimal_places=4, max_digits=32) - nutrition_type = models.ForeignKey(NutritionType, on_delete=models.PROTECT) + property_amount = models.DecimalField(default=0, decimal_places=4, max_digits=32) + property_type = models.ForeignKey(FoodPropertyType, on_delete=models.PROTECT) space = models.ForeignKey(Space, on_delete=models.CASCADE) objects = ScopedManager(space='space') def __str__(self): - return f'{self.food_amount} {self.food_unit} {self.food}: {self.nutrition_amount} {self.nutrition_type.unit} {self.nutrition_type.name}' + return f'{self.food_amount} {self.food_unit} {self.food}: {self.property_amount} {self.property_type.unit} {self.property_type.name}' class Meta: constraints = [ - models.UniqueConstraint(fields=['food', 'nutrition_type', 'space'], name='food_nutrition_unique_per_space') + models.UniqueConstraint(fields=['food', 'property_type', 'space'], name='food_property_unique_per_space') ] diff --git a/cookbook/serializer.py b/cookbook/serializer.py index e5de4868..f94f68c7 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -31,8 +31,8 @@ from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Cu RecipeBookEntry, RecipeImport, ShareLink, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, - SyncLog, Unit, UserFile, UserPreference, UserSpace, ViewLog, UnitConversion, FoodNutrition, - NutritionType) + SyncLog, Unit, UserFile, UserPreference, UserSpace, ViewLog, UnitConversion, FoodProperty, + FoodPropertyType) from cookbook.templatetags.custom_tags import markdown from recipes.settings import AWS_ENABLED, MEDIA_URL @@ -660,12 +660,12 @@ class IngredientSimpleSerializer(WritableNestedModelSerializer): if ingredient.food: for fn in ingredient.food.foodnutrition_set.all(): if fn.food_unit == ingredient.unit: - nutritions[fn.nutrition_type.id] = ingredient.amount / fn.food_amount * fn.nutrition_amount + nutritions[fn.property_type.id] = ingredient.amount / fn.food_amount * fn.property_amount else: conversions = self.get_conversions(ingredient) for c in conversions: if fn.food_unit.id == c['unit']['id']: - nutritions[fn.nutrition_type.id] = c['amount'] / fn.food_amount * fn.nutrition_amount + nutritions[fn.property_type.id] = c['amount'] / fn.food_amount * fn.property_amount return nutritions @@ -758,7 +758,7 @@ class NutritionTypeSerializer(serializers.ModelSerializer): return super().create(validated_data) class Meta: - model = NutritionType + model = FoodPropertyType fields = ('id', 'name', 'icon', 'unit', 'description') diff --git a/cookbook/tests/other/test_food_property.py b/cookbook/tests/other/test_food_property.py new file mode 100644 index 00000000..ebca1b32 --- /dev/null +++ b/cookbook/tests/other/test_food_property.py @@ -0,0 +1,42 @@ +from django.contrib import auth +from django_scopes import scopes_disabled + +from cookbook.helper.food_property_helper import calculate_recipe_properties +from cookbook.helper.unit_conversion_helper import get_conversions +from cookbook.models import Unit, Food, Ingredient, UnitConversion, FoodPropertyType, FoodProperty, Recipe, Step + + +def test_food_property(space_1, u1_s1): + with scopes_disabled(): + unit_gram = Unit.objects.create(name='gram', base_unit='g', space=space_1) + unit_pcs = Unit.objects.create(name='pcs', base_unit='', space=space_1) + unit_floz1 = Unit.objects.create(name='fl. oz 1', base_unit='imperial_fluid_ounce', space=space_1) # US and UK use different volume systems (US vs imperial) + unit_floz2 = Unit.objects.create(name='fl. oz 2', base_unit='fluid_ounce', space=space_1) + unit_fantasy = Unit.objects.create(name='Fantasy Unit', base_unit='', space=space_1) + + food_1 = Food.objects.create(name='food_1', space=space_1) + food_2 = Food.objects.create(name='food_2', space=space_1) + + property_fat = FoodPropertyType.objects.create(name='property_fat', space=space_1) + property_calories = FoodPropertyType.objects.create(name='property_calories', space=space_1) + property_nuts = FoodPropertyType.objects.create(name='property_nuts', space=space_1) + property_price = FoodPropertyType.objects.create(name='property_price', space=space_1) + + food_1_property_fat = FoodProperty.objects.create(food_amount=100, food_unit=unit_gram, food=food_1, property_amount=50, property_type=property_fat, space=space_1) + food_1_property_nuts = FoodProperty.objects.create(food_amount=100, food_unit=unit_gram, food=food_1, property_amount=1, property_type=property_nuts, space=space_1) + food_1_property_price = FoodProperty.objects.create(food_amount=100, food_unit=unit_gram, food=food_1, property_amount=7.50, property_type=property_price, space=space_1) + + food_2_property_fat = FoodProperty.objects.create(food_amount=100, food_unit=unit_gram, food=food_2, property_amount=25, property_type=property_fat, space=space_1) + food_2_property_nuts = FoodProperty.objects.create(food_amount=100, food_unit=unit_gram, food=food_2, property_amount=0, property_type=property_nuts, space=space_1) + food_2_property_price = FoodProperty.objects.create(food_amount=100, food_unit=unit_gram, food=food_2, property_amount=2.50, property_type=property_price, space=space_1) + + recipe_1 = Recipe.objects.create(name='recipe_1', waiting_time=0, working_time=0, space=space_1, created_by=auth.get_user(u1_s1)) + step_1 = Step.objects.create(instruction='instruction_step_1', space=space_1) + step_1.ingredients.create(amount=500, unit=unit_gram, food=food_1, space=space_1) + step_1.ingredients.create(amount=1000, unit=unit_gram, food=food_2, space=space_1) + recipe_1.steps.add(step_1) + recipe_1.save() + + property_values = calculate_recipe_properties(recipe_1) + for p in property_values: + print(p) diff --git a/cookbook/urls.py b/cookbook/urls.py index a2423d50..fa5f2fb0 100644 --- a/cookbook/urls.py +++ b/cookbook/urls.py @@ -12,7 +12,7 @@ from recipes.version import VERSION_NUMBER from .models import (Automation, Comment, CustomFilter, Food, InviteLink, Keyword, MealPlan, Recipe, RecipeBook, RecipeBookEntry, RecipeImport, ShoppingList, Step, Storage, Supermarket, SupermarketCategory, Sync, SyncLog, Unit, UserFile, - get_model_name, UserSpace, Space, NutritionType, UnitConversion) + get_model_name, UserSpace, Space, FoodPropertyType, UnitConversion) from .views import api, data, delete, edit, import_export, lists, new, telegram, views from .views.api import CustomAuthToken @@ -191,7 +191,7 @@ for m in generic_models: ) ) -vue_models = [Food, Keyword, Unit, Supermarket, SupermarketCategory, Automation, UserFile, Step, CustomFilter, UnitConversion, NutritionType] +vue_models = [Food, Keyword, Unit, Supermarket, SupermarketCategory, Automation, UserFile, Step, CustomFilter, UnitConversion, FoodPropertyType] for m in vue_models: py_name = get_model_name(m) url_name = py_name.replace('_', '-') diff --git a/cookbook/views/api.py b/cookbook/views/api.py index eff35895..3e47531c 100644 --- a/cookbook/views/api.py +++ b/cookbook/views/api.py @@ -68,7 +68,7 @@ from cookbook.models import (Automation, BookmarkletImport, CookLog, CustomFilte MealType, Recipe, RecipeBook, RecipeBookEntry, ShareLink, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, - SyncLog, Unit, UserFile, UserPreference, UserSpace, ViewLog, UnitConversion, NutritionType) + SyncLog, Unit, UserFile, UserPreference, UserSpace, ViewLog, UnitConversion, FoodPropertyType) from cookbook.provider.dropbox import Dropbox from cookbook.provider.local import Local from cookbook.provider.nextcloud import Nextcloud @@ -820,10 +820,10 @@ class RecipeViewSet(viewsets.ModelViewSet): 'steps__ingredients__food__onhand_users', 'steps__ingredients__food__substitute', 'steps__ingredients__food__child_inherit_fields', - 'steps__ingredients__food__foodnutrition_set', - 'steps__ingredients__food__foodnutrition_set__food', - 'steps__ingredients__food__foodnutrition_set__food_unit', - 'steps__ingredients__food__foodnutrition_set__nutrition_type', + # 'steps__ingredients__food__foodnutrition_set', + # 'steps__ingredients__food__foodnutrition_set__food', + # 'steps__ingredients__food__foodnutrition_set__food_unit', + # 'steps__ingredients__food__foodnutrition_set__nutrition_type', 'steps__ingredients__unit', 'steps__ingredients__unit__unit_conversion_base_relation', 'steps__ingredients__unit__unit_conversion_base_relation__base_unit', @@ -970,7 +970,7 @@ class UnitConversionViewSet(viewsets.ModelViewSet): class NutritionTypeViewSet(viewsets.ModelViewSet): - queryset = NutritionType.objects + queryset = FoodPropertyType.objects serializer_class = NutritionTypeSerializer permission_classes = [CustomIsUser & CustomTokenHasReadWriteScope] diff --git a/cookbook/views/lists.py b/cookbook/views/lists.py index 10732c9a..10d07cac 100644 --- a/cookbook/views/lists.py +++ b/cookbook/views/lists.py @@ -246,15 +246,15 @@ def unit_conversion(request): @group_required('user') -def nutrition_type(request): +def food_property_type(request): # model-name is the models.js name of the model, probably ALL-CAPS return render( request, 'generic/model_template.html', { - "title": _("Unit Conversions"), + "title": _("Food Property Types"), "config": { - 'model': "NUTRITION_TYPE", # *REQUIRED* name of the model in models.js + 'model': "FOOD_PROPERTY_TYPE", # *REQUIRED* name of the model in models.js } } ) diff --git a/vue/src/utils/models.js b/vue/src/utils/models.js index 4f1fe363..18503558 100644 --- a/vue/src/utils/models.js +++ b/vue/src/utils/models.js @@ -622,9 +622,9 @@ export class Models { }, } - static NUTRITION_TYPE = { - name: "Nutrition Type", - apiName: "NutritionType", + static FOOD_PROPERTY_TYPE = { + name: "Food Property Type", + apiName: "FoodPropertyType", paginated: false, list: { header_component: {