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

1from django.core.cache import caches 

2 

3from cookbook.helper.cache_helper import CacheHelper 

4from cookbook.helper.unit_conversion_helper import UnitConversionHelper 

5from cookbook.models import PropertyType 

6 

7 

8class FoodPropertyHelper: 

9 space = None 

10 

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 

17 

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 = {} 

26 

27 for s in recipe.steps.all(): 

28 ingredients += s.ingredients.all() 

29 

30 property_types = caches['default'].get(CacheHelper(self.space).PROPERTY_TYPE_CACHE_KEY, None) 

31 

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) 

36 

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} 

40 

41 uch = UnitConversionHelper(self.space) 

42 

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} 

63 

64 return computed_properties 

65 

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