diff --git a/stripe/api_resources/__init__.py b/stripe/api_resources/__init__.py index 9c98c61ae..ce93cba37 100644 --- a/stripe/api_resources/__init__.py +++ b/stripe/api_resources/__init__.py @@ -19,6 +19,7 @@ from stripe.api_resources.charge import Charge from stripe.api_resources.country_spec import CountrySpec from stripe.api_resources.coupon import Coupon +from stripe.api_resources.credit_note import CreditNote from stripe.api_resources.customer import Customer from stripe.api_resources.dispute import Dispute from stripe.api_resources.ephemeral_key import EphemeralKey diff --git a/stripe/api_resources/credit_note.py b/stripe/api_resources/credit_note.py new file mode 100644 index 000000000..e040c727a --- /dev/null +++ b/stripe/api_resources/credit_note.py @@ -0,0 +1,20 @@ +from __future__ import absolute_import, division, print_function + +from stripe import util +from stripe.api_resources.abstract import CreateableAPIResource +from stripe.api_resources.abstract import UpdateableAPIResource +from stripe.api_resources.abstract import ListableAPIResource +from stripe.api_resources.abstract import custom_method + + +@custom_method("void_credit_note", http_verb="post", http_path="void") +class CreditNote( + CreateableAPIResource, UpdateableAPIResource, ListableAPIResource +): + OBJECT_NAME = "credit_note" + + def void_credit_note(self, idempotency_key=None, **params): + url = self.instance_url() + "/void" + headers = util.populate_headers(idempotency_key) + self.refresh_from(self.request("post", url, params, headers)) + return self diff --git a/stripe/util.py b/stripe/util.py index 17f672bb4..983a7f9a8 100644 --- a/stripe/util.py +++ b/stripe/util.py @@ -159,6 +159,7 @@ def load_object_classes(): api_resources.checkout.Session.OBJECT_NAME: api_resources.checkout.Session, api_resources.CountrySpec.OBJECT_NAME: api_resources.CountrySpec, api_resources.Coupon.OBJECT_NAME: api_resources.Coupon, + api_resources.CreditNote.OBJECT_NAME: api_resources.CreditNote, api_resources.Customer.OBJECT_NAME: api_resources.Customer, api_resources.Dispute.OBJECT_NAME: api_resources.Dispute, api_resources.EphemeralKey.OBJECT_NAME: api_resources.EphemeralKey, diff --git a/tests/api_resources/test_credit_note.py b/tests/api_resources/test_credit_note.py new file mode 100644 index 000000000..c1e954837 --- /dev/null +++ b/tests/api_resources/test_credit_note.py @@ -0,0 +1,60 @@ +from __future__ import absolute_import, division, print_function + +import stripe + + +TEST_RESOURCE_ID = "cn_123" + + +class TestCreditNote(object): + def test_is_listable(self, request_mock): + resources = stripe.CreditNote.list() + request_mock.assert_requested("get", "/v1/credit_notes") + assert isinstance(resources.data, list) + assert isinstance(resources.data[0], stripe.CreditNote) + + def test_is_retrievable(self, request_mock): + resource = stripe.CreditNote.retrieve(TEST_RESOURCE_ID) + request_mock.assert_requested( + "get", "/v1/credit_notes/%s" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.CreditNote) + + def test_is_creatable(self, request_mock): + resource = stripe.CreditNote.create( + amount=100, invoice="in_123", reason="duplicate" + ) + request_mock.assert_requested("post", "/v1/credit_notes") + assert isinstance(resource, stripe.CreditNote) + + def test_is_saveable(self, request_mock): + resource = stripe.CreditNote.retrieve(TEST_RESOURCE_ID) + resource.metadata["key"] = "value" + resource.save() + request_mock.assert_requested( + "post", "/v1/credit_notes/%s" % TEST_RESOURCE_ID + ) + + def test_is_modifiable(self, request_mock): + resource = stripe.CreditNote.modify( + TEST_RESOURCE_ID, metadata={"key": "value"} + ) + request_mock.assert_requested( + "post", "/v1/credit_notes/%s" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.CreditNote) + + def test_can_void_credit_note(self, request_mock): + resource = stripe.CreditNote.retrieve(TEST_RESOURCE_ID) + resource = resource.void_credit_note() + request_mock.assert_requested( + "post", "/v1/credit_notes/%s/void" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.CreditNote) + + def test_can_void_credit_note_classmethod(self, request_mock): + resource = stripe.CreditNote.void_credit_note(TEST_RESOURCE_ID) + request_mock.assert_requested( + "post", "/v1/credit_notes/%s/void" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.CreditNote)