Skip to content

Commit

Permalink
Merge pull request #699 from recurly/line-item-refunds
Browse files Browse the repository at this point in the history
Add percentage and amount_in_cents to line items
  • Loading branch information
amandamfielding authored Aug 20, 2024
2 parents 7f547e5 + 952a1c4 commit 95e6f28
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 9 deletions.
42 changes: 33 additions & 9 deletions recurly/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1210,7 +1210,24 @@ def refund_amount(self, amount_in_cents, refund_options = {}):
if 'refund_method' not in refund_options:
refund_options = { 'refund_method': 'credit_first' }

amount_element = self._refund_open_amount_xml(amount_in_cents,
amount_element = self._refund_open_amount_xml('amount_in_cents',
amount_in_cents,
refund_options)
return self._create_refund_invoice(amount_element)

def refund_percentage(self, percentage, refund_options = {}):
# For backwards compatibility
# TODO the consequent branch of this conditional should eventually be removed
# and we should document that as a breaking change in the changelog.
# The same change should be applied to the refund() method
if (isinstance(refund_options, six.string_types)):
refund_options = { 'refund_method': refund_options }
else:
if 'refund_method' not in refund_options:
refund_options = { 'refund_method': 'credit_first' }

amount_element = self._refund_open_amount_xml('percentage',
percentage,
refund_options)
return self._create_refund_invoice(amount_element)

Expand All @@ -1229,10 +1246,10 @@ def refund(self, adjustments, refund_options = {}):
refund_options)
return self._create_refund_invoice(adjustments_element)

def _refund_open_amount_xml(self, amount_in_cents, refund_options):
def _refund_open_amount_xml(self, refund_type, refund_amount, refund_options):
elem = ElementTreeBuilder.Element(self.nodename)
elem.append(Resource.element_for_value('amount_in_cents',
amount_in_cents))
elem.append(Resource.element_for_value(refund_type,
refund_amount))

# Need to sort the keys for tests to pass in python 2 and 3
# Can remove `sorted` when we drop python 2 support
Expand All @@ -1247,15 +1264,22 @@ def _refund_line_items_xml(self, line_items, refund_options):

for item in line_items:
adj_elem = ElementTreeBuilder.Element('adjustment')
adj_elem.append(Resource.element_for_value('uuid',
item['adjustment'].uuid))
adj_elem.append(Resource.element_for_value('quantity',
item['quantity']))
adj_elem.append(Resource.element_for_value('uuid', item['adjustment'].uuid))

if 'quantity' in item:
adj_elem.append(Resource.element_for_value('quantity', item['quantity']))

if 'quantity_decimal' in item:
adj_elem.append(Resource.element_for_value('quantity_decimal', item['quantity_decimal']))

adj_elem.append(Resource.element_for_value('prorate', item['prorate']))
if 'percentage' in item:
adj_elem.append(Resource.element_for_value('percentage', item['percentage']))

if 'amount_in_cents' in item:
adj_elem.append(Resource.element_for_value('amount_in_cents', item['amount_in_cents']))

if 'prorate' in item:
adj_elem.append(Resource.element_for_value('prorate', item['prorate']))
line_items_elem.append(adj_elem)

elem.append(line_items_elem)
Expand Down
39 changes: 39 additions & 0 deletions tests/fixtures/invoice/line-item-refunded-amount-in-cents.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
POST https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8/refund 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

<?xml version="1.0" encoding="UTF-8"?>
<invoice>
<line_items>
<adjustment>
<uuid>2bc3cf4cb513049c6aec1b419c97b508</uuid>
<amount_in_cents type="integer">500</amount_in_cents>
<prorate type="boolean">false</prorate>
</adjustment>
</line_items>
<credit_customer_notes>Credit Customer Notes</credit_customer_notes>
<description>Description</description>
<refund_method>credit_first</refund_method>
</invoice>

HTTP/1.1 201 Created
Content-Type: application/xml; charset=utf-8
Location: https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8

<?xml version="1.0" encoding="UTF-8"?>
<invoice href="https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8">
<uuid>4ba1531325014b4f969cd13676f514d8</uuid>
<account_code>invoicemock</account_code>
<invoice_number type="integer">1001</invoice_number>
<invoice_number_prefix></invoice_number_prefix>
<subtotal_in_cents type="integer">-500</subtotal_in_cents>
<tax_in_cents type="integer">0</tax_in_cents>
<total_in_cents type="integer">-500</total_in_cents>
<start_date type="datetime">2009-11-03T23:27:46-08:00</start_date>
<end_date type="datetime"></end_date>
<description>test charge</description>
<created_at type="datetime">2009-11-03T23:27:46-08:00</created_at>
</invoice>
39 changes: 39 additions & 0 deletions tests/fixtures/invoice/line-item-refunded-percentage.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
POST https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8/refund 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

<?xml version="1.0" encoding="UTF-8"?>
<invoice>
<line_items>
<adjustment>
<uuid>2bc3cf4cb513049c6aec1b419c97b508</uuid>
<percentage type="integer">50</percentage>
<prorate type="boolean">false</prorate>
</adjustment>
</line_items>
<credit_customer_notes>Credit Customer Notes</credit_customer_notes>
<description>Description</description>
<refund_method>credit_first</refund_method>
</invoice>

