From be39812ce414b26f6513c63c14e3f4b8f0500c7b Mon Sep 17 00:00:00 2001 From: Chris Barton Date: Thu, 9 Jan 2014 17:57:13 -0800 Subject: [PATCH 1/4] Adding tax attributes to the resources --- recurly/__init__.py | 7 +++- tests/fixtures/account/show-taxed.xml | 25 +++++++++++++++ tests/fixtures/adjustment/show-taxed.xml | 23 ++++++++++++++ tests/fixtures/invoice/show-taxed.xml | 25 +++++++++++++++ tests/fixtures/plan/show-taxed.xml | 34 ++++++++++++++++++++ tests/fixtures/subscription/show-taxed.xml | 37 ++++++++++++++++++++++ tests/test_resources.py | 26 +++++++++++++++ 7 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/account/show-taxed.xml create mode 100644 tests/fixtures/adjustment/show-taxed.xml create mode 100644 tests/fixtures/invoice/show-taxed.xml create mode 100644 tests/fixtures/plan/show-taxed.xml create mode 100644 tests/fixtures/subscription/show-taxed.xml diff --git a/recurly/__init__.py b/recurly/__init__.py index 00ab5d81..c9fc57cb 100644 --- a/recurly/__init__.py +++ b/recurly/__init__.py @@ -79,6 +79,7 @@ class Account(Resource): 'last_name', 'company_name', 'vat_number', + 'tax_exempt', 'accept_language', 'created_at', ) @@ -369,7 +370,7 @@ class Adjustment(Resource): 'tax_in_cents', 'total_in_cents', 'currency', - 'taxable', + 'tax_exempt', 'start_date', 'end_date', 'created_at', @@ -396,6 +397,7 @@ class Invoice(Resource): 'vat_number', 'subtotal_in_cents', 'tax_in_cents', + 'tax_type', 'total_in_cents', 'currency', 'created_at', @@ -479,6 +481,8 @@ class Subscription(Resource): 'trial_started_at', 'trial_ends_at', 'unit_amount_in_cents', + 'tax_in_cents', + 'tax_type', 'total_billing_cycles', 'timeframe', 'currency', @@ -617,6 +621,7 @@ class Plan(Resource): 'trial_interval_unit', 'accounting_code', 'created_at', + 'tax_exempt', 'unit_amount_in_cents', 'setup_fee_in_cents', ) diff --git a/tests/fixtures/account/show-taxed.xml b/tests/fixtures/account/show-taxed.xml new file mode 100644 index 00000000..384dd4e6 --- /dev/null +++ b/tests/fixtures/account/show-taxed.xml @@ -0,0 +1,25 @@ +GET https://api.recurly.com/v2/accounts/testmock HTTP/1.1 +Accept: application/xml +Authorization: Basic YXBpa2V5Og== +User-Agent: recurly-python/{version} + + +HTTP/1.1 200 OK +Content-Type: application/xml; charset=utf-8 + + + + + + + + + testmock + + + + + + + true + diff --git a/tests/fixtures/adjustment/show-taxed.xml b/tests/fixtures/adjustment/show-taxed.xml new file mode 100644 index 00000000..d08d661f --- /dev/null +++ b/tests/fixtures/adjustment/show-taxed.xml @@ -0,0 +1,23 @@ +GET https://api.recurly.com/v2/accounts/chargemock/adjustments HTTP/1.1 +Accept: application/xml +Authorization: Basic YXBpa2V5Og== +User-Agent: recurly-python/{version} + + +HTTP/1.1 200 OK +Content-Type: application/xml; charset=utf-8 +X-Records: 1 + + + + 4ba1531325014b4f969cd13676f514d8 + test charge + chargemock + 1000 + USD + false + 2009-11-03T23:27:46Z + + 2009-11-03T23:27:46Z + + diff --git a/tests/fixtures/invoice/show-taxed.xml b/tests/fixtures/invoice/show-taxed.xml new file mode 100644 index 00000000..cfe363c8 --- /dev/null +++ b/tests/fixtures/invoice/show-taxed.xml @@ -0,0 +1,25 @@ +GET https://api.recurly.com/v2/accounts/invoicemock/invoices HTTP/1.1 +Accept: application/xml +Authorization: Basic YXBpa2V5Og== +User-Agent: recurly-python/{version} + + +HTTP/1.1 200 OK +X-Records: 1 +Content-Type: application/xml; charset=utf-8 + + + + + 4ba1531325014b4f969cd13676f514d8 + invoicemock + + 1000 + + 2009-11-03T23:27:46-08:00 + + test charge + 2009-11-03T23:27:46-08:00 + usst + + diff --git a/tests/fixtures/plan/show-taxed.xml b/tests/fixtures/plan/show-taxed.xml new file mode 100644 index 00000000..929929a2 --- /dev/null +++ b/tests/fixtures/plan/show-taxed.xml @@ -0,0 +1,34 @@ +GET https://api.recurly.com/v2/plans/planmock HTTP/1.1 +Accept: application/xml +Authorization: Basic YXBpa2V5Og== +User-Agent: recurly-python/{version} + + +HTTP/1.1 200 OK +Content-Type: application/xml; charset=utf-8 + + + + + planmock + Mock Plan + + + + false + false + false + false + unit + + 1 + months + 0 + days + 2011-10-03T22:23:12Z + true + + + + + diff --git a/tests/fixtures/subscription/show-taxed.xml b/tests/fixtures/subscription/show-taxed.xml new file mode 100644 index 00000000..750b5544 --- /dev/null +++ b/tests/fixtures/subscription/show-taxed.xml @@ -0,0 +1,37 @@ +GET https://api.recurly.com/v2/accounts/subscribemock/subscriptions HTTP/1.1 +Accept: application/xml +Authorization: Basic YXBpa2V5Og== +User-Agent: recurly-python/{version} + + +HTTP/1.1 200 OK +X-Records: 1 +Content-Type: application/xml; charset=utf-8 + + + + + 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 + + + + diff --git a/tests/test_resources.py b/tests/test_resources.py index 91d47ca8..4271b805 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -135,6 +135,11 @@ def test_account(self): self.assertEqual(account.address.country, 'US') self.assertEqual(account.address.phone, '8015559876') + """Get taxed account""" + with self.mock_request('account/show-taxed.xml'): + account = Account.get(account_code) + self.assertTrue(account.tax_exempt) + def test_add_on(self): plan_code = 'plan%s' % self.test_id @@ -336,6 +341,11 @@ def test_charge(self): with self.mock_request('adjustment/account-deleted.xml'): account.delete() + """Test taxed adjustments""" + with self.mock_request('adjustment/show-taxed.xml'): + charge = account.adjustments()[0] + self.assertFalse(charge.tax_exempt) + def test_coupon(self): # Check that a coupon may not exist. coupon_code = 'coupon%s' % self.test_id @@ -507,6 +517,11 @@ def test_invoice(self): with self.mock_request('invoice/account-deleted.xml'): account.delete() + """Test taxed invoice""" + with self.mock_request('invoice/show-taxed.xml'): + invoice = account.invoices()[0] + self.assertEqual(invoice.tax_type, 'usst') + def test_pages(self): account_code = 'pages-%s-%%d' % self.test_id all_test_accounts = list() @@ -577,6 +592,11 @@ def test_plan(self): with self.mock_request('plan/deleted.xml'): plan.delete() + """Test taxed plan""" + with self.mock_request('plan/show-taxed.xml'): + plan = Plan.get(plan_code) + self.assertTrue(plan.tax_exempt) + def test_subscribe(self): logging.basicConfig(level=logging.DEBUG) # make sure it's init'ed logger = logging.getLogger('recurly.http.request') @@ -752,6 +772,12 @@ def test_subscribe(self): with self.mock_request('subscription/plan-deleted.xml'): plan.delete() + """Test taxed subscription""" + with self.mock_request('subscription/show-taxed.xml'): + sub = account.subscriptions()[0] + self.assertEqual(sub.tax_in_cents, 0) + self.assertEqual(sub.tax_type, 'usst') + def test_subscribe_add_on(self): plan = Plan( plan_code='basicplan', From 9564d1e6c2defbba89dadbfcc0dc04e151117008 Mon Sep 17 00:00:00 2001 From: Chris Barton Date: Thu, 30 Jan 2014 16:11:09 -0800 Subject: [PATCH 2/4] Add tax details to adjustments --- recurly/__init__.py | 15 +++++++++++++++ recurly/resource.py | 2 ++ .../adjustment/account-has-adjustments.xml | 15 +++++++++++++++ tests/test_resources.py | 15 +++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/recurly/__init__.py b/recurly/__init__.py index c9fc57cb..f251be66 100644 --- a/recurly/__init__.py +++ b/recurly/__init__.py @@ -352,6 +352,19 @@ class Redemption(Resource): 'created_at', ) +class TaxDetail(Resource): + + """A charge's tax breakdown""" + + nodename = 'taxdetail' + inherits_currency = True + + attributes = ( + 'name', + 'type', + 'tax_rate', + 'tax_in_cents', + ) class Adjustment(Resource): @@ -371,12 +384,14 @@ class Adjustment(Resource): 'total_in_cents', 'currency', 'tax_exempt', + 'tax_details', 'start_date', 'end_date', 'created_at', 'type', ) xml_attribute_attributes = ('type',) + _classes_for_nodename = {'tax_detail': TaxDetail,} class Invoice(Resource): diff --git a/recurly/resource.py b/recurly/resource.py index 6131f8c3..e4772d9b 100644 --- a/recurly/resource.py +++ b/recurly/resource.py @@ -405,6 +405,8 @@ def value_for_element(cls, elem): log.debug("Converting %r element with type %r", elem.tag, attr_type) if attr_type == 'integer': return int(elem.text.strip()) + if attr_type == 'float': + return float(elem.text.strip()) if attr_type == 'boolean': return elem.text.strip() == 'true' if attr_type == 'datetime': diff --git a/tests/fixtures/adjustment/account-has-adjustments.xml b/tests/fixtures/adjustment/account-has-adjustments.xml index 94c5c320..7956b843 100644 --- a/tests/fixtures/adjustment/account-has-adjustments.xml +++ b/tests/fixtures/adjustment/account-has-adjustments.xml @@ -13,8 +13,23 @@ X-Records: 1 4ba1531325014b4f969cd13676f514d8 test charge chargemock + 5000 1000 USD + + + california + state + 0.065 + 3000 + + + san francisco + county + 0.02 + 2000 + + 2009-11-03T23:27:46Z 2009-11-03T23:27:46Z diff --git a/tests/test_resources.py b/tests/test_resources.py index 4271b805..36522a4d 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -325,10 +325,25 @@ def test_charge(self): self.assertEqual(len(charges), 1) same_charge = charges[0] self.assertEqual(same_charge.unit_amount_in_cents, 1000) + self.assertEqual(same_charge.tax_in_cents, 5000) self.assertEqual(same_charge.currency, 'USD') self.assertEqual(same_charge.description, 'test charge') self.assertEqual(same_charge.type, 'charge') + tax_details = same_charge.tax_details + state, county = tax_details + + self.assertEqual(len(tax_details), 2) + self.assertEqual(state.name, 'california') + self.assertEqual(state.type, 'state') + self.assertEqual(state.tax_rate, 0.065) + self.assertEqual(state.tax_in_cents, 3000) + + self.assertEqual(county.name, 'san francisco') + self.assertEqual(county.type, 'county') + self.assertEqual(county.tax_rate, 0.02) + self.assertEqual(county.tax_in_cents, 2000) + with self.mock_request('adjustment/account-has-charges.xml'): charges = account.adjustments(type='charge') self.assertEqual(len(charges), 1) From 3137429c9126aa0c99c378d6d53b1f31131971fa Mon Sep 17 00:00:00 2001 From: Chris Barton Date: Mon, 3 Feb 2014 10:57:33 -0800 Subject: [PATCH 3/4] Adding tax_rate to subscriptions and invoices --- recurly/__init__.py | 2 ++ tests/fixtures/subscription/show.xml | 37 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/fixtures/subscription/show.xml diff --git a/recurly/__init__.py b/recurly/__init__.py index f251be66..995af6e5 100644 --- a/recurly/__init__.py +++ b/recurly/__init__.py @@ -413,6 +413,7 @@ class Invoice(Resource): 'subtotal_in_cents', 'tax_in_cents', 'tax_type', + 'tax_rate', 'total_in_cents', 'currency', 'created_at', @@ -498,6 +499,7 @@ class Subscription(Resource): 'unit_amount_in_cents', 'tax_in_cents', 'tax_type', + 'tax_rate', 'total_billing_cycles', 'timeframe', 'currency', diff --git a/tests/fixtures/subscription/show.xml b/tests/fixtures/subscription/show.xml new file mode 100644 index 00000000..750b5544 --- /dev/null +++ b/tests/fixtures/subscription/show.xml @@ -0,0 +1,37 @@ +GET https://api.recurly.com/v2/accounts/subscribemock/subscriptions HTTP/1.1 +Accept: application/xml +Authorization: Basic YXBpa2V5Og== +User-Agent: recurly-python/{version} + + +HTTP/1.1 200 OK +X-Records: 1 +Content-Type: application/xml; charset=utf-8 + + + + + 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 + + + + From d5287311cbf41edb6574e82197afb0d79b980e7f Mon Sep 17 00:00:00 2001 From: Chris Barton Date: Mon, 3 Feb 2014 18:03:11 -0800 Subject: [PATCH 4/4] bump to 2.2.0 --- CHANGELOG | 9 +++++++++ recurly/__init__.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index f7909111..f7631084 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +## Version 2.2.0 May 14, 2014 + +- Added subscription preview: `subscription.preview()` +- Added tax details to adjustments: `adjustment.tax_details` +- Removed `taxable` support on adjustments +- Added `tax_exempt` to accounts, adjustments and plans +- Added `tax_rate`, `tax_type` to invoices and subscriptions +- Added `tax_in_cents` to subscriptions + ## Version 2.1.15 April 8, 2014 - Added token_id support to BillingInfo diff --git a/recurly/__init__.py b/recurly/__init__.py index 995af6e5..a6792367 100644 --- a/recurly/__init__.py +++ b/recurly/__init__.py @@ -18,7 +18,7 @@ """ -__version__ = '2.1.15' +__version__ = '2.2.0' BASE_URI = 'https://%s.recurly.com/v2/' """The API endpoint to send requests to."""