瀏覽代碼

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 年之前
父節點
當前提交
888dcc0a2a
共有 3 個文件被更改,包括 27 次插入2 次删除
  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,