Skip to content

Commit

Permalink
Adds support for updating invoices via HTTP POST
Browse files Browse the repository at this point in the history
  • Loading branch information
isaac committed May 18, 2011
1 parent 87679a5 commit 24e9d95
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 23 deletions.
9 changes: 9 additions & 0 deletions README.textile
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,15 @@ Invoice and line item totals are calculated automatically.
invoice.create</code></pre>



h3. POST /api.xro/2.0/invoice

Updates an existing invoice record.
<pre><code> invoice_retrieved_from_xero.due_date = Date.today
invoice_retrieved_from_xero.save</code></pre>



h3. PUT /api.xro/2.0/invoices

Inserts multiple invoices for a specific organization in Xero (currently only adding new invoices is allowed).
Expand Down
60 changes: 46 additions & 14 deletions lib/xero_gateway/gateway.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,21 +197,24 @@ def build_invoice(invoice = {})
#
# create_invoice(invoice)
def create_invoice(invoice)
request_xml = invoice.to_xml
response_xml = http_put(@client, "#{@xero_url}/Invoices", request_xml)
response = parse_response(response_xml, {:request_xml => request_xml}, {:request_signature => 'PUT/invoice'})

# Xero returns invoices inside an <Invoices> tag, even though there's only ever
# one for this request
response.response_item = response.invoices.first

if response.success? && response.invoice && response.invoice.invoice_id
invoice.invoice_id = response.invoice.invoice_id
end

response
save_invoice(invoice)
end


#
# Updates an existing Xero invoice
#
# Usage :
#
# invoice = xero_gateway.get_invoice(some_invoice_id)
# invoice.due_date = Date.today
#
# xero_gateway.update_invoice(invoice)

def update_invoice(invoice)
raise "invoice_id is required for updating invoices" if invoice.invoice_id.nil?
save_invoice(invoice)
end

#
# Creates an array of invoices with a single API request.
#
Expand Down Expand Up @@ -425,6 +428,35 @@ def save_contact(contact)
response
end

# Create or update an invoice record based on if it has an invoice_id.
def save_invoice(invoice)
request_xml = invoice.to_xml

response_xml = nil
create_or_save = nil
if invoice.invoice_id.nil?
# Create new invoice record.
response_xml = http_put(@client, "#{@xero_url}/Invoices", request_xml, {})
create_or_save = :create
else
# Update existing invoice record.
response_xml = http_post(@client, "#{@xero_url}/Invoices", request_xml, {})
create_or_save = :save
end

response = parse_response(response_xml, {:request_xml => request_xml}, {:request_signature => "#{create_or_save == :create ? 'PUT' : 'POST'}/invoice"})

# Xero returns invoices inside an <Invoices> tag, even though there's only ever
# one for this request
response.response_item = response.invoices.first

if response.success? && response.invoice && response.invoice.invoice_id
invoice.invoice_id = response.invoice.invoice_id
end

response
end

def parse_response(raw_response, request = {}, options = {})

response = XeroGateway::Response.new
Expand Down
26 changes: 17 additions & 9 deletions lib/xero_gateway/invoice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,14 @@ def ==(other)
return true
end

# General purpose createsave method.
# If contact_id and contact_number are nil then create, otherwise, attempt to save.
# General purpose create/save method.
# If invoice_id is nil then create, otherwise, attempt to save.
def save
create
if invoice_id.nil?
create
else
update
end
end

# Creates this invoice record (using gateway.create_invoice) with the associated gateway.
Expand All @@ -222,19 +226,24 @@ def create
gateway.create_invoice(self)
end

# Alias create as save as this is currently the only write action.
alias_method :save, :create

# Updates this invoice record (using gateway.update_invoice) with the associated gateway.
# If no gateway set, raise a Xero::Invoice::NoGatewayError exception.
def update
raise NoGatewayError unless gateway
gateway.update_invoice(self)
end

def to_xml(b = Builder::XmlMarkup.new)
b.Invoice {
b.InvoiceID self.invoice_id if self.invoice_id
b.InvoiceNumber self.invoice_number if invoice_number
b.Type self.invoice_type
b.CurrencyCode self.currency_code if self.currency_code
contact.to_xml(b)
b.Date Invoice.format_date(self.date || Date.today)
b.DueDate Invoice.format_date(self.due_date) if self.due_date
b.Status self.invoice_status if self.invoice_status
b.InvoiceNumber self.invoice_number if invoice_number
b.Reference self.reference if self.reference
b.CurrencyCode self.currency_code if self.currency_code
b.LineAmountTypes self.line_amount_types
b.LineItems {
self.line_items.each do |line_item|
Expand All @@ -253,7 +262,6 @@ def self.from_xml(invoice_element, gateway = nil, options = {})
when "InvoiceNumber" then invoice.invoice_number = element.text
when "Type" then invoice.invoice_type = element.text
when "CurrencyCode" then invoice.currency_code = element.text
when "Type" then invoice.invoice_type = element.text
when "Contact" then invoice.contact = Contact.from_xml(element)
when "Date" then invoice.date = parse_date(element.text)
when "DueDate" then invoice.due_date = parse_date(element.text)
Expand Down
31 changes: 31 additions & 0 deletions test/integration/update_invoice_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require File.dirname(__FILE__) + '/../test_helper'

class UpdateInvoiceTest < Test::Unit::TestCase
include TestHelper

def setup
@gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)

if STUB_XERO_CALLS
@gateway.xero_url = "DUMMY_URL"

@gateway.stubs(:http_put).with {|client, url, body, params| url =~ /Invoices$/ }.returns(get_file_as_string("create_invoice.xml"))
@gateway.stubs(:http_post).with {|client, url, body, params| url =~ /Invoices$/ }.returns(get_file_as_string("invoice.xml"))
end
end

def test_update_invoice
invoice = @gateway.create_invoice(dummy_invoice).invoice

today = Date.today
invoice.due_date = today

result = @gateway.update_invoice(invoice)

assert result.success?
assert !result.request_xml.nil?
assert !result.response_xml.nil?
assert_equal invoice.invoice_id, result.invoice.invoice_id
assert_equal today, result.invoice.due_date if !STUB_XERO_CALLS
end
end

0 comments on commit 24e9d95

Please sign in to comment.