Coverage for cookbook/helper/property_helper.py: 100%
45 statements
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 01:02 +0100
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 01:02 +0100
1from django.core.cache import caches
3from cookbook.helper.cache_helper import CacheHelper
4from cookbook.helper.unit_conversion_helper import UnitConversionHelper
5from cookbook.models import PropertyType
8class FoodPropertyHelper:
9 space = None
11 def __init__(self, space):
12 """
13 Helper to perform food property calculations
14 :param space: space to limit scope to
15 """
16 self.space = space
18 def calculate_recipe_properties(self, recipe):
19 """
20 Calculate all food properties for a given recipe.
21 :param recipe: recipe to calculate properties for
22 :return: dict of with property keys and total/food values for each property available
23 """
24 ingredients = []
25 computed_properties = {}
27 for s in recipe.steps.all():
28 ingredients += s.ingredients.all()
30 property_types = caches['default'].get(CacheHelper(self.space).PROPERTY_TYPE_CACHE_KEY, None)
32 if not property_types:
33 property_types = PropertyType.objects.filter(space=self.space).all()
34 # cache is cleared on property type save signal so long duration is fine
35 caches['default'].set(CacheHelper(self.space).PROPERTY_TYPE_CACHE_KEY, property_types, 60 * 60)
37 for fpt in property_types:
38 computed_properties[fpt.id] = {'id': fpt.id, 'name': fpt.name, 'description': fpt.description,
39 'unit': fpt.unit, 'order': fpt.order, 'food_values': {}, 'total_value': 0, 'missing_value': False}
41 uch = UnitConversionHelper(self.space)
43 for i in ingredients:
44 if i.food is not None:
45 conversions = uch.get_conversions(i)
46 for pt in property_types:
47 found_property = False
48 if i.food.properties_food_amount == 0 or i.food.properties_food_unit is None:
49 computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': 0}
50 computed_properties[pt.id]['missing_value'] = i.food.properties_food_unit is None
51 else:
52 for p in i.food.properties.all():
53 if p.property_type == pt:
54 for c in conversions:
55 if c.unit == i.food.properties_food_unit:
56 found_property = True
57 computed_properties[pt.id]['total_value'] += (c.amount / i.food.properties_food_amount) * p.property_amount
58 computed_properties[pt.id]['food_values'] = self.add_or_create(
59 computed_properties[p.property_type.id]['food_values'], c.food.id, (c.amount / i.food.properties_food_amount) * p.property_amount, c.food)
60 if not found_property:
61 computed_properties[pt.id]['missing_value'] = True
62 computed_properties[pt.id]['food_values'][i.food.id] = {'id': i.food.id, 'food': i.food.name, 'value': 0}
64 return computed_properties
66 # small dict helper to add to existing key or create new, probably a better way of doing this
67 # TODO move to central helper ?
68 @staticmethod
69 def add_or_create(d, key, value, food):
70 if key in d:
71 d[key]['value'] += value
72 else:
73 d[key] = {'id': food.id, 'food': food.name, 'value': value}
74 return d