first conversions working

This commit is contained in:
vabene1111 2023-01-09 17:42:53 +01:00
parent 666e4d282f
commit 3ced8c7a1e
5 changed files with 12236 additions and 16678 deletions

View File

@ -15,7 +15,7 @@ from .models import (BookmarkletImport, Comment, CookLog, Food, FoodInheritField
Recipe, RecipeBook, RecipeBookEntry, RecipeImport, SearchPreference, ShareLink, Recipe, RecipeBook, RecipeBookEntry, RecipeImport, SearchPreference, ShareLink,
ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, ShoppingList, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage,
Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog, Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, SyncLog,
TelegramBot, Unit, UserFile, UserPreference, ViewLog, Automation, UserSpace) TelegramBot, Unit, UserFile, UserPreference, ViewLog, Automation, UserSpace, UnitConversion)
class CustomUserAdmin(UserAdmin): class CustomUserAdmin(UserAdmin):
@ -201,6 +201,14 @@ class FoodAdmin(TreeAdmin):
admin.site.register(Food, FoodAdmin) admin.site.register(Food, FoodAdmin)
class UnitConversionAdmin(admin.ModelAdmin):
list_display = ('base_amount', 'base_unit', 'food', 'converted_amount', 'converted_unit')
search_fields = ('food__name', 'unit__name')
admin.site.register(UnitConversion, UnitConversionAdmin)
class IngredientAdmin(admin.ModelAdmin): class IngredientAdmin(admin.ModelAdmin):
list_display = ('food', 'amount', 'unit') list_display = ('food', 'amount', 'unit')
search_fields = ('food__name', 'unit__name') search_fields = ('food__name', 'unit__name')

View File

@ -0,0 +1,34 @@
# Generated by Django 4.1.4 on 2023-01-09 16:41
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', '0186_automation_order_alter_automation_type'),
]
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),
),
]

View File

@ -649,6 +649,25 @@ class Food(ExportModelOperationsMixin('food'), TreeModel, PermissionModelMixin):
) )
class UnitConversion(ExportModelOperationsMixin('unit_conversion'), models.Model, PermissionModelMixin):
base_amount = models.DecimalField(default=0, decimal_places=16, max_digits=32)
base_unit = models.ForeignKey('Unit', on_delete=models.CASCADE, related_name='base_unit')
converted_amount = models.DecimalField(default=0, decimal_places=16, max_digits=32)
converted_unit = models.ForeignKey('Unit', on_delete=models.CASCADE, related_name='converted_unit')
food = models.ForeignKey('Food', on_delete=models.CASCADE, null=True, blank=True)
created_by = models.ForeignKey(User, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
space = models.ForeignKey(Space, on_delete=models.CASCADE)
objects = ScopedManager(space='space')
def __str__(self):
return f'{self.base_amount} {self.base_unit} -> {self.converted_amount} {self.converted_unit} {self.food}'
class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, PermissionModelMixin): class Ingredient(ExportModelOperationsMixin('ingredient'), models.Model, PermissionModelMixin):
# delete method on Food and Unit checks if they are part of a Recipe, if it is raises a ProtectedError instead of cascading the delete # delete method on Food and Unit checks if they are part of a Recipe, if it is raises a ProtectedError instead of cascading the delete
food = models.ForeignKey(Food, on_delete=models.CASCADE, null=True, blank=True) food = models.ForeignKey(Food, on_delete=models.CASCADE, null=True, blank=True)

View File

@ -29,7 +29,7 @@ from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, Cu
RecipeBookEntry, RecipeImport, ShareLink, ShoppingList, RecipeBookEntry, RecipeImport, ShareLink, ShoppingList,
ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage, ShoppingListEntry, ShoppingListRecipe, Space, Step, Storage,
Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync, Supermarket, SupermarketCategory, SupermarketCategoryRelation, Sync,
SyncLog, Unit, UserFile, UserPreference, UserSpace, ViewLog) SyncLog, Unit, UserFile, UserPreference, UserSpace, ViewLog, UnitConversion)
from cookbook.templatetags.custom_tags import markdown from cookbook.templatetags.custom_tags import markdown
from recipes.settings import AWS_ENABLED, MEDIA_URL from recipes.settings import AWS_ENABLED, MEDIA_URL
@ -610,10 +610,28 @@ class IngredientSimpleSerializer(WritableNestedModelSerializer):
unit = UnitSerializer(allow_null=True) unit = UnitSerializer(allow_null=True)
used_in_recipes = serializers.SerializerMethodField('get_used_in_recipes') used_in_recipes = serializers.SerializerMethodField('get_used_in_recipes')
amount = CustomDecimalField() amount = CustomDecimalField()
conversions = serializers.SerializerMethodField('get_conversions')
def get_used_in_recipes(self, obj): def get_used_in_recipes(self, obj):
return list(Recipe.objects.filter(steps__ingredients=obj.id).values('id', 'name')) return list(Recipe.objects.filter(steps__ingredients=obj.id).values('id', 'name'))
def get_conversions(self, obj):
conversions = []
for c in UnitConversion.objects.filter(space=self.context['request'].space).filter(Q(food__isnull=True) | Q(food=obj.food)).filter(Q(base_unit=obj.unit) | Q(converted_unit=obj.unit)):
if obj.unit == c.base_unit:
conversions.append({
'amount': obj.amount * (c.converted_amount/c.base_amount),
'unit': UnitSerializer(c.converted_unit, context={'request': self.context['request']}).data,
})
else:
conversions.append({
'amount': obj.amount * (c.base_amount / c.converted_amount),
'unit': UnitSerializer(c.base_unit, context={'request': self.context['request']}).data,
})
return conversions
def create(self, validated_data): def create(self, validated_data):
validated_data['space'] = self.context['request'].space validated_data['space'] = self.context['request'].space
return super().create(validated_data) return super().create(validated_data)
@ -625,7 +643,7 @@ class IngredientSimpleSerializer(WritableNestedModelSerializer):
class Meta: class Meta:
model = Ingredient model = Ingredient
fields = ( fields = (
'id', 'food', 'unit', 'amount', 'note', 'order', 'id', 'food', 'unit', 'amount', 'conversions', 'note', 'order',
'is_header', 'no_amount', 'original_text', 'used_in_recipes', 'is_header', 'no_amount', 'original_text', 'used_in_recipes',
'always_use_plural_unit', 'always_use_plural_food', 'always_use_plural_unit', 'always_use_plural_food',
) )

File diff suppressed because it is too large Load Diff