diff --git a/AUTHORS.rst b/AUTHORS.rst index cb931816bb..8f4d51cd86 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -24,7 +24,6 @@ Contributors * Thomas Parslow (@almost) * Leonid Shvechikov (@shvechikov) * sromero84 -* Mahdi Yusuf (@myusuf3) * Peter Baumgartner (@ipmb) * Vikas (@vikasgulati) * Colton Allen (@cmanallen) @@ -32,4 +31,5 @@ Contributors * Martin Hill (@martinhill) * Michael Thornhill * Tobias Lorenz (@Tyrdall) -* Ben Whalley \ No newline at end of file +* Ben Whalley +* nanvel diff --git a/HISTORY.rst b/HISTORY.rst index b1982883b0..b9dcf456ca 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,7 +3,7 @@ History ======= -0.5.0 (2015-04-??) +0.5.0 (2015-05-??) --------------------- * Removed the StripeSubscriptionSignupForm @@ -12,6 +12,8 @@ History * The sync_subscriber argument has been renamed from subscriber_model to subscriber * Moved available currencies to the DJSTRIPE_CURRENCIES setting (Thanks @martinhill) * Allow passing of extra parameters to stripe Charge API (Thanks @mthornhill) +* charge.refund() now returns the refunded charge object (Thanks @mthornhill) +* Charge model now has captured field and a capture method (Thanks @mthornhill) * South migrations are now up to date (Thanks @Tyrdall) 0.4.0 (2015-04-05) diff --git a/djstripe/migrations/0005_charge_captured.py b/djstripe/migrations/0005_charge_captured.py new file mode 100644 index 0000000000..d3fcb43a57 --- /dev/null +++ b/djstripe/migrations/0005_charge_captured.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('djstripe', '0004_auto_20150427_1609'), + ] + + operations = [ + migrations.AddField( + model_name='charge', + name='captured', + field=models.NullBooleanField(), + preserve_default=True, + ), + ] diff --git a/djstripe/models.py b/djstripe/models.py index 02d5bb6daf..1b7dc76931 100644 --- a/djstripe/models.py +++ b/djstripe/models.py @@ -827,6 +827,7 @@ class Charge(StripeObject): paid = models.NullBooleanField(null=True) disputed = models.NullBooleanField(null=True) refunded = models.NullBooleanField(null=True) + captured = models.NullBooleanField(null=True) fee = models.DecimalField(decimal_places=2, max_digits=7, null=True) receipt_sent = models.BooleanField(default=False) charge_created = models.DateTimeField(null=True, blank=True) @@ -847,7 +848,18 @@ def refund(self, amount=None): ).refund( amount=self.calculate_refund_amount(amount=amount) ) - Charge.sync_from_stripe_data(charge_obj) + return Charge.sync_from_stripe_data(charge_obj) + + def capture(self): + """ + Capture the payment of an existing, uncaptured, charge. This is the second half of the two-step payment flow, + where first you created a charge with the capture option set to false. + See https://stripe.com/docs/api#capture_charge + """ + charge_obj = stripe.Charge.retrieve( + self.stripe_id + ).capture() + return Charge.sync_from_stripe_data(charge_obj) @classmethod def sync_from_stripe_data(cls, data): @@ -862,6 +874,7 @@ def sync_from_stripe_data(cls, data): obj.amount = (data["amount"] / decimal.Decimal("100")) obj.paid = data["paid"] obj.refunded = data["refunded"] + obj.captured = data["captured"] obj.fee = (data["fee"] / decimal.Decimal("100")) obj.disputed = data["dispute"] is not None obj.charge_created = convert_tstamp(data, "created") diff --git a/djstripe/south_migrations/0007_auto__add_field_charge_captured.py b/djstripe/south_migrations/0007_auto__add_field_charge_captured.py new file mode 100644 index 0000000000..be2b07a367 --- /dev/null +++ b/djstripe/south_migrations/0007_auto__add_field_charge_captured.py @@ -0,0 +1,222 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding field 'Charge.captured' + db.add_column(u'djstripe_charge', 'captured', + self.gf('django.db.models.fields.NullBooleanField')(null=True, blank=True), + keep_default=False) + + + def backwards(self, orm): + # Deleting field 'Charge.captured' + db.delete_column(u'djstripe_charge', 'captured') + + + models = { + u'auth.group': { + 'Meta': {'object_name': 'Group'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'auth.permission': { + 'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Group']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "u'user_set'", 'blank': 'True', 'to': u"orm['auth.Permission']"}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + u'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + u'djstripe.charge': { + 'Meta': {'object_name': 'Charge'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2'}), + 'amount_refunded': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2'}), + 'captured': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'card_kind': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'card_last_4': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'charge_created': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'customer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'charges'", 'to': u"orm['djstripe.Customer']"}), + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'disputed': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'fee': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '7', 'decimal_places': '2'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'invoice': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'charges'", 'null': 'True', 'to': u"orm['djstripe.Invoice']"}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'paid': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'receipt_sent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'refunded': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'stripe_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}) + }, + u'djstripe.currentsubscription': { + 'Meta': {'object_name': 'CurrentSubscription'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'cancel_at_period_end': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'canceled_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'current_period_end': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'current_period_start': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + 'customer': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "u'current_subscription'", 'unique': 'True', 'null': 'True', 'to': u"orm['djstripe.Customer']"}), + 'ended_at': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'plan': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'quantity': ('django.db.models.fields.IntegerField', [], {}), + 'start': ('django.db.models.fields.DateTimeField', [], {}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '25'}), + 'trial_end': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}), + 'trial_start': ('django.db.models.fields.DateTimeField', [], {'null': 'True', 'blank': 'True'}) + }, + u'djstripe.customer': { + 'Meta': {'object_name': 'Customer'}, + 'card_fingerprint': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'card_kind': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'card_last_4': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'date_purged': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'stripe_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}), + 'subscriber': ('django.db.models.fields.related.OneToOneField', [], {'to': u"orm['auth.User']", 'unique': 'True', 'null': 'True'}) + }, + u'djstripe.event': { + 'Meta': {'object_name': 'Event'}, + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'customer': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['djstripe.Customer']", 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kind': ('django.db.models.fields.CharField', [], {'max_length': '250'}), + 'livemode': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'processed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'stripe_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}), + 'valid': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'validated_message': ('jsonfield.fields.JSONField', [], {'null': 'True'}), + 'webhook_message': ('jsonfield.fields.JSONField', [], {}) + }, + u'djstripe.eventprocessingexception': { + 'Meta': {'object_name': 'EventProcessingException'}, + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'data': ('django.db.models.fields.TextField', [], {}), + 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['djstripe.Event']", 'null': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'message': ('django.db.models.fields.CharField', [], {'max_length': '500'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'traceback': ('django.db.models.fields.TextField', [], {}) + }, + u'djstripe.invoice': { + 'Meta': {'ordering': "[u'-date']", 'object_name': 'Invoice'}, + 'attempted': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}), + 'attempts': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'charge': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}), + 'closed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'customer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'invoices'", 'to': u"orm['djstripe.Customer']"}), + 'date': ('django.db.models.fields.DateTimeField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'paid': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'period_end': ('django.db.models.fields.DateTimeField', [], {}), + 'period_start': ('django.db.models.fields.DateTimeField', [], {}), + 'stripe_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}), + 'subtotal': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'total': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}) + }, + u'djstripe.invoiceitem': { + 'Meta': {'object_name': 'InvoiceItem'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'currency': ('django.db.models.fields.CharField', [], {'max_length': '10'}), + 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'invoice': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'items'", 'to': u"orm['djstripe.Invoice']"}), + 'line_type': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'period_end': ('django.db.models.fields.DateTimeField', [], {}), + 'period_start': ('django.db.models.fields.DateTimeField', [], {}), + 'plan': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}), + 'proration': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'quantity': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'stripe_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'djstripe.plan': { + 'Meta': {'object_name': 'Plan'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'currency': ('django.db.models.fields.CharField', [], {'max_length': '10'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'interval': ('django.db.models.fields.CharField', [], {'max_length': '10'}), + 'interval_count': ('django.db.models.fields.IntegerField', [], {'default': '1', 'null': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'stripe_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}), + 'trial_period_days': ('django.db.models.fields.IntegerField', [], {'null': 'True'}) + }, + u'djstripe.transfer': { + 'Meta': {'object_name': 'Transfer'}, + 'adjustment_count': ('django.db.models.fields.IntegerField', [], {}), + 'adjustment_fees': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'adjustment_gross': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'charge_count': ('django.db.models.fields.IntegerField', [], {}), + 'charge_fees': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'charge_gross': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'collected_fee_count': ('django.db.models.fields.IntegerField', [], {}), + 'collected_fee_gross': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'date': ('django.db.models.fields.DateTimeField', [], {}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'event': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'transfers'", 'to': u"orm['djstripe.Event']"}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'net': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'refund_count': ('django.db.models.fields.IntegerField', [], {}), + 'refund_fees': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'refund_gross': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'status': ('django.db.models.fields.CharField', [], {'max_length': '25'}), + 'stripe_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}), + 'validation_count': ('django.db.models.fields.IntegerField', [], {}), + 'validation_fees': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}) + }, + u'djstripe.transferchargefee': { + 'Meta': {'object_name': 'TransferChargeFee'}, + 'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '7', 'decimal_places': '2'}), + 'application': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'created': ('model_utils.fields.AutoCreatedField', [], {'default': 'datetime.datetime.now'}), + 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'kind': ('django.db.models.fields.CharField', [], {'max_length': '150'}), + 'modified': ('model_utils.fields.AutoLastModifiedField', [], {'default': 'datetime.datetime.now'}), + 'transfer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "u'charge_fee_details'", 'to': u"orm['djstripe.Transfer']"}) + } + } + + complete_apps = ['djstripe'] \ No newline at end of file diff --git a/tests/test_customer.py b/tests/test_customer.py index 2769e14ad8..826f77b32e 100644 --- a/tests/test_customer.py +++ b/tests/test_customer.py @@ -66,6 +66,7 @@ def test_record_charge(self, RetrieveMock): "amount": 1000, "paid": True, "refunded": False, + "captured": True, "fee": 499, "dispute": None, "created": 1363911708, @@ -100,6 +101,7 @@ def test_refund_charge(self, RetrieveMock): "amount": 1000, "paid": True, "refunded": True, + "captured": True, "amount_refunded": 1000, "fee": 499, "dispute": None, @@ -111,6 +113,72 @@ def test_refund_charge(self, RetrieveMock): self.assertEquals(charge2.refunded, True) self.assertEquals(charge2.amount_refunded, decimal.Decimal("10.00")) + @patch("stripe.Charge.retrieve") + def test_capture_charge(self, RetrieveMock): + charge = Charge.objects.create( + stripe_id="ch_XXXXXX", + customer=self.customer, + card_last_4="4323", + card_kind="Visa", + amount=decimal.Decimal("10.00"), + paid=True, + refunded=False, + captured=False, + fee=decimal.Decimal("4.99"), + disputed=False + ) + RetrieveMock.return_value.capture.return_value = { + "id": "ch_XXXXXX", + "card": { + "last4": "4323", + "type": "Visa" + }, + "amount": 1000, + "paid": True, + "refunded": True, + "captured": True, + "amount_refunded": 1000, + "fee": 499, + "dispute": None, + "created": 1363911708, + "customer": "cus_xxxxxxxxxxxxxxx" + } + charge2 = charge.capture() + self.assertEquals(charge2.captured, True) + + @patch("stripe.Charge.retrieve") + def test_refund_charge_object_returned(self, RetrieveMock): + charge = Charge.objects.create( + stripe_id="ch_XXXXXX", + customer=self.customer, + card_last_4="4323", + card_kind="Visa", + amount=decimal.Decimal("10.00"), + paid=True, + refunded=False, + fee=decimal.Decimal("4.99"), + disputed=False + ) + RetrieveMock.return_value.refund.return_value = { + "id": "ch_XXXXXX", + "card": { + "last4": "4323", + "type": "Visa" + }, + "amount": 1000, + "paid": True, + "refunded": True, + "captured": True, + "amount_refunded": 1000, + "fee": 499, + "dispute": None, + "created": 1363911708, + "customer": "cus_xxxxxxxxxxxxxxx" + } + charge2 = charge.refund() + self.assertEquals(charge2.refunded, True) + self.assertEquals(charge2.amount_refunded, decimal.Decimal("10.00")) + def test_calculate_refund_amount_full_refund(self): charge = Charge( stripe_id="ch_111111", @@ -157,6 +225,7 @@ def test_charge_converts_dollars_into_cents(self, ChargeMock, RetrieveMock): "amount": 1000, "paid": True, "refunded": False, + "captured": True, "fee": 499, "dispute": None, "created": 1363911708, @@ -181,6 +250,7 @@ def test_charge_passes_extra_arguments(self, ChargeMock, RetrieveMock): "amount": 1000, "paid": True, "refunded": False, + "captured": True, "fee": 499, "dispute": None, "created": 1363911708, diff --git a/tests/test_email.py b/tests/test_email.py index 760f279fa6..3287994bce 100644 --- a/tests/test_email.py +++ b/tests/test_email.py @@ -35,6 +35,7 @@ def test_email_reciept_renders_amount_properly(self, ChargeMock, RetrieveMock): "amount": 40000, "paid": True, "refunded": False, + "captured": True, "fee": 499, "dispute": None, "created": 1363911708,