diff --git a/stripe/api_resources/customer.py b/stripe/api_resources/customer.py index 4b78fcdca..6ca340e4c 100644 --- a/stripe/api_resources/customer.py +++ b/stripe/api_resources/customer.py @@ -23,11 +23,6 @@ http_verb="get", http_path="payment_methods", ) -@nested_resource_class_methods( - "cash_balance", - operations=["retrieve", "update"], - resource_plural="cash_balance", -) @nested_resource_class_methods( "balance_transaction", operations=["create", "retrieve", "update", "list"], @@ -120,3 +115,47 @@ def delete_discount(self, **params): url = self.instance_url() + "/discount" _, api_key = requestor.request("delete", url, params) self.refresh_from({"discount": None}, api_key, True) + + @classmethod + def retrieve_cash_balance( + cls, + customer, + nested_id=None, + api_key=None, + stripe_version=None, + stripe_account=None, + **params + ): + # The nested_id parameter is required for backwards compatibility purposes and is ignored. + requestor = api_requestor.APIRequestor( + api_key, api_version=stripe_version, account=stripe_account + ) + url = "/v1/customers/{customer}/cash_balance".format( + customer=util.sanitize_id(customer) + ) + response, api_key = requestor.request("get", url, params) + return util.convert_to_stripe_object( + response, api_key, stripe_version, stripe_account + ) + + @classmethod + def modify_cash_balance( + cls, + customer, + nested_id=None, + api_key=None, + stripe_version=None, + stripe_account=None, + **params + ): + # The nested_id parameter is required for backwards compatibility purposes and is ignored. + requestor = api_requestor.APIRequestor( + api_key, api_version=stripe_version, account=stripe_account + ) + url = "/v1/customers/{customer}/cash_balance".format( + customer=util.sanitize_id(customer) + ) + response, api_key = requestor.request("post", url, params) + return util.convert_to_stripe_object( + response, api_key, stripe_version, stripe_account + ) diff --git a/tests/api_resources/test_customer.py b/tests/api_resources/test_customer.py index 2b5d1aa33..7af265cae 100644 --- a/tests/api_resources/test_customer.py +++ b/tests/api_resources/test_customer.py @@ -188,3 +188,42 @@ def test_is_listable_on_object(self, request_mock): "get", "/v1/customers/%s/payment_methods" % TEST_RESOURCE_ID ) assert isinstance(resource, stripe.ListObject) + + +class TestCustomerCashBalanceMethods(object): + # These tests are present for compatibility purposes. Previously the cash + # balance methods required None as a second nested_id parameter. The method + # has been patched to no longer require this, but we want to preserve + # compatibility for existing users. + def test_customer_cashbalance_retrieve_legacy_call_pattern( + self, request_mock + ): + stripe.Customer.retrieve_cash_balance("cus_123", None) + request_mock.assert_requested( + "get", "/v1/customers/cus_123/cash_balance" + ) + + def test_customer_cashbalance_modify_legacy_call_pattern( + self, request_mock + ): + stripe.Customer.modify_cash_balance( + "cus_123", + None, + settings={"reconciliation_mode": "manual"}, + ) + request_mock.assert_requested( + "post", + "/v1/customers/cus_123/cash_balance", + {"settings": {"reconciliation_mode": "manual"}}, + ) + + def test_customer_cashbalance_modify_fixed_pattern(self, request_mock): + stripe.Customer.modify_cash_balance( + "cus_123", + settings={"reconciliation_mode": "manual"}, + ) + request_mock.assert_requested( + "post", + "/v1/customers/cus_123/cash_balance", + {"settings": {"reconciliation_mode": "manual"}}, + ) diff --git a/tests/test_generated_examples.py b/tests/test_generated_examples.py index a8d20239e..47739f613 100644 --- a/tests/test_generated_examples.py +++ b/tests/test_generated_examples.py @@ -352,6 +352,21 @@ def test_apps_secret_delete_where(self, request_mock): ) request_mock.assert_requested("post", "/v1/apps/secrets/delete") + def test_customer_cashbalance_retrieve(self, request_mock): + stripe.Customer.retrieve_cash_balance("cus_123") + request_mock.assert_requested( + "get", "/v1/customers/cus_123/cash_balance" + ) + + def test_customer_cashbalance_update(self, request_mock): + stripe.Customer.modify_cash_balance( + "cus_123", + settings={"reconciliation_mode": "manual"}, + ) + request_mock.assert_requested( + "post", "/v1/customers/cus_123/cash_balance" + ) + def test_customer_list(self, request_mock): stripe.Customer.list(limit=3) request_mock.assert_requested("get", "/v1/customers")