Skip to content

Commit 336a6a6

Browse files
authored
Merge pull request #218 from American-Institutes-for-Research/HEA-772/end_point_for_baseline_wealthcharactersics
Hea 772/end point for baseline wealthcharactersics
2 parents f28dc1b + 0dc7138 commit 336a6a6

11 files changed

Lines changed: 682 additions & 19 deletions
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Generated by Django 5.2.9 on 2026-01-13 17:58
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("baseline", "0022_alter_wealthgroup_options"),
10+
]
11+
12+
operations = [
13+
migrations.CreateModel(
14+
name="BaselineWealthGroupCharacteristicValue",
15+
fields=[],
16+
options={
17+
"verbose_name": "Baseline Wealth Group Characteristic Value",
18+
"verbose_name_plural": "Baseline Wealth Group Characteristic Values",
19+
"proxy": True,
20+
"indexes": [],
21+
"constraints": [],
22+
},
23+
bases=("baseline.wealthgroupcharacteristicvalue",),
24+
),
25+
migrations.CreateModel(
26+
name="CommunityWealthGroupCharacteristicValue",
27+
fields=[],
28+
options={
29+
"verbose_name": "Community Wealth Group Characteristic Value",
30+
"verbose_name_plural": "Community Wealth Group Characteristic Values",
31+
"proxy": True,
32+
"indexes": [],
33+
"constraints": [],
34+
},
35+
bases=("baseline.wealthgroupcharacteristicvalue",),
36+
),
37+
]

apps/baseline/models.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,56 @@ class Meta:
843843
]
844844

845845

