Browse Source

fix(api): properly return mandate reference for donations, fixes #530

The response is generated from serializer.data, which is based on only
request data until .save() is called.  After that, is contains a
representation of the instance created during the .save() call.

This commit moves the instance creation from the view to the .save()
call so that the .data logistics works properly (without actually
saving anything).
Peter Thomassen 4 years ago
parent
commit
888dcc0a2a
3 changed files with 27 additions and 2 deletions
  1. 3 0
      api/desecapi/serializers.py
  2. 23 1
      api/desecapi/tests/test_donations.py
  3. 1 1
      api/desecapi/views.py

+ 3 - 0
api/desecapi/serializers.py

@@ -601,6 +601,9 @@ class DonationSerializer(serializers.ModelSerializer):
     def validate_iban(value):
         return re.sub(r'[\s]', '', value)
 
+    def create(self, validated_data):
+        return self.Meta.model(**validated_data)
+
 
 class UserSerializer(serializers.ModelSerializer):
 

+ 23 - 1
api/desecapi/tests/test_donations.py

@@ -12,7 +12,26 @@ class DonationTests(DesecTestCase):
             response = method(reverse('v1:donation'))
             self.assertStatus(response, status.HTTP_405_METHOD_NOT_ALLOWED)
 
-    def test_create_donation(self):
+    def test_create_donation_minimal(self):
+        url = reverse('v1:donation')
+        data = {
+            'name': 'Name',
+            'iban': 'DE89370400440532013000',
+            'amount': 123.45,
+        }
+        response = self.client.post(url, data)
+        self.assertTrue(mail.outbox)
+        email_internal = str(mail.outbox[0].message())
+        direct_debit = str(mail.outbox[0].attachments[0][1])
+        self.assertStatus(response, status.HTTP_201_CREATED)
+        self.assertEqual(len(mail.outbox), 1)
+        self.assertEqual(response.data['iban'], data['iban'])
+        self.assertEqual(response.data['interval'], 0)
+        self.assertIn('ONDON1', response.data['mref'])
+        self.assertTrue('Name' in direct_debit)
+        self.assertTrue(data['iban'] in email_internal)
+
+    def test_create_donation_verbose(self):
         url = reverse('v1:donation')
         data = {
             'name': 'Komplizierter Vörnämü-ßßß 马大为',
@@ -21,6 +40,7 @@ class DonationTests(DesecTestCase):
             'amount': 123.45,
             'message': 'hi there, thank you. Also, some random chars:  ™ • ½ ¼ ¾ ⅓ ⅔ † ‡ µ ¢ £ € « » ♤ ♧ ♥ ♢ ¿ ',
             'email': 'email@example.com',
+            'interval': 3,
         }
         response = self.client.post(url, data)
         self.assertTrue(mail.outbox)
@@ -29,5 +49,7 @@ class DonationTests(DesecTestCase):
         self.assertStatus(response, status.HTTP_201_CREATED)
         self.assertEqual(len(mail.outbox), 2)
         self.assertEqual(response.data['iban'], data['iban'])
+        self.assertEqual(response.data['interval'], 3)
+        self.assertIn('ONDON1', response.data['mref'])
         self.assertTrue('Komplizierter Vornamu' in direct_debit)
         self.assertTrue(data['iban'] in email_internal)

+ 1 - 1
api/desecapi/views.py

@@ -391,7 +391,7 @@ class DonationList(generics.CreateAPIView):
     serializer_class = serializers.DonationSerializer
 
     def perform_create(self, serializer):
-        instance = self.serializer_class.Meta.model(**serializer.validated_data)
+        instance = serializer.save()
 
         context = {
             'donation': instance,