diff --git a/recurly/__init__.py b/recurly/__init__.py
index 6aba554e..45c5d9c9 100644
--- a/recurly/__init__.py
+++ b/recurly/__init__.py
@@ -792,7 +792,8 @@ class GiftCard(Resource):
'billing_info',
'liability_gl_account_id',
'revenue_gl_account_id',
- 'performance_obligation_id'
+ 'performance_obligation_id',
+ 'tax_service_opt_out'
)
_classes_for_nodename = {'recipient_account': Account,'gifter_account':
Account, 'delivery': Delivery}
diff --git a/tests/fixtures/gift_cards/created-with-tax-service-opt-out-false.xml b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-false.xml
new file mode 100644
index 00000000..0a25e168
--- /dev/null
+++ b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-false.xml
@@ -0,0 +1,82 @@
+POST https://api.recurly.com/v2/gift_cards 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
+
+
+
+ USD
+
+
+ 400 Alabama St
+ San Francisco
+ US
+ CA
+ 94110
+
+ john@email.com
+ John
+ Smith
+ email
+
+
+ e0004e3c-216c-4254-8767-9be605cd0b03
+ verena@example.com
+ Verena
+ Example
+
+ US
+ USD
+ Verena
+ Example
+ 11
+ 4111-1111-1111-1111
+ 123
+ 2019
+
+
+ test_gift_card
+ false
+ 2000
+
+
+HTTP/1.1 201 Created
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/gift_cards/2018434791876074812
+
+
+
+
+
+ 2018434791876074812
+ 9FC359369CD3892E
+ test_gift_card
+ 2000
+ USD
+
+ email
+ john@email.com
+
+
+
+
+ 400 Alabama St
+
+ San Francisco
+ CA
+ 94110
+ US
+
+
+
+
+
+ 2016-08-16T21:49:37Z
+ 2016-08-16T21:49:37Z
+
+
+
+
+
diff --git a/tests/fixtures/gift_cards/created-with-tax-service-opt-out-invalid.xml b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-invalid.xml
new file mode 100644
index 00000000..5320dbe6
--- /dev/null
+++ b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-invalid.xml
@@ -0,0 +1,52 @@
+POST https://api.recurly.com/v2/gift_cards 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
+
+
+
+ USD
+
+
+ 400 Alabama St
+ San Francisco
+ US
+ CA
+ 94110
+
+ john@email.com
+ John
+ Smith
+ email
+
+
+ e0004e3c-216c-4254-8767-9be605cd0b03
+ verena@example.com
+ Verena
+ Example
+
+ US
+ USD
+ Verena
+ Example
+ 11
+ 4111-1111-1111-1111
+ 123
+ 2019
+
+
+ test_gift_card
+ invalid
+ 2000
+
+
+HTTP/1.1 422 Unprocessable Entity
+Content-Type: application/xml; charset=utf-8
+
+
+
+ tax_service_opt_out
+ Allowed values: true, false
+
diff --git a/tests/fixtures/gift_cards/created-with-tax-service-opt-out-legacy-site.xml b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-legacy-site.xml
new file mode 100644
index 00000000..d5bce600
--- /dev/null
+++ b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-legacy-site.xml
@@ -0,0 +1,52 @@
+POST https://api.recurly.com/v2/gift_cards 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
+
+
+
+ USD
+
+
+ 400 Alabama St
+ San Francisco
+ US
+ CA
+ 94110
+
+ john@email.com
+ John
+ Smith
+ email
+
+
+ e0004e3c-216c-4254-8767-9be605cd0b03
+ verena@example.com
+ Verena
+ Example
+
+ US
+ USD
+ Verena
+ Example
+ 11
+ 4111-1111-1111-1111
+ 123
+ 2019
+
+
+ test_gift_card
+ true
+ 2000
+
+
+HTTP/1.1 422 Unprocessable Entity
+Content-Type: application/xml; charset=utf-8
+
+
+
+ tax_service_opt_out
+ Not supported for legacy invoices
+
diff --git a/tests/fixtures/gift_cards/created-with-tax-service-opt-out-true.xml b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-true.xml
new file mode 100644
index 00000000..9cacb387
--- /dev/null
+++ b/tests/fixtures/gift_cards/created-with-tax-service-opt-out-true.xml
@@ -0,0 +1,82 @@
+POST https://api.recurly.com/v2/gift_cards 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
+
+
+
+ USD
+
+
+ 400 Alabama St
+ San Francisco
+ US
+ CA
+ 94110
+
+ john@email.com
+ John
+ Smith
+ email
+
+
+ e0004e3c-216c-4254-8767-9be605cd0b03
+ verena@example.com
+ Verena
+ Example
+
+ US
+ USD
+ Verena
+ Example
+ 11
+ 4111-1111-1111-1111
+ 123
+ 2019
+
+
+ test_gift_card
+ true
+ 2000
+
+
+HTTP/1.1 201 Created
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/gift_cards/2018434791876074812
+
+
+
+
+
+ 2018434791876074812
+ 9FC359369CD3892E
+ test_gift_card
+ 2000
+ USD
+
+ email
+ john@email.com
+
+
+
+
+ 400 Alabama St
+
+ San Francisco
+ CA
+ 94110
+ US
+
+
+
+
+
+ 2016-08-16T21:49:37Z
+ 2016-08-16T21:49:37Z
+
+
+
+
+
diff --git a/tests/test_resources.py b/tests/test_resources.py
index 9d28f14d..df5cb392 100644
--- a/tests/test_resources.py
+++ b/tests/test_resources.py
@@ -570,16 +570,16 @@ def test_charge_with_vertex_transaction_type(self):
type='charge',
vertex_transaction_type='sale'
)
-
+
with self.mock_request('adjustment/charged-with-vertex-transaction-type.xml'):
account.charge(charge)
-
+
# Verify the charge was created with vertex_transaction_type
self.assertEqual(charge.vertex_transaction_type, 'sale')
def test_purchase_with_invoice_override_vertex_transaction_type(self):
"""Test that invoice-level vertex_transaction_type overrides adjustment-level values.
-
+
This demonstrates the override behavior where an invoice can have its own
vertex_transaction_type that takes precedence over the individual adjustment values.
"""
@@ -596,16 +596,16 @@ def test_purchase_with_invoice_override_vertex_transaction_type(self):
],
vertex_transaction_type='rental' # Invoice-level value (should override)
)
-
+
with self.mock_request('purchase/invoiced-with-invoice-override-vertex-type.xml'):
invoice_collection = purchase.invoice()
-
+
invoice = invoice_collection.charge_invoice
adjustments = invoice.line_items
-
+
# Verify the invoice has the invoice-level vertex_transaction_type
self.assertEqual(invoice.vertex_transaction_type, 'rental')
-
+
# The adjustment still has its own value (API preserves both)
# but the invoice-level value is what gets used for tax calculation
self.assertEqual(adjustments[0].vertex_transaction_type, 'sale')
@@ -3454,6 +3454,62 @@ def test_gift_cards_purchase(self):
self.assertTrue(gift_card.delivery is not None)
self.assertTrue(gift_card.canceled_at is None)
+ def test_gift_cards_purchase_with_tax_service_opt_out_true(self):
+ gift_card = self._build_gift_card()
+ gift_card.tax_service_opt_out = True
+
+ self.assertFalse('_url' in gift_card.attributes)
+
+ with self.mock_request('gift_cards/created-with-tax-service-opt-out-true.xml'):
+ gift_card.save()
+
+ self.assertTrue(gift_card._url is not None)
+ self.assertTrue(gift_card.delivery is not None)
+ self.assertTrue(gift_card.canceled_at is None)
+
+ def test_gift_cards_purchase_with_tax_service_opt_out_false(self):
+ gift_card = self._build_gift_card()
+ gift_card.tax_service_opt_out = False
+
+ self.assertFalse('_url' in gift_card.attributes)
+
+ with self.mock_request('gift_cards/created-with-tax-service-opt-out-false.xml'):
+ gift_card.save()
+
+ self.assertTrue(gift_card._url is not None)
+ self.assertTrue(gift_card.delivery is not None)
+ self.assertTrue(gift_card.canceled_at is None)
+
+ def test_gift_cards_purchase_with_tax_service_opt_out_invalid(self):
+ gift_card = self._build_gift_card()
+ gift_card.tax_service_opt_out = 'invalid'
+
+ self.assertFalse('_url' in gift_card.attributes)
+
+ with self.mock_request('gift_cards/created-with-tax-service-opt-out-invalid.xml'):
+ try:
+ gift_card.save()
+ except ValidationError as exc:
+ error = exc
+ else:
+ self.fail('Creating a gift card with invalid tax_service_opt_out did not raise a ValidationError')
+ self.assertEqual(error.symbol, 'tax_service_opt_out')
+ self.assertIn('Allowed values: true, false', error.message)
+
+ def test_gift_cards_purchase_with_tax_service_opt_out_legacy_site(self):
+ gift_card = self._build_gift_card()
+ gift_card.tax_service_opt_out = True
+
+ with self.mock_request('gift_cards/created-with-tax-service-opt-out-legacy-site.xml'):
+ try:
+ gift_card.save()
+ except ValidationError as exc:
+ error = exc
+ else:
+ self.fail('Creating a gift card with tax_service_opt_out on legacy site did not raise a ValidationError')
+ self.assertEqual(error.symbol, 'tax_service_opt_out')
+ self.assertIn('Not supported for legacy invoices', error.message)
+
def test_gift_cards_preview(self):
gift_card = self._build_gift_card()