diff --git a/lib/recurly/invoice.rb b/lib/recurly/invoice.rb
index 00851ebae..cac806c93 100644
--- a/lib/recurly/invoice.rb
+++ b/lib/recurly/invoice.rb
@@ -249,6 +249,25 @@ def refund_amount(amount_in_cents = nil, refund_method = 'credit_first', options
)
end
+ # Refunds the invoice for a specific percentage.
+ #
+ # @return [Invoice, false] Invoice if successful, false if the invoice isn't
+ # refundable.
+ # @raise [Error] If the refund fails.
+ # @param percentage [Integer, nil] The percentage to refund from the invoice.
+ # @param refund_method ["credit_first", "transaction_first", "all_transaction", "all_credit"] The method used to refund.
+ # @param external_refund [true, false] Designates that the refund transactions created are manual.
+ # @param credit_customer_notes [String] Adds notes to refund credit invoice.
+ # @param payment_method [String] Creates the manual transactions with this payment method. Allowed if *external_refund* is true.
+ # @param description [String] Sets this value as the *transaction_note* on the manual transactions created. Allowed if *external_refund* is true.
+ # @param refunded_at [DateTime] Sets this value as the *collected_at* on the manual transactions created. Allowed if *external_refund* is true.
+ def refund_percentage(percentage = nil, refund_method = 'credit_first', options = {})
+ return false unless link? :refund
+ self.class.from_response(
+ follow_link :refund, :body => refund_percentage_to_xml(percentage, refund_method, options)
+ )
+ end
+
def xml_keys
super - ['currency']
end
@@ -285,6 +304,16 @@ def refund_amount_to_xml(amount_in_cents = nil, refund_method = nil, options = {
builder.to_s
end
+ def refund_percentage_to_xml(percentage = nil, refund_method = nil, options = {})
+ builder = XML.new("")
+ builder.add_element 'refund_method', refund_method
+ builder.add_element 'percentage', percentage
+ options.each do |k, v|
+ builder.add_element k.to_s, v
+ end
+ builder.to_s
+ end
+
def refund_line_items_to_xml(line_items = nil, refund_method = nil, options = {})
builder = XML.new("")
builder.add_element 'refund_method', refund_method
@@ -296,8 +325,10 @@ def refund_line_items_to_xml(line_items = nil, refund_method = nil, options = {}
line_items.each do |line_item|
adj_node = node.add_element 'adjustment'
adj_node.add_element 'uuid', line_item[:adjustment].uuid
- adj_node.add_element 'quantity', line_item[:quantity]
+ adj_node.add_element 'quantity', line_item[:quantity] if line_item.key?(:quantity)
adj_node.add_element('quantity_decimal', line_item[:quantity_decimal]) if line_item.key?(:quantity_decimal)
+ adj_node.add_element 'percentage', line_item[:percentage] if line_item.key?(:percentage)
+ adj_node.add_element 'amount_in_cents', line_item[:amount_in_cents] if line_item.key?(:amount_in_cents)
adj_node.add_element 'prorate', line_item[:prorate]
end
builder.to_s
diff --git a/spec/recurly/invoice_spec.rb b/spec/recurly/invoice_spec.rb
index 155a6e11e..fb30c87b3 100644
--- a/spec/recurly/invoice_spec.rb
+++ b/spec/recurly/invoice_spec.rb
@@ -162,6 +162,22 @@
adjustment.quantity_remaining.must_equal 1
end
end
+
+ it "creates a refund invoice for the line items refunded with amount in cents" do
+ line_items = @invoice.line_items.values.map do |adjustment|
+ { adjustment: adjustment, amount_in_cents: 100, prorate: false }
+ end
+ refund_invoice = @invoice.refund line_items
+ refund_invoice.must_be_instance_of Invoice
+ end
+
+ it "creates a refund invoice for the line items refunded with percentage" do
+ line_items = @invoice.line_items.values.map do |adjustment|
+ { adjustment: adjustment, percentage: 77, prorate: false }
+ end
+ refund_invoice = @invoice.refund line_items
+ refund_invoice.must_be_instance_of Invoice
+ end
end
describe "#refund_to_xml" do
@@ -178,6 +194,38 @@
'credit_firstCredit NotestruecheckCheck no. 123456782018-12-01T00:00:00+00:0017500charge11false'
)
end
+
+ it "must serialize line_items with amount_in_cents" do
+ line_items = @invoice.line_items.values.map do |adjustment|
+ { adjustment: adjustment, amount_in_cents: 100, prorate: false }
+ end
+ options = {
+ credit_customer_notes: 'Credit Notes',
+ external_refund: true,
+ payment_method: 'check',
+ description: 'Check no. 12345678',
+ refunded_at: DateTime.new(2018, 12, 1, 0, 0, 0)
+ }
+ @invoice.send(:refund_line_items_to_xml, line_items, 'credit_first', options).must_equal(
+ 'credit_firstCredit NotestruecheckCheck no. 123456782018-12-01T00:00:00+00:00charge1100false'
+ )
+ end
+
+ it "must serialize line_items with percentage" do
+ line_items = @invoice.line_items.values.map do |adjustment|
+ { adjustment: adjustment, percentage: 77, prorate: false }
+ end
+ options = {
+ credit_customer_notes: 'Credit Notes',
+ external_refund: true,
+ payment_method: 'check',
+ description: 'Check no. 12345678',
+ refunded_at: DateTime.new(2018, 12, 1, 0, 0, 0)
+ }
+ @invoice.send(:refund_line_items_to_xml, line_items, 'credit_first', options).must_equal(
+ 'credit_firstCredit NotestruecheckCheck no. 123456782018-12-01T00:00:00+00:00charge177false'
+ )
+ end
end
end
@@ -189,8 +237,8 @@
@invoice = Invoice.find 'refundable-invoice'
end
- describe "#refund" do
- it "creates a refund invoice for the line items refunded" do
+ describe "#refund_amount" do
+ it "creates a refund invoice for the line items refunded using amount" do
refund_invoice = @invoice.refund_amount 1000
refund_invoice.must_be_instance_of Invoice
refund_invoice.original_invoices.must_be_instance_of Recurly::Resource::Pager
@@ -198,7 +246,7 @@
end
end
- describe "#refund_to_xml" do
+ describe "#refund_amount_to_xml" do
it "must serialize amount_in_cents" do
options = {
credit_customer_notes: 'Credit Notes',
@@ -215,6 +263,39 @@
end
end
+ describe "percentage refund" do
+ before do
+ stub_api_request :get, 'invoices/refundable-invoice', 'invoices/show-200-refundable'
+ stub_api_request :post, 'invoices/refundable-invoice/refund', 'invoices/refund_amount-201'
+
+ @invoice = Invoice.find 'refundable-invoice'
+ end
+
+ describe "#refund_percentage" do
+ it "creates a refund invoice for the line items refunded using percentage" do
+ refund_invoice = @invoice.refund_percentage 50
+ refund_invoice.must_be_instance_of Invoice
+ refund_invoice.original_invoices.must_be_instance_of Recurly::Resource::Pager
+ refund_invoice.amount_remaining_in_cents.must_equal 100
+ end
+ end
+
+ describe "#refund_percentage_to_xml" do
+ it "must serialize percentage" do
+ options = {
+ credit_customer_notes: 'Credit Notes',
+ external_refund: true,
+ payment_method: 'check',
+ description: 'Check no. 12345678',
+ refunded_at: DateTime.new(2018, 12, 1, 0, 0, 0)
+ }
+ @invoice.send(:refund_percentage_to_xml, 50, 'credit_first', options).must_equal(
+ 'credit_first50Credit NotestruecheckCheck no. 123456782018-12-01T00:00:00+00:00'
+ )
+ end
+ end
+ end
+
describe "failed_refund" do
before do
stub_api_request :get, 'invoices/refundable-invoice', 'invoices/show-200-refundable'