diff --git a/recurly/__init__.py b/recurly/__init__.py
index deea2b07..8469e602 100644
--- a/recurly/__init__.py
+++ b/recurly/__init__.py
@@ -1055,6 +1055,7 @@ class Adjustment(Resource):
'revenue_gl_account_code',
'revenue_gl_account_id',
'performance_obligation_id',
+ 'vertex_transaction_type',
)
xml_attribute_attributes = ('type',)
_classes_for_nodename = {
@@ -1138,7 +1139,8 @@ class Invoice(Resource):
'billing_info_uuid',
'dunning_campaign_id',
'refundable_in_cents',
- 'used_tax_service'
+ 'used_tax_service',
+ 'vertex_transaction_type',
)
blacklist_attributes = (
@@ -1406,6 +1408,7 @@ class Purchase(Resource):
'transaction_type',
'billing_info_uuid',
'ramp_intervals',
+ 'vertex_transaction_type',
)
def invoice(self):
diff --git a/tests/fixtures/adjustment/charged-with-vertex-transaction-type.xml b/tests/fixtures/adjustment/charged-with-vertex-transaction-type.xml
new file mode 100644
index 00000000..19f6ae39
--- /dev/null
+++ b/tests/fixtures/adjustment/charged-with-vertex-transaction-type.xml
@@ -0,0 +1,31 @@
+POST https://api.recurly.com/v2/accounts/chargemock/adjustments 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
+ test charge
+ 1000
+ sale
+
+
+HTTP/1.1 201 Created
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/adjustments/4ba1531325014b4f969cd13676f514d8
+
+
+
+ 4ba1531325014b4f969cd13676f514d8
+ chargemock
+ 1000
+ USD
+ 2009-11-03T23:27:46-08:00
+
+ test charge
+ sale
+ 2009-11-03T23:27:46-08:00
+
diff --git a/tests/fixtures/purchase/invoiced-with-invoice-override-vertex-type.xml b/tests/fixtures/purchase/invoiced-with-invoice-override-vertex-type.xml
new file mode 100644
index 00000000..e0ff6dc3
--- /dev/null
+++ b/tests/fixtures/purchase/invoiced-with-invoice-override-vertex-type.xml
@@ -0,0 +1,184 @@
+POST https://api.recurly.com/v2/purchases 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
+
+
+
+
+ testmock
+
+
+
+ 500
+ sale
+
+
+ USD
+ rental
+
+
+HTTP/1.1 201 Created
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/invoices/1360
+
+
+
+
+
+
+
+
+
+ test
+ mock
+
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ 6f4654a0444808153e65594a08b9e7a3
+ paid
+
+ 1360
+
+ 51
+ 551
+ USD
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+ 2024-02-23T19:55:22Z
+
+
+
+ 500
+ 500
+ 0
+ 2024-02-23T19:55:22Z
+ 0
+ charge
+ purchase
+
+ 551
+
+
+ 0
+ automatic
+
+
+ usst
+ CA
+ 0.1025
+ true
+ rental
+
+
+
+
+
+
+
+
+ 551
+ 6f46549f12d532b7579250425881a3bb
+ invoiced
+
+
+
+ debit
+ 500
+ 1
+ 0
+ 51
+ 551
+ false
+ USD
+
+ usst
+ CA
+ 0.1025
+ false
+
+ 2024-02-23T19:55:20Z
+
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+
+
+ sale
+
+
+
+
+
+
+ 6f4654a1a6ba44d5272c794d0d9bd5f0
+ purchase
+ 551
+ 51
+ USD
+ success
+ credit_card
+ 8996823
+ transaction
+ false
+ true
+ true
+ true
+ 172.22.0.1
+ test
+ api
+
+ Successful test transaction
+
+
+
+
+ Street address and postal code match.
+
+
+ 2024-02-23T19:55:21Z
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+ false
+
+
+ testmock
+
+
+
+
+
+ test
+ mock
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ Visa
+ 2030
+ 12
+ 411111
+ 1111
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/fixtures/purchase/invoiced-with-multiple-adjustment-vertex-types.xml b/tests/fixtures/purchase/invoiced-with-multiple-adjustment-vertex-types.xml
new file mode 100644
index 00000000..9f14064d
--- /dev/null
+++ b/tests/fixtures/purchase/invoiced-with-multiple-adjustment-vertex-types.xml
@@ -0,0 +1,222 @@
+POST https://api.recurly.com/v2/purchases 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
+
+
+
+
+ testmock
+
+
+
+ 300
+ lease
+
+
+ 200
+ rental
+
+
+ USD
+
+
+HTTP/1.1 201 Created
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/invoices/1361
+
+
+
+
+
+
+
+
+
+ test
+ mock
+
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ 6f4654a0444808153e65594a08b9e7a4
+ paid
+
+ 1361
+
+ 51
+ 551
+ USD
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+ 2024-02-23T19:55:22Z
+
+
+
+ 500
+ 500
+ 0
+ 2024-02-23T19:55:22Z
+ 0
+ charge
+ purchase
+
+ 551
+
+
+ 0
+ automatic
+
+
+ usst
+ CA
+ 0.1025
+ true
+
+
+
+
+
+
+
+
+ 331
+ 6f46549f12d532b7579250425881a3bc
+ invoiced
+
+
+
+ debit
+ 300
+ 1
+ 0
+ 31
+ 331
+ false
+ USD
+
+ usst
+ CA
+ 0.1025
+ false
+
+ 2024-02-23T19:55:20Z
+
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+
+
+ lease
+
+
+
+
+
+
+
+
+ 220
+ 6f46549f12d532b7579250425881a3bd
+ invoiced
+
+
+
+ debit
+ 200
+ 1
+ 0
+ 20
+ 220
+ false
+ USD
+
+ usst
+ CA
+ 0.1025
+ false
+
+ 2024-02-23T19:55:20Z
+
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+
+
+ rental
+
+
+
+
+
+
+ 6f4654a1a6ba44d5272c794d0d9bd5f1
+ purchase
+ 551
+ 51
+ USD
+ success
+ credit_card
+ 8996824
+ transaction
+ false
+ true
+ true
+ true
+ 172.22.0.1
+ test
+ api
+
+ Successful test transaction
+
+
+
+
+ Street address and postal code match.
+
+
+ 2024-02-23T19:55:21Z
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+ false
+
+
+ testmock
+
+
+
+
+
+ test
+ mock
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ Visa
+ 2030
+ 12
+ 411111
+ 1111
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/fixtures/purchase/invoiced-with-purchase-level-vertex-transaction-type.xml b/tests/fixtures/purchase/invoiced-with-purchase-level-vertex-transaction-type.xml
new file mode 100644
index 00000000..f221e78e
--- /dev/null
+++ b/tests/fixtures/purchase/invoiced-with-purchase-level-vertex-transaction-type.xml
@@ -0,0 +1,182 @@
+POST https://api.recurly.com/v2/purchases 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
+
+
+
+
+ testmock
+
+
+
+ 500
+
+
+ USD
+ sale
+
+
+HTTP/1.1 201 Created
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/invoices/1360
+
+
+
+
+
+
+
+
+
+ test
+ mock
+
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ 6f4654a0444808153e65594a08b9e7a3
+ paid
+
+ 1360
+
+ 51
+ 551
+ USD
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+ 2024-02-23T19:55:22Z
+
+
+
+ 500
+ 500
+ 0
+ 2024-02-23T19:55:22Z
+ 0
+ charge
+ purchase
+
+ 551
+
+
+ 0
+ automatic
+
+
+ usst
+ CA
+ 0.1025
+ true
+
+
+
+
+
+
+
+
+ 551
+ 6f46549f12d532b7579250425881a3bb
+ invoiced
+
+
+
+ debit
+ 500
+ 1
+ 0
+ 51
+ 551
+ false
+ USD
+
+ usst
+ CA
+ 0.1025
+ false
+
+ 2024-02-23T19:55:20Z
+
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+
+
+ sale
+
+
+
+
+
+
+ 6f4654a1a6ba44d5272c794d0d9bd5f0
+ purchase
+ 551
+ 51
+ USD
+ success
+ credit_card
+ 8996823
+ transaction
+ false
+ true
+ true
+ true
+ 172.22.0.1
+ test
+ api
+
+ Successful test transaction
+
+
+
+
+ Street address and postal code match.
+
+
+ 2024-02-23T19:55:21Z
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+ false
+
+
+ testmock
+
+
+
+
+
+ test
+ mock
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ Visa
+ 2030
+ 12
+ 411111
+ 1111
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/fixtures/purchase/invoiced-with-vertex-transaction-type.xml b/tests/fixtures/purchase/invoiced-with-vertex-transaction-type.xml
new file mode 100644
index 00000000..36a76d75
--- /dev/null
+++ b/tests/fixtures/purchase/invoiced-with-vertex-transaction-type.xml
@@ -0,0 +1,182 @@
+POST https://api.recurly.com/v2/purchases 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
+
+
+
+
+ testmock
+
+
+
+ 500
+ lease
+
+
+ USD
+
+
+HTTP/1.1 201 Created
+Content-Type: application/xml; charset=utf-8
+Location: https://api.recurly.com/v2/invoices/1359
+
+
+
+
+
+
+
+
+
+ test
+ mock
+
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ 6f4654a0444808153e65594a08b9e7a2
+ paid
+
+ 1359
+
+ 51
+ 551
+ USD
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+ 2024-02-23T19:55:22Z
+
+
+
+ 500
+ 500
+ 0
+ 2024-02-23T19:55:22Z
+ 0
+ charge
+ purchase
+
+ 551
+
+
+ 0
+ automatic
+
+
+ usst
+ CA
+ 0.1025
+ true
+
+
+
+
+
+
+
+
+ 551
+ 6f46549f12d532b7579250425881a3ba
+ invoiced
+
+
+
+ debit
+ 500
+ 1
+ 0
+ 51
+ 551
+ false
+ USD
+
+ usst
+ CA
+ 0.1025
+ false
+
+ 2024-02-23T19:55:20Z
+
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+
+
+
+ lease
+
+
+
+
+
+
+ 6f4654a1a6ba44d5272c794d0d9bd5ef
+ purchase
+ 551
+ 51
+ USD
+ success
+ credit_card
+ 8996822
+ transaction
+ false
+ true
+ true
+ true
+ 172.22.0.1
+ test
+ api
+
+ Successful test transaction
+
+
+
+
+ Street address and postal code match.
+
+
+ 2024-02-23T19:55:21Z
+ 2024-02-23T19:55:22Z
+ 2024-02-23T19:55:22Z
+ false
+
+
+ testmock
+
+
+
+
+
+ test
+ mock
+ test
+
+ San Francisco
+ CA
+ 94016
+ US
+
+
+ Visa
+ 2030
+ 12
+ 411111
+ 1111
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/test_resources.py b/tests/test_resources.py
index 0fc4aab4..9d28f14d 100644
--- a/tests/test_resources.py
+++ b/tests/test_resources.py
@@ -473,6 +473,143 @@ def create_purchase():
self.assertEqual(adjustment.revenue_gl_account_code, 'firstrev')
self.assertEqual(adjustment.performance_obligation_id, '5')
+ def test_purchase_with_adjustment_level_vertex_transaction_type(self):
+ """Test that Adjustment can have vertex_transaction_type within a purchase"""
+ account_code = 'test%s' % self.test_id
+ def create_purchase():
+ return Purchase(
+ account = Account(
+ account_code = account_code,
+ ),
+ adjustments = [
+ recurly.Adjustment(
+ currency = 'USD',
+ vertex_transaction_type='lease',
+ unit_amount_in_cents=500
+ )
+ ]
+ )
+
+ with self.mock_request('purchase/invoiced-with-vertex-transaction-type.xml'):
+ collection = create_purchase().invoice()
+ adjustment = collection.charge_invoice.line_items[0]
+
+ self.assertIsInstance(collection, InvoiceCollection)
+ self.assertIsInstance(collection.charge_invoice, Invoice)
+ self.assertEqual(adjustment.vertex_transaction_type, 'lease')
+
+ def test_purchase_with_purchase_level_vertex_transaction_type(self):
+ """Test that Purchase can accept vertex_transaction_type at the top level"""
+ account_code = 'test%s' % self.test_id
+ def create_purchase():
+ return Purchase(
+ account = Account(
+ account_code = account_code,
+ ),
+ adjustments = [
+ recurly.Adjustment(
+ currency = 'USD',
+ unit_amount_in_cents=500
+ )
+ ],
+ vertex_transaction_type='sale'
+ )
+
+ with self.mock_request('purchase/invoiced-with-purchase-level-vertex-transaction-type.xml'):
+ collection = create_purchase().invoice()
+ adjustment = collection.charge_invoice.line_items[0]
+
+ self.assertIsInstance(collection, InvoiceCollection)
+ self.assertIsInstance(collection.charge_invoice, Invoice)
+ # The adjustment inherits the purchase-level vertex_transaction_type
+ self.assertEqual(adjustment.vertex_transaction_type, 'sale')
+
+ def test_purchase_with_multiple_adjustments_vertex_transaction_type(self):
+ """Test that each adjustment in a purchase can have its own vertex_transaction_type"""
+ account_code = 'test%s' % self.test_id
+ def create_purchase():
+ return Purchase(
+ account = Account(
+ account_code = account_code,
+ ),
+ adjustments = [
+ recurly.Adjustment(
+ currency = 'USD',
+ vertex_transaction_type='lease',
+ unit_amount_in_cents=300
+ ),
+ recurly.Adjustment(
+ currency = 'USD',
+ vertex_transaction_type='rental',
+ unit_amount_in_cents=200
+ )
+ ]
+ )
+
+ with self.mock_request('purchase/invoiced-with-multiple-adjustment-vertex-types.xml'):
+ collection = create_purchase().invoice()
+ adjustments = collection.charge_invoice.line_items
+
+ self.assertIsInstance(collection, InvoiceCollection)
+ self.assertIsInstance(collection.charge_invoice, Invoice)
+ self.assertEqual(len(adjustments), 2)
+ # Each adjustment has its own vertex_transaction_type
+ self.assertEqual(adjustments[0].vertex_transaction_type, 'lease')
+ self.assertEqual(adjustments[1].vertex_transaction_type, 'rental')
+
+ def test_charge_with_vertex_transaction_type(self):
+ """Test that vertex_transaction_type can be set on a direct adjustment via account.charge()"""
+ account = Account(account_code='charge%s' % self.test_id)
+ with self.mock_request('adjustment/account-created.xml'):
+ account.save()
+
+ charge = Adjustment(
+ unit_amount_in_cents=1000,
+ currency='USD',
+ description='test charge',
+ 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.
+ """
+ # Create a purchase with adjustment-level vertex_transaction_type='sale'
+ # but purchase-level (invoice-level) vertex_transaction_type='rental'
+ purchase = Purchase(
+ currency='USD',
+ account=Account(account_code='testmock'),
+ adjustments=[
+ Adjustment(
+ unit_amount_in_cents=500,
+ vertex_transaction_type='sale' # Adjustment-level value
+ )
+ ],
+ 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')
+
def test_account(self):
account_code = 'test%s' % self.test_id
with self.mock_request('account/does-not-exist.xml'):