From c700381c585a43af97548ad4c683bc4ff441e6b3 Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 08:58:48 +0300 Subject: [PATCH 01/10] Add display format choices Display format should be used to indicate how a value (in key metric or highlight) should be displayed to the user. Using denominator for both computing the value and hot to display is to limiting. --- wazimap_ng/config/common.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wazimap_ng/config/common.py b/wazimap_ng/config/common.py index b946fd71..5c40da54 100755 --- a/wazimap_ng/config/common.py +++ b/wazimap_ng/config/common.py @@ -337,6 +337,12 @@ def get_env_value(env_variable): ('sibling', 'Sibling'), ) +DISPLAY_FORMAT_CHOICES = ( + ('absolute_value', 'Integer'), + ('decimal', 'Decimal'), + ('percentage', 'Percentage'), +) + PERMISSION_TYPES = ( ('private', 'Private'), ('public', 'Public'), From 76e5d4e20dcc7e61afa5131b7ef8f19950de5efa Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 09:44:08 +0300 Subject: [PATCH 02/10] Add support for DISPLAY_FORMAT_CHOICES in KeyMetric and Hightlight models --- .../migrations/0053_value_display_format.py | 33 +++++++++++++++++++ wazimap_ng/profile/models.py | 4 ++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 wazimap_ng/profile/migrations/0053_value_display_format.py diff --git a/wazimap_ng/profile/migrations/0053_value_display_format.py b/wazimap_ng/profile/migrations/0053_value_display_format.py new file mode 100644 index 00000000..0ed0f40f --- /dev/null +++ b/wazimap_ng/profile/migrations/0053_value_display_format.py @@ -0,0 +1,33 @@ +# Generated by Django 2.2.24 on 2022-05-27 06:25 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('profile', '0052_auto_20220111_1315'), + ] + + operations = [ + migrations.AddField( + model_name='historicalprofilehighlight', + name='display_format', + field=models.CharField(choices=[('absolute_value', 'Integer'), ('decimal', 'Decimal'), ('percentage', 'Percentage')], default='percentage', help_text='Method for displaying the value to the user.', max_length=32), + ), + migrations.AddField( + model_name='historicalprofilekeymetrics', + name='display_format', + field=models.CharField(choices=[('absolute_value', 'Integer'), ('decimal', 'Decimal'), ('percentage', 'Percentage')], default='percentage', help_text='Method for displaying the value to the user.', max_length=32), + ), + migrations.AddField( + model_name='profilehighlight', + name='display_format', + field=models.CharField(choices=[('absolute_value', 'Integer'), ('decimal', 'Decimal'), ('percentage', 'Percentage')], default='percentage', help_text='Method for displaying the value to the user.', max_length=32), + ), + migrations.AddField( + model_name='profilekeymetrics', + name='display_format', + field=models.CharField(choices=[('absolute_value', 'Integer'), ('decimal', 'Decimal'), ('percentage', 'Percentage')], default='percentage', help_text='Method for displaying the value to the user.', max_length=32), + ), + ] diff --git a/wazimap_ng/profile/models.py b/wazimap_ng/profile/models.py index 7e8a6397..b644e075 100644 --- a/wazimap_ng/profile/models.py +++ b/wazimap_ng/profile/models.py @@ -6,7 +6,7 @@ from wazimap_ng.datasets.models import Indicator, GeographyHierarchy from wazimap_ng.general.models import BaseModel, SimpleHistory from wazimap_ng.config.common import ( - DENOMINATOR_CHOICES, PERMISSION_TYPES, PI_CONTENT_TYPE + DENOMINATOR_CHOICES, PERMISSION_TYPES, PI_CONTENT_TYPE, DISPLAY_FORMAT_CHOICES ) class Profile(BaseModel, SimpleHistory): @@ -76,6 +76,7 @@ class ProfileKeyMetrics(BaseModel, SimpleHistory): subindicator = models.PositiveSmallIntegerField() denominator = models.CharField(choices=DENOMINATOR_CHOICES, max_length=32, help_text="Method for calculating the denominator that will normalise this value.") label = models.CharField(max_length=255, help_text="Text used for display to users.") + display_format = models.CharField(choices=DISPLAY_FORMAT_CHOICES, default="percentage", max_length=32, help_text="Method for displaying the value to the user.") order = models.PositiveIntegerField(default=0, blank=False, null=False) @property @@ -96,6 +97,7 @@ class ProfileHighlight(BaseModel, SimpleHistory): subindicator = models.PositiveSmallIntegerField(null=True, blank=True) denominator = models.CharField(choices=DENOMINATOR_CHOICES, max_length=32, help_text="Method for calculating the denominator that will normalise this value.") label = models.CharField(max_length=255, null=False, blank=True, help_text="Label for the indicator displayed on the front-end") + display_format = models.CharField(choices=DISPLAY_FORMAT_CHOICES, default="percentage", max_length=32, help_text="Method for displaying the value to the user.") order = models.PositiveIntegerField(default=0, blank=False, null=False) def __str__(self): From 15133d26a0b7879ed49396df71ea9a49c1d37dd2 Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 09:44:50 +0300 Subject: [PATCH 03/10] Inlcude value_display_format in HighlightsSerializer --- wazimap_ng/profile/serializers/highlights_serializer.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/wazimap_ng/profile/serializers/highlights_serializer.py b/wazimap_ng/profile/serializers/highlights_serializer.py index f636ec58..f0081f7e 100644 --- a/wazimap_ng/profile/serializers/highlights_serializer.py +++ b/wazimap_ng/profile/serializers/highlights_serializer.py @@ -54,5 +54,11 @@ def HighlightsSerializer(profile, geography, version): val = method(highlight, geography, version) if val is not None: - highlights.append({"label": highlight.label, "value": val, "method": denominator}) + highlights.append({ + "label": highlight.label, + "value": val, + "value_display_format": highlight.display_format, + "method": denominator + }) + return highlights From 150a6d2dc1ef1c9b7877ae0c0b1cd46055d938d6 Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 09:45:13 +0300 Subject: [PATCH 04/10] Include value_display_format in MetricsSerializer --- wazimap_ng/profile/serializers/metrics_serializer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/wazimap_ng/profile/serializers/metrics_serializer.py b/wazimap_ng/profile/serializers/metrics_serializer.py index eaeed8d7..3e6cb363 100644 --- a/wazimap_ng/profile/serializers/metrics_serializer.py +++ b/wazimap_ng/profile/serializers/metrics_serializer.py @@ -61,6 +61,7 @@ def MetricsSerializer(profile, geography, version): "key_metrics": [{ "label": profile_key_metric.label, "value": val, + "value_display_format": profile_key_metric.display_format, "method": denominator, "metadata": { "description": profile_key_metric.variable.dataset.metadata.description, From 2c3ba01c78c486ddad0ccef22c3538f75366b25f Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 09:50:51 +0300 Subject: [PATCH 05/10] Include display_format in admin --- wazimap_ng/profile/admin/admins/profile_highlight_admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wazimap_ng/profile/admin/admins/profile_highlight_admin.py b/wazimap_ng/profile/admin/admins/profile_highlight_admin.py index 9d18b992..4382c9c9 100644 --- a/wazimap_ng/profile/admin/admins/profile_highlight_admin.py +++ b/wazimap_ng/profile/admin/admins/profile_highlight_admin.py @@ -31,7 +31,7 @@ class ProfileHighlightAdmin(SortableAdminMixin, BaseAdminModel, HistoryAdmin): "fields": ("profile", "indicator") }), ("Profile fields", { - "fields": ("label", "subindicator", "denominator") + "fields": ("label", "subindicator", "denominator", "display_format") }) ) form = ProfileHighlightForm From d3a79c3fdd85f5f35b2b765e352aa498113ace49 Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 09:51:18 +0300 Subject: [PATCH 06/10] Include display_format in admin --- wazimap_ng/profile/admin/admins/profile_key_metrics_admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wazimap_ng/profile/admin/admins/profile_key_metrics_admin.py b/wazimap_ng/profile/admin/admins/profile_key_metrics_admin.py index 935a6da1..75709e88 100644 --- a/wazimap_ng/profile/admin/admins/profile_key_metrics_admin.py +++ b/wazimap_ng/profile/admin/admins/profile_key_metrics_admin.py @@ -37,7 +37,7 @@ class ProfileKeyMetricsAdmin(SortableAdminMixin, BaseAdminModel, HistoryAdmin): help_texts = ["denominator", ] - fields = ["profile", "variable", "subindicator", "subcategory", "denominator", "label"] + fields = ["profile", "variable", "subindicator", "subcategory", "denominator", "label", "display_format"] search_fields = ("label", ) From 8f34491483710ae25e2d840742a08b079794aa66 Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 13:46:27 +0300 Subject: [PATCH 07/10] Include collectstatic command in starting supporting services --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dc2ae180..845a3199 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Local development is normally done inside docker-compose so that the supporting Make docker-compose start the supporting services docker-compose run --rm web python wait_for_postgres.py + docker-compose run --rm web python manage.py collectstatic --no-input Migrate, load development data and start the app From 3cc1878459d6f3fa74bd1dcba779a41a323d2b47 Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 13:47:07 +0300 Subject: [PATCH 08/10] Include display_format in admin_history tests --- tests/profile/admin_history/test_highlights_history.py | 4 +++- tests/profile/admin_history/test_key_metrics_history.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/profile/admin_history/test_highlights_history.py b/tests/profile/admin_history/test_highlights_history.py index 08f94421..eed6922e 100644 --- a/tests/profile/admin_history/test_highlights_history.py +++ b/tests/profile/admin_history/test_highlights_history.py @@ -33,17 +33,19 @@ def test_history_for_highlight_edit_from_admin( "subindicator": profile_highlight.subindicator, "denominator": "absolute_value", "label": "new label", + "display_format": "absolute_value", "change_reason": "Changed Label", } res = client.post(url, data, follow=True) assert res.status_code == 200 - assert profile_highlight.history.all().count() == 2 + assert profile_highlight.history.count() == 2 history = profile_highlight.history.first() assert history.history_user_id == superuser.id changed_data = json.loads(history.history_change_reason) assert changed_data["reason"] == "Changed Label" assert "label" in changed_data["changed_fields"] + assert "display_format" in changed_data["changed_fields"] assert "denominator" in changed_data["changed_fields"] assert history.history_type == "~" \ No newline at end of file diff --git a/tests/profile/admin_history/test_key_metrics_history.py b/tests/profile/admin_history/test_key_metrics_history.py index 1a9e9f60..1ddf4429 100644 --- a/tests/profile/admin_history/test_key_metrics_history.py +++ b/tests/profile/admin_history/test_key_metrics_history.py @@ -35,17 +35,19 @@ def test_history_for_key_metrics_edit_from_admin( "variable_variable_type": "public", "denominator": "absolute_value", "label": "new label", + "display_format": "absolute_value", "change_reason": "Changed Label", } res = client.post(url, data, follow=True) assert res.status_code == 200 - assert profile_key_metric.history.all().count() == 2 + assert profile_key_metric.history.count() == 2 history = profile_key_metric.history.first() assert history.history_user_id == superuser.id changed_data = json.loads(history.history_change_reason) assert changed_data["reason"] == "Changed Label" assert "label" in changed_data["changed_fields"] + assert "display_format" in changed_data["changed_fields"] assert "denominator" in changed_data["changed_fields"] assert history.history_type == "~" From d21da49b335fb71d6e3447a8da5dbcc0fc82831a Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 13:47:35 +0300 Subject: [PATCH 09/10] Include display_format tests in serializers tests --- .../serializers/test_highlights_serializer.py | 21 ++++++++++++++++++ .../serializers/test_metrics_serializer.py | 22 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/tests/profile/serializers/test_highlights_serializer.py b/tests/profile/serializers/test_highlights_serializer.py index aa9ea30c..cb9f1348 100644 --- a/tests/profile/serializers/test_highlights_serializer.py +++ b/tests/profile/serializers/test_highlights_serializer.py @@ -11,6 +11,15 @@ def profile_highlight_without_data(profile, indicator): profile=profile, indicator=indicator, subindicator=FEMALE_GROUP_INDEX ) +@pytest.fixture +def profile_highlight_with_decimal_display_format(profile, indicatordata): + FEMALE_GROUP_INDEX = 1 + indicator = indicatordata[0].indicator + return ProfileHighlightFactory( + profile=profile, indicator=indicator, subindicator=FEMALE_GROUP_INDEX, + display_format='decimal', + ); + @pytest.mark.django_db def test_absolute_value(profile_highlight, indicatordata_json, geography, version): expected_value = sum(el["count"] for el in indicatordata_json if el["gender"] == "female") @@ -61,3 +70,15 @@ def test_sibling_without_indicatordata(profile_highlight_without_data, version, expected_value = None actual_value = sibling(profile_highlight_without_data, geography, version) assert expected_value == actual_value + +@pytest.mark.django_db +def test_data_format(profile_highlight): + expected_value = 'percentage' + actual_value = profile_highlight.display_format; + assert expected_value == actual_value + +@pytest.mark.django_db +def test_data_format_with_decimal_display_format(profile_highlight_with_decimal_display_format): + expected_value = 'decimal' + actual_value = profile_highlight_with_decimal_display_format.display_format; + assert expected_value == actual_value diff --git a/tests/profile/serializers/test_metrics_serializer.py b/tests/profile/serializers/test_metrics_serializer.py index 4fbf51c2..3f038269 100644 --- a/tests/profile/serializers/test_metrics_serializer.py +++ b/tests/profile/serializers/test_metrics_serializer.py @@ -3,6 +3,7 @@ from wazimap_ng.profile.serializers.metrics_serializer import absolute_value, subindicator, sibling from tests.datasets.factories import GeographyFactory, IndicatorDataFactory +from tests.profile.factories import ProfileKeyMetricsFactory @pytest.fixture def additional_data_json(): @@ -21,6 +22,15 @@ def additional_data_json(): ] ] +@pytest.fixture +def profile_key_metric_with_decimal_display_format(profile, indicatordata, subcategory): + FEMALE_GROUP_INDEX = 1 + indicator = indicatordata[0].indicator + return ProfileKeyMetricsFactory( + profile=profile, variable=indicator, subindicator=FEMALE_GROUP_INDEX, + subcategory=subcategory, display_format="decimal", + ) + @pytest.mark.django_db class TestAbsoluteValue: def test_absolute_value(self, profile_key_metric, indicatordata_json, geography): @@ -169,3 +179,15 @@ def test_sibling_not_none(profile_key_metric, geography, other_geographies, vers with patch.object(geography, "get_version_siblings", side_effect=lambda _version: other_geographies): sibling_data = sibling(profile_key_metric, geography, version) assert sibling_data != None + +@pytest.mark.django_db +def test_data_format(profile_highlight): + expected_value = 'percentage' + actual_value = profile_highlight.display_format; + assert expected_value == actual_value + +@pytest.mark.django_db +def test_data_format_with_decimal_display_format(profile_key_metric_with_decimal_display_format): + expected_value = 'decimal' + actual_value = profile_key_metric_with_decimal_display_format.display_format; + assert expected_value == actual_value From 7c5ccada8094df74fd843c73acc3583daacbfea3 Mon Sep 17 00:00:00 2001 From: _ Kilemensi Date: Fri, 27 May 2022 13:50:12 +0300 Subject: [PATCH 10/10] Format --- tests/profile/admin_history/test_highlights_history.py | 2 +- wazimap_ng/profile/models.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/profile/admin_history/test_highlights_history.py b/tests/profile/admin_history/test_highlights_history.py index eed6922e..98ebc731 100644 --- a/tests/profile/admin_history/test_highlights_history.py +++ b/tests/profile/admin_history/test_highlights_history.py @@ -48,4 +48,4 @@ def test_history_for_highlight_edit_from_admin( assert "label" in changed_data["changed_fields"] assert "display_format" in changed_data["changed_fields"] assert "denominator" in changed_data["changed_fields"] - assert history.history_type == "~" \ No newline at end of file + assert history.history_type == "~" diff --git a/wazimap_ng/profile/models.py b/wazimap_ng/profile/models.py index b644e075..90cbeaf3 100644 --- a/wazimap_ng/profile/models.py +++ b/wazimap_ng/profile/models.py @@ -6,7 +6,7 @@ from wazimap_ng.datasets.models import Indicator, GeographyHierarchy from wazimap_ng.general.models import BaseModel, SimpleHistory from wazimap_ng.config.common import ( - DENOMINATOR_CHOICES, PERMISSION_TYPES, PI_CONTENT_TYPE, DISPLAY_FORMAT_CHOICES + DENOMINATOR_CHOICES, DISPLAY_FORMAT_CHOICES, PERMISSION_TYPES, PI_CONTENT_TYPE ) class Profile(BaseModel, SimpleHistory):