HTTP/1.1 201 Created
Content-Type: application/xml; charset=utf-8
Location: https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8

<?xml version="1.0" encoding="UTF-8"?>
<invoice href="https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8">
<uuid>4ba1531325014b4f969cd13676f514d8</uuid>
<account_code>invoicemock</account_code>
<invoice_number type="integer">1001</invoice_number>
<invoice_number_prefix></invoice_number_prefix>
<subtotal_in_cents type="integer">-500</subtotal_in_cents>
<tax_in_cents type="integer">0</tax_in_cents>
<total_in_cents type="integer">-500</total_in_cents>
<start_date type="datetime">2009-11-03T23:27:46-08:00</start_date>
<end_date type="datetime"></end_date>
<description>test charge</description>
<created_at type="datetime">2009-11-03T23:27:46-08:00</created_at>
</invoice>
33 changes: 33 additions & 0 deletions tests/fixtures/invoice/refunded-percentage.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
POST https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8/refund 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

<?xml version="1.0" encoding="UTF-8"?>
<invoice>
<percentage type="integer">50</percentage>
<credit_customer_notes>Credit Customer Notes</credit_customer_notes>
<description>Description</description>
<refund_method>credit_first</refund_method>
</invoice>

HTTP/1.1 201 Created
Content-Type: application/xml; charset=utf-8
Location: https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8

<?xml version="1.0" encoding="UTF-8"?>
<invoice href="https://api.recurly.com/v2/invoices/4ba1531325014b4f969cd13676f514d8">
<uuid>4ba1531325014b4f969cd13676f514d8</uuid>
<account_code>invoicemock</account_code>
<invoice_number type="integer">1001</invoice_number>
<invoice_number_prefix></invoice_number_prefix>
<subtotal_in_cents type="integer">-50</subtotal_in_cents>
<tax_in_cents type="integer">0</tax_in_cents>
<total_in_cents type="integer">-50</total_in_cents>
<start_date type="datetime">2009-11-03T23:27:46-08:00</start_date>
<end_date type="datetime"></end_date>
<description>test charge</description>
<created_at type="datetime">2009-11-03T23:27:46-08:00</created_at>
</invoice>
53 changes: 53 additions & 0 deletions tests/test_resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,23 @@ def test_invoice_refund_amount(self):
refund_invoice = invoice.refund_amount(1000, options)
self.assertEqual(refund_invoice.subtotal_in_cents, -1000)

def test_invoice_refund_percentage(self):
account = Account(account_code='invoice%s' % self.test_id)
with self.mock_request('invoice/account-created.xml'):
account.save()

with self.mock_request('invoice/invoiced.xml'):
invoice = account.invoice().charge_invoice

with self.mock_request('invoice/refunded-percentage.xml'):
options = {
'refund_method': 'credit_first',
'credit_customer_notes': 'Credit Customer Notes',
'description': 'Description'
}
refund_invoice = invoice.refund_percentage(50, options)
self.assertEqual(refund_invoice.subtotal_in_cents, -50)

def test_invoice_refund(self):
account = Account(account_code='invoice%s' % self.test_id)
with self.mock_request('invoice/account-created.xml'):
Expand All @@ -1697,6 +1714,42 @@ def test_invoice_refund(self):
refund_invoice = invoice.refund(line_items, options)
self.assertEqual(refund_invoice.subtotal_in_cents, -1000)

def test_invoice_refund_line_item_percentage(self):
account = Account(account_code='invoice%s' % self.test_id)
with self.mock_request('invoice/account-created.xml'):
account.save()

with self.mock_request('invoice/invoiced-line-items.xml'):
invoice = account.invoice().charge_invoice

with self.mock_request('invoice/line-item-refunded-percentage.xml'):
line_items = [{ 'adjustment': invoice.line_items[0], 'percentage': 50, 'prorate': False }]
options = {
'refund_method': 'credit_first',
'credit_customer_notes': 'Credit Customer Notes',
'description': 'Description'
}
refund_invoice = invoice.refund(line_items, options)
self.assertEqual(refund_invoice.subtotal_in_cents, -500)

def test_invoice_refund_line_item_amount_in_cents(self):
account = Account(account_code='invoice%s' % self.test_id)
with self.mock_request('invoice/account-created.xml'):
account.save()

with self.mock_request('invoice/invoiced-line-items.xml'):
invoice = account.invoice().charge_invoice

with self.mock_request('invoice/line-item-refunded-amount-in-cents.xml'):
line_items = [{ 'adjustment': invoice.line_items[0], 'amount_in_cents': 500, 'prorate': False }]
options = {
'refund_method': 'credit_first',
'credit_customer_notes': 'Credit Customer Notes',
'description': 'Description'
}
refund_invoice = invoice.refund(line_items, options)
self.assertEqual(refund_invoice.subtotal_in_cents, -500)

def test_invoice_collect(self):
with self.mock_request('invoice/show-invoice.xml'):
invoice = Invoice.get("6019")
Expand Down

0 comments on commit 95e6f28

Please sign in to comment.