846+
class BaselineWealthGroupCharacteristicValueManager(InheritanceManager):
847+
def get_queryset(self):
848+
return super().get_queryset().filter(wealth_group__community__isnull=True).select_subclasses()
849+
850+
851+
class BaselineWealthGroupCharacteristicValue(WealthGroupCharacteristicValue):
852+
"""
853+
An attribute of a Baseline Wealth Group such as the number of school-age children.
854+
"""
855+
856+
objects = BaselineWealthGroupCharacteristicValueManager()
857+
858+
def clean(self):
859+
if self.wealth_group.community:
860+
raise ValidationError(
861+
_("A Baseline Wealth Group Characteristic Value cannot be for a Community Wealth Group")
862+
)
863+
super().clean()
864+
865+
class Meta:
866+
verbose_name = _("Baseline Wealth Group Characteristic Value")
867+
verbose_name_plural = _("Baseline Wealth Group Characteristic Values")
868+
proxy = True
869+
870+
871+
class CommunityWealthGroupCharacteristicValueManager(InheritanceManager):
872+
def get_queryset(self):
873+
return super().get_queryset().exclude(wealth_group__community__isnull=True).select_subclasses()
874+
875+
876+
class CommunityWealthGroupCharacteristicValue(WealthGroupCharacteristicValue):
877+
"""
878+
An attribute of a Community Wealth Group such as the number of school-age children.
879+
"""
880+
881+
objects = CommunityWealthGroupCharacteristicValueManager()
882+
883+
def clean(self):
884+
if not self.wealth_group.community:
885+
raise ValidationError(
886+
_("A Community Wealth Group Characteristic Value must be for a Community Wealth Group")
887+
)
888+
super().clean()
889+
890+
class Meta:
891+
verbose_name = _("Community Wealth Group Characteristic Value")
892+
verbose_name_plural = _("Community Wealth Group Characteristic Values")
893+
proxy = True
894+
895+
846896
class LivelihoodStrategyManager(common_models.IdentifierManager):
847897
def get_by_natural_key(
848898
self,

apps/baseline/serializers.py

Lines changed: 135 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
from .models import (
99
BaselineLivelihoodActivity,
1010
BaselineWealthGroup,
11+
BaselineWealthGroupCharacteristicValue,
1112
ButterProduction,
1213
Community,
1314
CommunityCropProduction,
1415
CommunityLivestock,
1516
CommunityWealthGroup,
17+
CommunityWealthGroupCharacteristicValue,
1618
CopingStrategy,
1719
CropProduction,
1820
Event,
@@ -359,6 +361,12 @@ class Meta:
359361
"wealth_characteristic",
360362
"wealth_characteristic_name",
361363
"wealth_characteristic_description",
364+
"variable_type",
365+
"characteristic_group",
366+
"product",
367+
"product_common_name",
368+
"unit_of_measure",
369+
"unit_of_measure_description",
362370
"value",
363371
"min_value",
364372
"max_value",
@@ -389,6 +397,7 @@ def get_wealth_group_label(self, obj):
389397
wealth_characteristic_description = serializers.CharField(
390398
source="wealth_characteristic.description", read_only=True
391399
)
400+
variable_type = serializers.CharField(source="wealth_characteristic.variable_type", read_only=True)
392401
livelihood_zone_baseline = serializers.IntegerField(
393402
source="wealth_group.community.livelihood_zone_baseline.pk", read_only=True
394403
)
@@ -413,6 +422,132 @@ def get_wealth_group_label(self, obj):
413422
source_organization_name = serializers.CharField(
414423
source="wealth_group.community.livelihood_zone_baseline.source_organization.name", read_only=True
415424
)
425+
characteristic_group = serializers.SerializerMethodField()
426+
427+
def get_characteristic_group(self, obj):
428+
"""
429+
Override the default characteristic_group for Livestock and Poultry.
430+
431+
This allows us to use the same wealth characteristic, e.g. 'Number owned' for both Livestock and Poultry,
432+
as well as other wealth characteristics.
433+
"""
434+
if obj.product and obj.product.cpc.startswith("L0215"):
435+
return "Poultry"
436+
if obj.product and obj.product.cpc.startswith("L02"):
437+
return "Livestock"
438+
return obj.wealth_characteristic.characteristic_group
439+
440+
product_common_name = serializers.CharField(source="product.common_name", read_only=True, allow_null=True)
441+
unit_of_measure_description = serializers.CharField(
442+
source="unit_of_measure.description", read_only=True, allow_null=True
443+
)
444+
445+
446+
class BaselineWealthGroupCharacteristicValueSerializer(serializers.ModelSerializer):
447+
448+
class Meta:
449+
model = BaselineWealthGroupCharacteristicValue
450+
fields = [
451+
"id",
452+
"wealth_group",
453+
"wealth_group_label",
454+
"source_organization",
455+
"source_organization_name",
456+
"livelihood_zone_baseline",
457+
"livelihood_zone_baseline_label",
458+
"livelihood_zone",
459+
"livelihood_zone_name",
460+
"livelihood_zone_country_code",
461+
"livelihood_zone_country_name",
462+
"wealth_group_category",
463+
"wealth_group_category_name",
464+
"wealth_group_category_description",
465+
"wealth_characteristic",
466+
"wealth_characteristic_name",
467+
"wealth_characteristic_description",
468+
"variable_type",
469+
"characteristic_group",
470+
"product",
471+
"product_common_name",
472+
"unit_of_measure",
473+
"unit_of_measure_description",
474+
"value",
475+
"min_value",
476+
"max_value",
477+
]
478+
479+
livelihood_zone_baseline_label = serializers.SerializerMethodField()
480+
481+
def get_livelihood_zone_baseline_label(self, obj):
482+
return (
483+
str(obj.wealth_group.livelihood_zone_baseline)
484+
if obj.wealth_group.community
485+
else str(obj.wealth_group.livelihood_zone_baseline)
486+
)
487+
488+
wealth_group_label = serializers.SerializerMethodField()
489+
490+
def get_wealth_group_label(self, obj):
491+
return str(obj.wealth_group)
492+
493+
wealth_group_category = serializers.CharField(source="wealth_group.wealth_group_category.pk", read_only=True)
494+
wealth_group_category_name = serializers.CharField(
495+
source="wealth_group.wealth_group_category.name", read_only=True
496+
)
497+
wealth_group_category_description = serializers.CharField(
498+
source="wealth_group.wealth_group_category.description", read_only=True
499+
)
500+
wealth_characteristic_name = serializers.CharField(source="wealth_characteristic.name", read_only=True)
501+
wealth_characteristic_description = serializers.CharField(
502+
source="wealth_characteristic.description", read_only=True
503+
)
504+
variable_type = serializers.CharField(source="wealth_characteristic.variable_type", read_only=True)
505+
livelihood_zone_baseline = serializers.IntegerField(
506+
source="wealth_group.livelihood_zone_baseline.pk", read_only=True
507+
)
508+
livelihood_zone_name = serializers.CharField(
509+
source="wealth_group.livelihood_zone_baseline.livelihood_zone.name", read_only=True
510+
)
511+
livelihood_zone = serializers.CharField(
512+
source="wealth_group.livelihood_zone_baseline.livelihood_zone.pk", read_only=True
513+
)
514+
livelihood_zone_country_code = serializers.CharField(
515+
source="wealth_group.livelihood_zone_baseline.livelihood_zone.country.pk", read_only=True
516+
)
517+
livelihood_zone_country_name = serializers.CharField(
518+
source="wealth_group.livelihood_zone_baseline.livelihood_zone.country.name", read_only=True
519+
)
520+
source_organization = serializers.IntegerField(
521+
source="wealth_group.livelihood_zone_baseline.source_organization.pk", read_only=True
522+
)
523+
source_organization_name = serializers.CharField(
524+
source="wealth_group.livelihood_zone_baseline.source_organization.name", read_only=True
525+
)
526+
characteristic_group = serializers.SerializerMethodField()
527+
528+
def get_characteristic_group(self, obj):
529+
"""
530+
Override the default characteristic_group for Livestock and Poultry.
531+
532+
This allows us to use the same wealth characteristic, e.g. 'Number owned' for both Livestock and Poultry,
533+
as well as other wealth characteristics.
534+
"""
535+
if obj.product and obj.product.cpc.startswith("L0215"):
536+
return "Poultry"
537+
if obj.product and obj.product.cpc.startswith("L02"):
538+
return "Livestock"
539+
return obj.wealth_characteristic.characteristic_group
540+
541+
product_common_name = serializers.CharField(source="product.common_name", read_only=True, allow_null=True)
542+
unit_of_measure_description = serializers.CharField(
543+
source="unit_of_measure.description", read_only=True, allow_null=True
544+
)
545+
546+
547+
class CommunityWealthGroupCharacteristicValueSerializer(WealthGroupCharacteristicValueSerializer):
548+
class Meta:
549+
model = CommunityWealthGroupCharacteristicValue
550+
fields = WealthGroupCharacteristicValueSerializer.Meta.fields
416551

417552

418553
class LivelihoodStrategySerializer(serializers.ModelSerializer):
@@ -439,7 +574,6 @@ class Meta:
439574
"product_common_name",
440575
"product_description",
441576
"unit_of_measure",
442-
"unit_of_measure_name",
443577
"unit_of_measure_description",
444578
"currency",
445579
"additional_identifier",
@@ -461,7 +595,6 @@ class Meta:
461595
source_organization_name = serializers.CharField(
462596
source="livelihood_zone_baseline.source_organization.name", read_only=True
463597
)
464-
unit_of_measure_name = serializers.CharField(source="unit_of_measure.name", read_only=True)
465598
unit_of_measure_description = serializers.CharField(source="unit_of_measure.description", read_only=True)
466599
product_common_name = serializers.CharField(source="product.common_name", read_only=True)
467600
product_description = serializers.CharField(source="product.description", read_only=True)
@@ -510,7 +643,6 @@ class Meta:
510643
"product_common_name",
511644
"product_description",
512645
"unit_of_measure",
513-
"unit_of_measure_name",
514646
"unit_of_measure_description",
515647
"currency",
516648
"additional_identifier",
@@ -570,7 +702,6 @@ def get_livelihood_zone_baseline_label(self, obj):
570702
community_name = serializers.CharField(source="wealth_group.community.name", read_only=True)
571703
community_full_name = serializers.CharField(source="wealth_group.community.full_name", read_only=True)
572704
unit_of_measure = serializers.CharField(source="livelihood_strategy.unit_of_measure.pk", read_only=True)
573-
unit_of_measure_name = serializers.CharField(source="livelihood_strategy.unit_of_measure.name", read_only=True)
574705
unit_of_measure_description = serializers.CharField(
575706
source="livelihood_strategy.unit_of_measure.description", read_only=True
576707
)
@@ -910,19 +1041,15 @@ class Meta:
9101041
"yield_without_inputs",
9111042
"seed_requirement",
9121043
"crop_unit_of_measure",
913-
"crop_unit_of_measure_name",
9141044
"crop_unit_of_measure_description",
9151045
"land_unit_of_measure",
916-
"land_unit_of_measure_name",
9171046
"land_unit_of_measure_description",
9181047
]
9191048

9201049
crop_common_name = serializers.CharField(source="crop.common_name", read_only=True)
9211050
crop_description = serializers.CharField(source="crop.description", read_only=True)
9221051
community_name = serializers.CharField(source="community.name", read_only=True)
923-
crop_unit_of_measure_name = serializers.CharField(source="crop_unit_of_measure.name", read_only=True)
9241052
crop_unit_of_measure_description = serializers.CharField(source="crop_unit_of_measure.description", read_only=True)
925-
land_unit_of_measure_name = serializers.CharField(source="land_unit_of_measure.name", read_only=True)
9261053
land_unit_of_measure_description = serializers.CharField(source="land_unit_of_measure.description", read_only=True)
9271054
season_name = serializers.CharField(source="season.name", read_only=True)
9281055
season_description = serializers.CharField(source="season.description", read_only=True)
@@ -1040,7 +1167,6 @@ class Meta:
10401167
"product_common_name",
10411168
"product_description",
10421169
"unit_of_measure",
1043-
"unit_of_measure_name",
10441170
"unit_of_measure_description",
10451171
"currency",
10461172
"description",
@@ -1057,7 +1183,6 @@ class Meta:
10571183
product = serializers.CharField(source="product.pk", read_only=True)
10581184
product_common_name = serializers.CharField(source="product.common_name", read_only=True)
10591185
product_description = serializers.CharField(source="product.description", read_only=True)
1060-
unit_of_measure_name = serializers.CharField(source="unit_of_measure.name", read_only=True)
10611186
unit_of_measure_description = serializers.CharField(source="unit_of_measure.description", read_only=True)
10621187
livelihood_zone_baseline = serializers.IntegerField(source="community.livelihood_zone_baseline.pk", read_only=True)
10631188
livelihood_zone_name = serializers.CharField(
@@ -1274,7 +1399,6 @@ class Meta:
12741399
"product_common_name",
12751400
"product_description",
12761401
"unit_of_measure",
1277-
"unit_of_measure_name",
12781402
"unit_of_measure_description",
12791403
"currency",
12801404
"additional_identifier",
@@ -1329,7 +1453,6 @@ def get_livelihood_zone_baseline_label(self, obj):
13291453
community = serializers.IntegerField(source="wealth_group.community.pk", read_only=True)
13301454
community_name = serializers.CharField(source="wealth_group.community.name", read_only=True)
13311455
unit_of_measure = serializers.CharField(source="livelihood_strategy.unit_of_measure.pk", read_only=True)
1332-
unit_of_measure_name = serializers.CharField(source="livelihood_strategy.unit_of_measure.name", read_only=True)
13331456
unit_of_measure_description = serializers.CharField(
13341457
source="livelihood_strategy.unit_of_measure.description", read_only=True
13351458
)
@@ -1408,7 +1531,6 @@ class Meta:
14081531
"product_common_name",
14091532
"product_description",
14101533
"unit_of_measure",
1411-
"unit_of_measure_name",
14121534
"unit_of_measure_description",
14131535
"currency",
14141536
"additional_identifier",
@@ -1445,7 +1567,6 @@ def get_livelihood_zone_baseline_label(self, obj):
14451567
additional_identifier = serializers.CharField(source="livelihood_strategy.additional_identifier", read_only=True)
14461568
currency = serializers.CharField(source="livelihood_strategy.currency.pk", read_only=True)
14471569
unit_of_measure = serializers.CharField(source="livelihood_strategy.unit_of_measure.pk", read_only=True)
1448-
unit_of_measure_name = serializers.CharField(source="livelihood_strategy.unit_of_measure.name", read_only=True)
14491570
unit_of_measure_description = serializers.CharField(
14501571
source="livelihood_strategy.unit_of_measure.description", read_only=True
14511572
)

0 commit comments

Comments
 (0)