Skip to content

Commit fb99709

Browse files
committed
Change WealthGroup.average_household_size to float and update related pipeline wtih safe numeric conversions see HEA-811
1 parent a98fa33 commit fb99709

6 files changed

Lines changed: 58 additions & 16 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Generated by Django 5.2.7 on 2025-12-29 07:04
2+
3+
import common.models
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
("baseline", "0021_remove_livelihoodproductcategory_livelihood_zone_baseline_and_more"),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name="wealthgroup",
16+
name="average_household_size",
17+
field=models.FloatField(
18+
blank=True,
19+
help_text="Average number of people per household in this Wealth Group",
20+
null=True,
21+
validators=[common.models.validate_positive],
22+
verbose_name="Average household size",
23+
),
24+
),
25+
]

apps/baseline/models.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,12 @@ class WealthGroup(common_models.Model):
517517
verbose_name=_("Percentage of households"),
518518
help_text=_("Percentage of households in the Community or Livelihood Zone that are in this Wealth Group"),
519519
)
520-
average_household_size = models.PositiveSmallIntegerField(
521-
blank=True, null=True, verbose_name=_("Average household size")
520+
average_household_size = models.FloatField(
521+
blank=True,
522+
null=True,
523+
validators=[common_models.validate_positive],
524+
verbose_name=_("Average household size"),
525+
help_text=_("Average number of people per household in this Wealth Group"),
522526
)
523527

524528
objects = WealthGroupManager()

apps/baseline/serializers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ def get_livelihood_zone_baseline_label(self, obj):
581581
wealth_group_percentage_of_households = serializers.IntegerField(
582582
source="wealth_group.percentage_of_households", read_only=True
583583
)
584-
wealth_group_average_household_size = serializers.IntegerField(
584+
wealth_group_average_household_size = serializers.FloatField(
585585
source="wealth_group.average_household_size", read_only=True
586586
)
587587
wealth_group_category = serializers.CharField(source="wealth_group.wealth_group_category.pk", read_only=True)
@@ -1336,7 +1336,7 @@ def get_livelihood_zone_baseline_label(self, obj):
13361336
wealth_group_percentage_of_households = serializers.IntegerField(
13371337
source="wealth_group.percentage_of_households", read_only=True
13381338
)
1339-
wealth_group_average_household_size = serializers.IntegerField(
1339+
wealth_group_average_household_size = serializers.FloatField(
13401340
source="wealth_group.average_household_size", read_only=True
13411341
)
13421342
wealth_group_category = serializers.CharField(source="wealth_group.wealth_group_category.pk", read_only=True)
@@ -1452,7 +1452,7 @@ def get_livelihood_zone_baseline_label(self, obj):
14521452
wealth_group_percentage_of_households = serializers.IntegerField(
14531453
source="wealth_group.percentage_of_households", read_only=True
14541454
)
1455-
wealth_group_average_household_size = serializers.IntegerField(
1455+
wealth_group_average_household_size = serializers.FloatField(
14561456
source="wealth_group.average_household_size", read_only=True
14571457
)
14581458
wealth_group_category = serializers.CharField(source="wealth_group.wealth_group_category.pk", read_only=True)

apps/baseline/tests/factories.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ class Meta:
155155
)
156156
wealth_group_category = factory.SubFactory(WealthGroupCategoryFactory)
157157
percentage_of_households = fuzzy.FuzzyInteger(10, 91)
158-
average_household_size = fuzzy.FuzzyInteger(2, 31)
158+
average_household_size = fuzzy.FuzzyDecimal(2.0, 31.0, precision=2)
159159

160160

161161
class BaselineWealthGroupFactory(WealthGroupFactory):

pipelines/assets/livelihood_activity.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -846,18 +846,27 @@ def get_instances_from_dataframe(
846846
# worksheets
847847
column = df.columns[i + 1]
848848
household_size = df.iloc[3, i + 1]
849-
# Convert household_size to int
849+
850+
# Convert to numeric to handle string values (e.g., "6" instead of 6)
850851
try:
851-
if pd.notna(household_size) and household_size != "":
852-
# Convert to float first to handle "5.0" or "5.7", then to int
853-
household_size = int(float(household_size))
854-
else:
855-
household_size = None
852+
percentage_kcals = (
853+
float(livelihood_activity["percentage_kcals"])
854+
if livelihood_activity.get("percentage_kcals")
855+
else None
856+
)
856857
except (ValueError, TypeError):
857-
household_size = None
858+
percentage_kcals = None
859+
860+
try:
861+
household_size_numeric = (
862+
float(household_size) if household_size not in ("", None) else None
863+
)
864+
except (ValueError, TypeError):
865+
household_size_numeric = None
866+
858867
livelihood_activity["kcals_consumed"] = (
859-
livelihood_activity["percentage_kcals"] * 2100 * 365 * household_size
860-
if livelihood_activity["percentage_kcals"] and household_size
868+
percentage_kcals * 2100 * 365 * household_size_numeric
869+
if percentage_kcals and household_size_numeric
861870
else None
862871
)
863872

pipelines/assets/wealth_characteristic.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,10 +490,14 @@ def wealth_characteristic_instances(
490490
# Calculate the kcals_consumed
491491
# Derive it by multiplying percentage_kcals by:
492492
# 2100 (kcals per person per day) * 365 (days per year) * average_household_size
493+
# Convert columns to numeric to handle string values from the dataframe
494+
wealth_group_df["percentage_kcals"] = pd.to_numeric(wealth_group_df["percentage_kcals"], errors="coerce")
495+
wealth_group_df["average_household_size"] = pd.to_numeric(
496+
wealth_group_df["average_household_size"], errors="coerce"
497+
)
493498
wealth_group_df["kcals_consumed"] = (
494499
wealth_group_df["percentage_kcals"] * 2100 * 365 * wealth_group_df["average_household_size"]
495500
)
496-
497501
result = {
498502
"WealthGroup": wealth_group_df.to_dict(orient="records"),
499503
"WealthGroupCharacteristicValue": wealth_group_characteristic_values,

0 commit comments

Comments
 (0)