From f4e1b858c7a39563cfaaca29b0ca94b08d533672 Mon Sep 17 00:00:00 2001 From: Judith Hengeveld Date: Tue, 22 Nov 2022 08:57:45 -0800 Subject: [PATCH] V2 add support for Apply Credit Balance to existing invoice feature Add new available_credit_balance_in_cents attribute to AccountBalance. The available_credit_balance_in_cents attribute is a similar format to the balance_in_cents attribute and contains the total of open balances for credit invoices in each currency. This value is useful when trying to determine if the customer's account has any available credit that can be applied to an existing collectible invoice on the account. Add new apply_credit_balance method to Invoice. This action will be available for collectible charge invoices. If the account has available credit it will be applied to pay down the balance on the invoice. --- recurly/__init__.py | 11 +++ tests/fixtures/account-balance/exists.xml | 4 ++ .../fixtures/invoice/apply-credit-balance.xml | 70 +++++++++++++++++++ tests/fixtures/invoice/show-invoice.xml | 1 + tests/test_resources.py | 11 +++ 5 files changed, 97 insertions(+) create mode 100644 tests/fixtures/invoice/apply-credit-balance.xml diff --git a/recurly/__init__.py b/recurly/__init__.py index bee7dcf1..88a7ac74 100644 --- a/recurly/__init__.py +++ b/recurly/__init__.py @@ -115,6 +115,7 @@ class AccountBalance(Resource): attributes = ( 'balance_in_cents', 'processing_prepayment_balance_in_cents', + 'available_credit_balance_in_cents', 'past_due', ) @@ -1140,6 +1141,16 @@ def force_collect(self, options={}): invoice_collection = InvoiceCollection.from_element(elem) return invoice_collection + def apply_credit_balance(self): + url = urljoin(self._url, '/apply_credit_balance') + response = self.http_request(url, 'PUT') + if response.status not in (200, 201): + self.raise_http_error(response) + response_xml = response.read() + elem = ElementTree.fromstring(response_xml) + invoice = Invoice.from_element(elem) + return invoice + def _create_refund_invoice(self, element): url = urljoin(self._url, '/refund') body = ElementTree.tostring(element, encoding='UTF-8') diff --git a/tests/fixtures/account-balance/exists.xml b/tests/fixtures/account-balance/exists.xml index edd6abd9..e0fe8a69 100644 --- a/tests/fixtures/account-balance/exists.xml +++ b/tests/fixtures/account-balance/exists.xml @@ -20,4 +20,8 @@ Content-Type: application/xml; charset=utf-8 -3000 0 + + -3000 + 0 + diff --git a/tests/fixtures/invoice/apply-credit-balance.xml b/tests/fixtures/invoice/apply-credit-balance.xml new file mode 100644 index 00000000..004d5e7e --- /dev/null +++ b/tests/fixtures/invoice/apply-credit-balance.xml @@ -0,0 +1,70 @@ +PUT https://api.recurly.com/v2/invoices/6019/apply_credit_balance HTTP/1.1 +X-Api-Version: {api-version} +Accept: application/xml +Authorization: Basic YXBpa2V5Og== +User-Agent: {user-agent} +Content-Length: 0 + + +HTTP/1.1 200 OK +Content-Type: application/xml; charset=utf-8 +Location: https://api.recurly.com/v2/invoices/6019 + + + + +
+ + + + + + + +
+ 46036dca820357dae40c94420ab52632 + paid + + 6019 + + 0 + 5000 + USD + 2018-07-13T17:13:57Z + 2018-07-13T17:13:57Z + + 2019-07-13T17:13:57Z + notes + + 0 + manual + + + + + 46036dc9823500f96f43ef44769df449 + invoiced + Charge for extra bandwidth + bandwidth + + debit + 5000 + 1 + 0 + 0 + 5000 + USD + false + false + + 2018-07-13T17:13:57Z + + 2018-07-13T17:13:57Z + 2018-07-13T17:13:57Z + + + + + + +
diff --git a/tests/fixtures/invoice/show-invoice.xml b/tests/fixtures/invoice/show-invoice.xml index 235b7a6e..f8a38126 100644 --- a/tests/fixtures/invoice/show-invoice.xml +++ b/tests/fixtures/invoice/show-invoice.xml @@ -91,4 +91,5 @@ Location: https://api.recurly.com/v2/invoices/6019 + diff --git a/tests/test_resources.py b/tests/test_resources.py index 1e8b8648..2b4fea90 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -336,6 +336,9 @@ def test_account(self): processing_prepayment_balance = account_balance.processing_prepayment_balance_in_cents self.assertTrue(processing_prepayment_balance['USD'] == -3000) self.assertTrue(processing_prepayment_balance['EUR'] == 0) + available_credit_balance_in_cents = account_balance.available_credit_balance_in_cents + self.assertTrue(available_credit_balance_in_cents['USD'] == -3000) + self.assertTrue(available_credit_balance_in_cents['EUR'] == 0) account.username = 'shmohawk58' account.email = 'larry.david' @@ -1397,6 +1400,14 @@ def test_invoice_collect(self): collection = invoice.force_collect() self.assertIsInstance(collection, InvoiceCollection) + def test_apply_credit_balance(self): + with self.mock_request('invoice/show-invoice.xml'): + invoice = Invoice.get("6019") + + with self.mock_request('invoice/apply-credit-balance.xml'): + updated_invoice = invoice.apply_credit_balance() + self.assertIsInstance(updated_invoice, Invoice) + def test_invoice_tax_details(self): with self.mock_request('invoice/show-invoice.xml'): invoice = Invoice.get("6019")