diff --git a/src/meshapi/serializers/nested_key_object_related_field.py b/src/meshapi/serializers/nested_key_object_related_field.py index 32e7c3c9..69b8ca5c 100644 --- a/src/meshapi/serializers/nested_key_object_related_field.py +++ b/src/meshapi/serializers/nested_key_object_related_field.py @@ -1,5 +1,6 @@ import typing from typing import Any, Dict, Tuple, cast +from uuid import UUID from django.core.exceptions import ObjectDoesNotExist from django.db.models import Model @@ -42,7 +43,16 @@ def _get_key_fields(self) -> Tuple[str, ...]: return ("id",) + self.additional_keys def to_representation(self, value: Model) -> dict[str, Any]: - return {key: getattr(value, key) for key in self._get_key_fields()} + output = {} + for key in self._get_key_fields(): + output[key] = getattr(value, key) + + # Convert UUID objects to str so that the resulting data + # is trivially JSON serializable + if isinstance(output[key], UUID): + output[key] = str(output[key]) + + return output def to_internal_value(self, data: dict) -> Model: queryset = self.get_queryset() diff --git a/src/meshapi/tests/test_slack_notification.py b/src/meshapi/tests/test_slack_notification.py index 1f3789ea..34190b53 100644 --- a/src/meshapi/tests/test_slack_notification.py +++ b/src/meshapi/tests/test_slack_notification.py @@ -6,12 +6,26 @@ from django.test import RequestFactory, TestCase from requests import RequestException -from meshapi.models import Member +from meshapi.models import Building, Install, Member from meshapi.serializers import MemberSerializer +from meshapi.tests.sample_data import sample_building, sample_install, sample_member from meshapi.util.admin_notifications import notify_administrators_of_data_issue class TestSlackNotification(TestCase): + def setUp(self): + self.sample_install_copy = sample_install.copy() + self.building_1 = Building(**sample_building) + self.building_1.save() + self.sample_install_copy["building"] = self.building_1 + + self.sample_member = Member(**sample_member) + self.sample_member.save() + self.sample_install_copy["member"] = self.sample_member + + self.install = Install(**self.sample_install_copy) + self.install.save() + @requests_mock.Mocker() @patch("meshapi.util.admin_notifications.SLACK_ADMIN_NOTIFICATIONS_WEBHOOK_URL", "https://mock-slack-url") def test_slack_notification_for_name_change(self, requests_mocker): @@ -23,6 +37,9 @@ def test_slack_notification_for_name_change(self, requests_mocker): ) member.save() + self.install.member = member + self.install.save() + rf = RequestFactory() mock_join_form_request = rf.post("https://mock-meshdb-url.example/join-form/") @@ -56,7 +73,12 @@ def test_slack_notification_for_name_change(self, requests_mocker): ' "all_phone_numbers": [\n' ' "+1 212-555-5555"\n' " ],\n" - ' "installs": [],\n' + ' "installs": [\n' + " {\n" + f' "id": "{self.install.id}",\n' + f' "install_number": {self.install.install_number}\n' + " }\n" + " ],\n" ' "name": "Stacy Maidenname",\n' ' "primary_email_address": "stacy@example.com",\n' ' "stripe_email_address": null,\n'