diff --git a/recurly/__init__.py b/recurly/__init__.py
index 9e91faad..f15e963e 100644
--- a/recurly/__init__.py
+++ b/recurly/__init__.py
@@ -41,7 +41,7 @@
API_KEY = None
"""The API key to use when authenticating API requests."""
-API_VERSION = '2.10'
+API_VERSION = '2.11'
"""The API version to use when making API requests."""
CA_CERTS_FILE = None
@@ -147,7 +147,9 @@ class Account(Resource):
'has_active_subscription',
'has_future_subscription',
'has_canceled_subscription',
+ 'has_paused_subscription',
'has_past_due_invoice',
+ 'preferred_locale',
)
_classes_for_nodename = { 'address': Address }
@@ -647,9 +649,12 @@ class Adjustment(Resource):
'updated_at',
'type',
'revenue_schedule_type',
+ 'shipping_address',
+ 'shipping_address_id',
)
xml_attribute_attributes = ('type',)
- _classes_for_nodename = {'tax_detail': TaxDetail,}
+ _classes_for_nodename = {'tax_detail': TaxDetail, 'shipping_address':
+ ShippingAddress}
# This can be removed when the `original_adjustment_uuid` is moved to a link
def __getattr__(self, name):
@@ -866,6 +871,7 @@ class Purchase(Resource):
'customer_notes',
'terms_and_conditions',
'vat_reverse_charge_notes',
+ 'shipping_address_id',
)
def invoice(self):
@@ -983,6 +989,8 @@ class Subscription(Resource):
'converted_at',
'no_billing_info_reason',
'imported_trial',
+ 'remaining_pause_cycles',
+ 'paused_at',
)
sensitive_attributes = ('number', 'verification_value', 'bulk')
@@ -1001,6 +1009,27 @@ def update_notes(self, **kwargs):
url = urljoin(self._url, '%s/notes' % self.uuid)
self.put(url)
+ def pause(self, remaining_pause_cycles):
+ """Pause a subscription"""
+ url = urljoin(self._url, '%s/pause' % self.uuid)
+ elem = ElementTree.Element(self.nodename)
+ elem.append(Resource.element_for_value('remaining_pause_cycles',
+ remaining_pause_cycles))
+ body = ElementTree.tostring(elem, encoding='UTF-8')
+
+ response = self.http_request(url, 'PUT', body, { 'Content-Type':
+ 'application/xml; charset=utf-8' })
+
+ if response.status not in (200, 201, 204):
+ self.raise_http_error(response)
+
+ self.update_from_element(ElementTree.fromstring(response.read()))
+
+ def resume(self):
+ """Resume a subscription"""
+ url = urljoin(self._url, '%s/resume' % self.uuid)
+ self.put(url)
+
def _update(self):
if not hasattr(self, 'timeframe'):
self.timeframe = 'now'
diff --git a/tests/fixtures/account/created.xml b/tests/fixtures/account/created.xml
index 8d836ead..2188f2c5 100644
--- a/tests/fixtures/account/created.xml
+++ b/tests/fixtures/account/created.xml
@@ -9,6 +9,7 @@ Content-Type: application/xml; charset=utf-8
testmock
444444-UK
+ en-US
HTTP/1.1 201 Created
@@ -41,4 +42,5 @@ Location: https://api.recurly.com/v2/accounts/testmock
true
+ en-US
diff --git a/tests/fixtures/purchase/authorized.xml b/tests/fixtures/purchase/authorized.xml
index 40955b82..1b321d70 100644
--- a/tests/fixtures/purchase/authorized.xml
+++ b/tests/fixtures/purchase/authorized.xml
@@ -10,6 +10,18 @@ Content-Type: application/xml; charset=utf-8
testmock
benjamin.dumonde@example.com
+
+
+ 123 Main St
+ New Orleans
+ US
+ Verena
+ Example
+ Work
+ LA
+ 70114
+
+
Verena
Example
diff --git a/tests/fixtures/purchase/invoiced.xml b/tests/fixtures/purchase/invoiced.xml
index ae64b31d..0837e6cb 100644
--- a/tests/fixtures/purchase/invoiced.xml
+++ b/tests/fixtures/purchase/invoiced.xml
@@ -9,6 +9,18 @@ Content-Type: application/xml; charset=utf-8
testmock
+
+
+ 123 Main St
+ New Orleans
+ US
+ Verena
+ Example
+ Work
+ LA
+ 70114
+
+
Verena
Example
@@ -105,6 +117,16 @@ Location: https://api.recurly.com/v2/invoices/1021
2017-10-06T21:25:56Z
2017-10-06T21:25:56Z
evenly
+
+ 123 Main St
+
+ New Orleans
+ LA
+ 70114
+ US
+ Work
+
+
@@ -127,6 +149,16 @@ Location: https://api.recurly.com/v2/invoices/1021
2017-10-06T21:25:56Z
2017-10-06T21:25:56Z
+
+ 123 Main St
+
+ New Orleans
+ LA
+ 70114
+ US
+ Work
+
+
@@ -149,6 +181,16 @@ Location: https://api.recurly.com/v2/invoices/1021
2017-10-06T21:25:56Z
2017-10-06T21:25:56Z
+
+ 123 Main St
+
+ New Orleans
+ LA
+ 70114
+ US
+ Work
+
+
diff --git a/tests/fixtures/purchase/previewed.xml b/tests/fixtures/purchase/previewed.xml
index e8bdfec1..def32c4e 100644
--- a/tests/fixtures/purchase/previewed.xml
+++ b/tests/fixtures/purchase/previewed.xml
@@ -9,6 +9,18 @@ Content-Type: application/xml; charset=utf-8
testmock
+
+
+ 123 Main St
+ New Orleans
+ US
+ Verena
+ Example
+ Work
+ LA
+ 70114
+
+
Verena
Example
diff --git a/tests/fixtures/subscription/pause.xml b/tests/fixtures/subscription/pause.xml
new file mode 100644
index 00000000..f0a481ab
--- /dev/null
+++ b/tests/fixtures/subscription/pause.xml
@@ -0,0 +1,55 @@
+PUT https://api.recurly.com/v2/subscriptions/123456789012345678901234567890ab/pause HTTP/1.1
+X-Api-Version: {api-version}
+Accept: application/xml
+Authorization: Basic YXBpa2V5Og==
+User-Agent: {user-agent}
+Content-Type: application/xml; charset=utf-8
+
+
+
+ 1
+
+
+HTTP/1.1 200 OK
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/subscriptions/123456789012345678901234567890ab
+
+
+
+
+ 123456789012345678901234567890ab
+
+
+ basicplan
+ Basic Plan
+
+ active
+ 1
+ EUR
+ 1000
+ 2011-05-27T07:00:00Z
+
+
+ 2011-06-27T07:00:00Z
+ 2010-07-27T07:00:00Z
+
+
+ 0
+ usst
+ plan_free_trial
+ 2019-07-27T07:00:00Z
+ 1>
+
+
+ usage
+
+
+ marketing_emails
+ 5
+ 1
+ price
+
+
+
+
diff --git a/tests/fixtures/subscription/resume.xml b/tests/fixtures/subscription/resume.xml
new file mode 100644
index 00000000..40785e19
--- /dev/null
+++ b/tests/fixtures/subscription/resume.xml
@@ -0,0 +1,52 @@
+PUT https://api.recurly.com/v2/subscriptions/123456789012345678901234567890ab/resume HTTP/1.1
+X-Api-Version: {api-version}
+Accept: application/xml
+Authorization: Basic YXBpa2V5Og==
+User-Agent: {user-agent}
+Content-Type: application/xml; charset=utf-8
+
+
+
+HTTP/1.1 200 OK
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/subscriptions/123456789012345678901234567890ab
+
+
+
+
+ 123456789012345678901234567890ab
+
+
+ basicplan
+ Basic Plan
+
+ active
+ 1
+ EUR
+ 1000
+ 2011-05-27T07:00:00Z
+
+
+ 2011-06-27T07:00:00Z
+ 2010-07-27T07:00:00Z
+
+
+ 0
+ usst
+ plan_free_trial
+ 2019-07-27T07:00:00Z
+ 1>
+
+
+ usage
+
+
+ marketing_emails
+ 5
+ 1
+ price
+
+
+
+
diff --git a/tests/test_resources.py b/tests/test_resources.py
index 02bd89fd..95b3c477 100644
--- a/tests/test_resources.py
+++ b/tests/test_resources.py
@@ -67,6 +67,18 @@ def test_purchase(self):
currency = 'USD',
account = Account(
account_code = account_code,
+ shipping_addresses = [
+ ShippingAddress(
+ first_name = 'Verena',
+ last_name = 'Example',
+ address1 = '123 Main St',
+ city = 'New Orleans',
+ state = 'LA',
+ zip = '70114',
+ country = 'US',
+ nickname = 'Work'
+ )
+ ],
billing_info = BillingInfo(
first_name = 'Verena',
last_name = 'Example',
@@ -97,6 +109,8 @@ def test_purchase(self):
self.assertIsInstance(collection.charge_invoice, Invoice)
self.assertIsInstance(collection.credit_invoices, list)
self.assertIsInstance(collection.credit_invoices[0], Invoice)
+ self.assertIsInstance(collection.charge_invoice.line_items[0].shipping_address,
+ ShippingAddress)
with self.mock_request('purchase/previewed.xml'):
collection = purchase.preview()
self.assertIsInstance(collection, InvoiceCollection)
@@ -115,6 +129,7 @@ def test_account(self):
account = Account(account_code=account_code)
account.vat_number = '444444-UK'
+ account.preferred_locale = 'en-US'
with self.mock_request('account/created.xml'):
account.save()
self.assertEqual(account._url, urljoin(recurly.base_uri(), 'accounts/%s' % account_code))
@@ -122,6 +137,7 @@ def test_account(self):
self.assertEqual(account.vat_location_enabled, True)
self.assertEqual(account.cc_emails,
'test1@example.com,test2@example.com')
+ self.assertEqual(account.preferred_locale, 'en-US')
with self.mock_request('account/list-active.xml'):
active = Account.all_active()
@@ -1172,6 +1188,19 @@ def test_measured_unit(self):
self.assertEqual(measured_unit.description, 'Unit of Marketing Email')
self.assertEqual(measured_unit.id, 123456)
+ def test_subscription_pause_resume(self):
+ with self.mock_request('subscription/show.xml'):
+ sub = Subscription.get('123456789012345678901234567890ab')
+
+ with self.mock_request('subscription/pause.xml'):
+ sub.pause(1)
+
+ self.assertIsInstance(sub.paused_at, datetime)
+ self.assertEqual(sub.remaining_pause_cycles, 1)
+
+ with self.mock_request('subscription/resume.xml'):
+ sub.resume()
+
def test_usage(self):
usage = Usage()
usage.amount = 100 # record 100 emails