Repository: wger-project/wger

Issue:
Nutrition plan: pick correct body weight entry
In the `get_nutritional_values` method of `NutritionPlan` the per-kg-calculation uses the user's last weight entry. While this is correct when adding meals to the plan, it can be wrong when opening the plan later (the user's weight changed). This should be changed so that the weight entry _closest to the plan's date_ should be used.

Nutrition plan: pick correct body weight entry
In the `get_nutritional_values` method of `NutritionPlan` the per-kg-calculation uses the user's last weight entry. While this is correct when adding meals to the plan, it can be wrong when opening the plan later (the user's weight changed). This should be changed so that the weight entry _closest to the plan's date_ should be used.



Discussion:
I can take a look at this

~Avinash

:+1: 

Hey @avinsrid, how is it going?

I can take a look at this

~Avinash

:+1: 

Hey @avinsrid, how is it going?


Resolving patch:
diff --git a/wger/nutrition/models.py b/wger/nutrition/models.py
--- a/wger/nutrition/models.py
+++ b/wger/nutrition/models.py
@@ -37,6 +37,7 @@
 from wger.utils.fields import Html5TimeField
 from wger.utils.models import AbstractLicenseModel
 from wger.utils.units import AbstractWeight
+from wger.weight.models import WeightEntry
 
 MEALITEM_WEIGHT_GRAM = '1'
 MEALITEM_WEIGHT_UNIT = '2'
@@ -121,7 +122,7 @@ def get_nutritional_values(self):
                               'fat': 0},
                   'per_kg': {'protein': 0,
                              'carbohydrates': 0,
-                             'fat': 0}
+                             'fat': 0},
                   }
 
         # Energy
@@ -139,10 +140,10 @@ def get_nutritional_values(self):
                     result['total'][key] * ENERGY_FACTOR[key][unit] / energy * 100
 
         # Per body weight
-        if self.user.userprofile.weight:
-            weight = Decimal(self.user.userprofile.weight)
+        weight_entry = self.get_closest_weight_entry()
+        if weight_entry:
             for key in result['per_kg'].keys():
-                result['per_kg'][key] = result['total'][key] / weight
+                result['per_kg'][key] = result['total'][key] / weight_entry.weight
 
         # Only 2 decimal places, anything else doesn't make sense
         for key in result.keys():
@@ -151,6 +152,23 @@ def get_nutritional_values(self):
 
         return result
 
+    def get_closest_weight_entry(self):
+        '''
+        Returns the closest weight entry for the nutrition plan.
+        Returns None if there are no entries.
+        '''
+        target = self.creation_date
+        closest_entry_gte = WeightEntry.objects.filter(user=self.user) \
+            .filter(date__gte=target).order_by('date').first()
+        closest_entry_lte = WeightEntry.objects.filter(user=self.user) \
+            .filter(date__lte=target).order_by('-date').first()
+        if closest_entry_gte is None or closest_entry_lte is None:
+            return closest_entry_gte or closest_entry_lte
+        if abs(closest_entry_gte.date - target) < abs(closest_entry_lte.date - target):
+            return closest_entry_gte
+        else:
+            return closest_entry_lte
+
     def get_owner_object(self):
         '''
         Returns the object that has owner information
diff --git a/wger/nutrition/views/plan.py b/wger/nutrition/views/plan.py
--- a/wger/nutrition/views/plan.py
+++ b/wger/nutrition/views/plan.py
@@ -144,7 +144,11 @@ def view(request, id):
 
     # Get the nutritional info
     template_data['plan'] = plan
-    template_data['nutritional_data'] = plan.get_nutritional_values()
+    template_data['nutritional_data'] = \
+        plan.get_nutritional_values()
+
+    # Get the weight entry used
+    template_data['weight_entry'] = plan.get_closest_weight_entry()
 
     # Tokens for the links
     template_data['uid'] = uid


Test patch: