diff --git a/cookbook/helper/unit_conversion_helper.py b/cookbook/helper/unit_conversion_helper.py new file mode 100644 index 000000000..443f20846 --- /dev/null +++ b/cookbook/helper/unit_conversion_helper.py @@ -0,0 +1,48 @@ +def base_conversions(): + METRIC_MASS_CONVERSIONS = { + 'g': {'base_amount': 1000, 'base_unit': 'mg', 'converted_amount': 1, 'converted_unit': 'g'}, + 'mg': {'base_amount': 1000, 'base_unit': 'g', 'converted_amount': 1, 'converted_unit': 'kg'}, + } + + + + METRIC_LIQUID_CONVERSIONS = [ + {'base_amount': 1000, 'base_unit': 'ml', 'converted_amount': 1, 'converted_unit': 'l'}, + ] + + +def get_conversions(amount, unit, food): + conversions = [] + if unit: + for c in unit.unit_conversion_base_relation.all(): + r = _uc_convert(c, amount, unit, food) + if r not in conversions: + conversions.append(r) + for c in unit.unit_conversion_converted_relation.all(): + r = _uc_convert(c, amount, unit, food) + if r not in conversions: + conversions.append(r) + + return conversions + + +def _uc_convert(uc, amount, unit, food): + if uc.food is None or uc.food == food: + if unit == uc.base_unit: + return { + 'amount': amount * (uc.converted_amount / uc.base_amount), + 'unit': { + 'id': uc.converted_unit.id, + 'name': uc.converted_unit.name, + 'plural_name': uc.converted_unit.plural_name + }, + } + else: + return { + 'amount': amount * (uc.base_amount / uc.converted_amount), + 'unit': { + 'id': uc.base_unit.id, + 'name': uc.base_unit.name, + 'plural_name': uc.base_unit.plural_name + }, + } diff --git a/cookbook/serializer.py b/cookbook/serializer.py index 19dc89ba0..e5de4868a 100644 --- a/cookbook/serializer.py +++ b/cookbook/serializer.py @@ -24,6 +24,7 @@ from cookbook.helper.CustomStorageClass import CachedS3Boto3Storage from cookbook.helper.HelperFunctions import str2bool from cookbook.helper.permission_helper import above_space_limit from cookbook.helper.shopping_helper import RecipeShoppingEditor +from cookbook.helper.unit_conversion_helper import get_conversions from cookbook.models import (Automation, BookmarkletImport, Comment, CookLog, CustomFilter, ExportLog, Food, FoodInheritField, ImportLog, Ingredient, InviteLink, Keyword, MealPlan, MealType, NutritionInformation, Recipe, RecipeBook, @@ -105,13 +106,16 @@ class CustomOnHandField(serializers.Field): def to_representation(self, obj): shared_users = [] - if c := caches['default'].get(f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', None): + if c := caches['default'].get( + f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', None): shared_users = c else: try: shared_users = [x.id for x in list(self.context['request'].user.get_shopping_share())] + [ self.context['request'].user.id] - caches['default'].set(f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', shared_users, timeout=5*60) + caches['default'].set( + f'shopping_shared_users_{self.context["request"].space.id}_{self.context["request"].user.id}', + shared_users, timeout=5 * 60) # TODO ugly hack that improves API performance significantly, should be done properly except AttributeError: # Anonymous users (using share links) don't have shared users pass @@ -645,19 +649,8 @@ class IngredientSimpleSerializer(WritableNestedModelSerializer): def get_conversions(self, obj): conversions = [] # TODO add hardcoded base conversions for metric/imperial - if obj.unit: # TODO move to function and also iterate obj.unit.unit_conversion_converted_relation.all() - for c in obj.unit.unit_conversion_base_relation.all(): - if c.food is None or c.food == obj.food: - 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, - }) + if obj.unit and obj.food: + conversions += get_conversions(obj.amount, obj.unit, obj.food) return conversions