tlconnor-xero_gateway 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.textile +14 -0
- data/LICENSE +14 -0
- data/README.textile +119 -0
- data/Rakefile +14 -0
- data/lib/xero_gateway.rb +35 -0
- data/lib/xero_gateway/account.rb +34 -0
- data/lib/xero_gateway/address.rb +47 -0
- data/lib/xero_gateway/contact.rb +54 -0
- data/lib/xero_gateway/dates.rb +31 -0
- data/lib/xero_gateway/gateway.rb +283 -0
- data/lib/xero_gateway/http.rb +73 -0
- data/lib/xero_gateway/invoice.rb +48 -0
- data/lib/xero_gateway/line_item.rb +40 -0
- data/lib/xero_gateway/messages/account_message.rb +59 -0
- data/lib/xero_gateway/messages/contact_message.rb +107 -0
- data/lib/xero_gateway/messages/invoice_message.rb +136 -0
- data/lib/xero_gateway/money.rb +30 -0
- data/lib/xero_gateway/phone.rb +38 -0
- data/lib/xero_gateway/response.rb +44 -0
- data/test/integration/gateway_test.rb +166 -0
- data/test/integration/stub_responses/accounts.xml +1 -0
- data/test/integration/stub_responses/contact.xml +1 -0
- data/test/integration/stub_responses/contacts.xml +1 -0
- data/test/integration/stub_responses/invoice.xml +1 -0
- data/test/integration/stub_responses/invoices.xml +1 -0
- data/test/test_helper.rb +22 -0
- data/test/unit/messages/contact_message_test.rb +66 -0
- data/test/unit/messages/invoice_message_test.rb +76 -0
- data/test/xsd/README +2 -0
- data/test/xsd/create_contact.xsd +50 -0
- data/test/xsd/create_invoice.xsd +98 -0
- data/xero_gateway.gemspec +44 -0
- metadata +92 -0
data/CHANGELOG.textile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
h2. 1.0.1, releases 01/12/2008
|
2
|
+
|
3
|
+
# Added implementation of GET /api.xro/1.0/accounts
|
4
|
+
|
5
|
+
|
6
|
+
h2. 1.0.0, released 01/12/2008
|
7
|
+
|
8
|
+
* Initial release, including:
|
9
|
+
* PUT /api.xro/1.0/contact
|
10
|
+
* GET /api.xro/1.0/contact
|
11
|
+
* GET /api.xro/1.0/contacts
|
12
|
+
* PUT /api.xro/1.0/invoice
|
13
|
+
* GET /api.xro/1.0/invoice
|
14
|
+
* GET /api.xro/1.0/invoices
|
data/LICENSE
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
data/README.textile
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
h1. Xero API wrapper
|
2
|
+
|
3
|
+
h2. Introduction
|
4
|
+
|
5
|
+
This library is designed to help ruby based applications communicate with the publicly available API for Xero. If you are unfamiliar with the API, you should first read the documentation, located here "http://blog.xero.com/developer/":http://blog.xero.com/developer/
|
6
|
+
|
7
|
+
h2. Prerequisites
|
8
|
+
|
9
|
+
To use the Xero API you must have a Xero API Key. If you don't know what this is, and don't know how to get one, this library is probably not for you.
|
10
|
+
|
11
|
+
h2. Usage
|
12
|
+
|
13
|
+
<pre><code> require 'xero_gateway'
|
14
|
+
gateway = XeroGateway::Gateway.new(
|
15
|
+
:customer_key => "THE_CUSTOMER_KEY_GENERATED_FOR_YOUR_APP",
|
16
|
+
:api_key => "YOUR_XERO_API_KEY",
|
17
|
+
:xero_url => "THE URL FOR THE XERO API (test or live)"
|
18
|
+
)</code></pre>
|
19
|
+
|
20
|
+
|
21
|
+
h2. Implemented interface methods
|
22
|
+
|
23
|
+
h3. GET /api.xro/1.0/contact (get_contact_by_id)
|
24
|
+
|
25
|
+
Example:
|
26
|
+
<pre><code>
|
27
|
+
result = gateway.get_contact_by_id(contact_id)
|
28
|
+
contact = result.contact if result.success?
|
29
|
+
</code></pre>
|
30
|
+
|
31
|
+
h3. GET /api.xro/1.0/contact (get_contact_by_number)
|
32
|
+
|
33
|
+
Example:
|
34
|
+
<pre><code>
|
35
|
+
gateway.get_contact_by_number(contact_number)
|
36
|
+
</code></pre>
|
37
|
+
|
38
|
+
h3. GET /api.xro/1.0/contacts (get_contacts)
|
39
|
+
|
40
|
+
Example:
|
41
|
+
<pre><code>
|
42
|
+
gateway.get_contacts(:type => :all, :sort => :name, :direction => :desc)
|
43
|
+
</code></pre>
|
44
|
+
|
45
|
+
h3. PUT /api.xro/1.0/contact
|
46
|
+
|
47
|
+
Example:
|
48
|
+
<pre><code>
|
49
|
+
contact = XeroGateway::Contact.new
|
50
|
+
contact.name = "The contacts name"
|
51
|
+
contact.email = "whoever@something.com"
|
52
|
+
contact.phone.number = "555 123 4567"
|
53
|
+
contact.address.line_1 = "LINE 1 OF THE ADDRESS"
|
54
|
+
contact.address.line_2 = "LINE 2 OF THE ADDRESS"
|
55
|
+
contact.address.city = "WELLINGTON"
|
56
|
+
contact.address.region = "WELLINGTON"
|
57
|
+
contact.address.country = "NEW ZEALAND"
|
58
|
+
contact.address.post_code = "6021"
|
59
|
+
|
60
|
+
gateway.create_contact(contact)
|
61
|
+
</code></pre>
|
62
|
+
|
63
|
+
h3. GET /api.xro/1.0/invoice (get_invoice_by_id)
|
64
|
+
|
65
|
+
Example:
|
66
|
+
<pre><code>
|
67
|
+
gateway.get_invoice_by_id(invoice_id)
|
68
|
+
</code></pre>
|
69
|
+
|
70
|
+
h3. GET /api.xro/1.0/invoice (get_invoice_by_number)
|
71
|
+
|
72
|
+
Example:
|
73
|
+
<pre><code>
|
74
|
+
gateway.get_invoice_by_number(invoice_number)
|
75
|
+
</code></pre>
|
76
|
+
|
77
|
+
h3. GET /api.xro/1.0/invoices (get_invoices)
|
78
|
+
|
79
|
+
Example:
|
80
|
+
<pre><code>
|
81
|
+
gateway.get_invoices(modified_since = nil)
|
82
|
+
</code></pre>
|
83
|
+
|
84
|
+
h3. PUT /api.xro/1.0/invoice
|
85
|
+
|
86
|
+
Example:
|
87
|
+
<pre><code>
|
88
|
+
invoice = XeroGateway::Invoice.new({
|
89
|
+
:invoice_type => "ACCREC",
|
90
|
+
:due_date => 1.month.from_now,
|
91
|
+
:invoice_number => "YOUR INVOICE NUMBER",
|
92
|
+
:reference => "YOUR REFERENCE (NOT NECESSARILY UNIQUE!)",
|
93
|
+
:tax_inclusive => true,
|
94
|
+
:includes_tax => false,
|
95
|
+
:sub_total => 1000,
|
96
|
+
:total_tax => 125,
|
97
|
+
:total => 1250
|
98
|
+
})
|
99
|
+
invoice.contact = XeroGateway::Contact.new(:name => "THE NAME OF THE CONTACT")
|
100
|
+
invoice.contact.phone.number = "12345"
|
101
|
+
invoice.contact.address.line_1 = "LINE 1 OF THE ADDRESS"
|
102
|
+
invoice.line_items << XeroGateway::LineItem.new(
|
103
|
+
:description => "THE DESCRIPTION OF THE LINE ITEM",
|
104
|
+
:unit_amount => 1000,
|
105
|
+
:tax_amount => 125,
|
106
|
+
:line_amount => 1000,
|
107
|
+
:tracking_category => "THE TRACKING CATEGORY FOR THE LINE ITEM",
|
108
|
+
:tracking_option => "THE TRACKING OPTION FOR THE LINE ITEM"
|
109
|
+
)
|
110
|
+
|
111
|
+
gateway.create_invoice(invoice)
|
112
|
+
</code></pre>
|
113
|
+
|
114
|
+
h3. GET /api.xro/1.0/accounts
|
115
|
+
|
116
|
+
Example:
|
117
|
+
<pre><code>
|
118
|
+
gateway.get_accounts
|
119
|
+
</code></pre>
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the xero gateway.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
data/lib/xero_gateway.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
require 'cgi'
|
16
|
+
require "uri"
|
17
|
+
require 'net/https'
|
18
|
+
require "rexml/document"
|
19
|
+
require "builder"
|
20
|
+
require "bigdecimal"
|
21
|
+
|
22
|
+
require File.dirname(__FILE__) + "/xero_gateway/http"
|
23
|
+
require File.dirname(__FILE__) + "/xero_gateway/dates"
|
24
|
+
require File.dirname(__FILE__) + "/xero_gateway/money"
|
25
|
+
require File.dirname(__FILE__) + "/xero_gateway/response"
|
26
|
+
require File.dirname(__FILE__) + "/xero_gateway/line_item"
|
27
|
+
require File.dirname(__FILE__) + "/xero_gateway/invoice"
|
28
|
+
require File.dirname(__FILE__) + "/xero_gateway/contact"
|
29
|
+
require File.dirname(__FILE__) + "/xero_gateway/address"
|
30
|
+
require File.dirname(__FILE__) + "/xero_gateway/phone"
|
31
|
+
require File.dirname(__FILE__) + "/xero_gateway/account"
|
32
|
+
require File.dirname(__FILE__) + "/xero_gateway/messages/contact_message"
|
33
|
+
require File.dirname(__FILE__) + "/xero_gateway/messages/invoice_message"
|
34
|
+
require File.dirname(__FILE__) + "/xero_gateway/messages/account_message"
|
35
|
+
require File.dirname(__FILE__) + "/xero_gateway/gateway"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
module XeroGateway
|
16
|
+
class Account
|
17
|
+
attr_accessor :code, :name, :type, :tax_type, :description
|
18
|
+
|
19
|
+
def initialize(params = {})
|
20
|
+
params.each do |k,v|
|
21
|
+
self.instance_variable_set("@#{k}", v) ## create and initialize an instance variable for this key/value pair
|
22
|
+
self.send("#{k}=", v)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def ==(other)
|
27
|
+
equal = true
|
28
|
+
[:code, :name, :type, :tax_type, :description].each do |field|
|
29
|
+
equal &&= (send(field) == other.send(field))
|
30
|
+
end
|
31
|
+
return equal
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
module XeroGateway
|
16
|
+
class Address
|
17
|
+
attr_accessor :address_type, :line_1, :line_2, :line_3, :line_4, :city, :region, :post_code, :country
|
18
|
+
|
19
|
+
def initialize(params = {})
|
20
|
+
params = {
|
21
|
+
:address_type => "DEFAULT"
|
22
|
+
}.merge(params)
|
23
|
+
|
24
|
+
params.each do |k,v|
|
25
|
+
self.instance_variable_set("@#{k}", v) ## create and initialize an instance variable for this key/value pair
|
26
|
+
self.send("#{k}=", v)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.parse(string)
|
31
|
+
address = Address.new
|
32
|
+
|
33
|
+
string.split("\r\n").each_with_index do |line, index|
|
34
|
+
address.instance_variable_set("@line_#{index+1}", line)
|
35
|
+
end
|
36
|
+
address
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(other)
|
40
|
+
equal = true
|
41
|
+
[:address_type, :line_1, :line_2, :line_3, :line_4, :city, :region, :post_code, :country].each do |field|
|
42
|
+
equal &&= (send(field) == other.send(field))
|
43
|
+
end
|
44
|
+
return equal
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
module XeroGateway
|
16
|
+
class Contact
|
17
|
+
attr_accessor :id, :contact_number, :status, :name, :email, :addresses, :phones, :updated_at
|
18
|
+
|
19
|
+
def initialize(params = {})
|
20
|
+
params = {}.merge(params)
|
21
|
+
params.each do |k,v|
|
22
|
+
self.instance_variable_set("@#{k}", v) ## create and initialize an instance variable for this key/value pair
|
23
|
+
self.send("#{k}=", v)
|
24
|
+
end
|
25
|
+
|
26
|
+
@phones ||= []
|
27
|
+
@addresses ||= []
|
28
|
+
end
|
29
|
+
|
30
|
+
def address=(address)
|
31
|
+
self.addresses = [address]
|
32
|
+
end
|
33
|
+
|
34
|
+
def address
|
35
|
+
self.addresses[0] ||= Address.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def phone=(phone)
|
39
|
+
self.phones = [phone]
|
40
|
+
end
|
41
|
+
|
42
|
+
def phone
|
43
|
+
self.phones[0] ||= Phone.new
|
44
|
+
end
|
45
|
+
|
46
|
+
def ==(other)
|
47
|
+
equal = true
|
48
|
+
[:contact_number, :status, :name, :email, :addresses, :phones].each do |field|
|
49
|
+
equal &&= (send(field) == other.send(field))
|
50
|
+
end
|
51
|
+
return equal
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
module XeroGateway
|
16
|
+
module Dates
|
17
|
+
def self.included(base)
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
def format_date_time(time)
|
23
|
+
return time.strftime("%Y-%m-%dT%H:%M:%S")
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_date_time(time)
|
27
|
+
Time.local(time[0..3].to_i, time[5..6].to_i, time[8..9].to_i, time[11..12].to_i, time[14..15].to_i, time[17..18].to_i)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,283 @@
|
|
1
|
+
# Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
13
|
+
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
module XeroGateway
|
16
|
+
class Gateway
|
17
|
+
include Http
|
18
|
+
|
19
|
+
attr_accessor :xero_url, :customer_key, :api_key
|
20
|
+
|
21
|
+
def initialize(params)
|
22
|
+
@xero_url = params[:xero_url] || "https://networktest.xero.com/api.xro/1.0"
|
23
|
+
@customer_key = params[:customer_key]
|
24
|
+
@api_key = params[:api_key]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Retrieve all contacts from Xero
|
28
|
+
# Usage get_contacts(:type => :all, :sort => :name, :direction => :desc)
|
29
|
+
def get_contacts(options = {})
|
30
|
+
request_params = {}
|
31
|
+
request_params[:type] = options[:type] if options[:type]
|
32
|
+
request_params[:sortBy] = options[:sort] if options[:sort]
|
33
|
+
request_params[:direction] = options[:direction] if options[:direction]
|
34
|
+
|
35
|
+
response_xml = http_get("#{@xero_url}/contacts", request_params)
|
36
|
+
|
37
|
+
doc = REXML::Document.new(response_xml)
|
38
|
+
|
39
|
+
# Create the response object
|
40
|
+
response = build_response(doc)
|
41
|
+
|
42
|
+
# Add the contacts to the response
|
43
|
+
if response.success?
|
44
|
+
response.response_item = []
|
45
|
+
REXML::XPath.each(doc, "/Response/Contacts/Contact") do |contact_element|
|
46
|
+
response.response_item << XeroGateway::Messages::ContactMessage.from_xml(contact_element)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Add the request and response XML to the response object
|
51
|
+
response.request_params = request_params
|
52
|
+
response.response_xml = response_xml
|
53
|
+
response
|
54
|
+
end
|
55
|
+
|
56
|
+
# Retrieve a contact from Xero
|
57
|
+
# Usage get_contact_by_id(contact_id)
|
58
|
+
def get_contact_by_id(contact_id)
|
59
|
+
get_contact(contact_id)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Retrieve a contact from Xero
|
63
|
+
# Usage get_contact_by_id(contact_id)
|
64
|
+
def get_contact_by_number(contact_number)
|
65
|
+
get_contact(nil, contact_number)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
# Creates a contact in Xero
|
70
|
+
#
|
71
|
+
# Usage :
|
72
|
+
#
|
73
|
+
# contact = XeroGateway::Contact.new(:name => "THE NAME OF THE CONTACT #{Time.now.to_i}")
|
74
|
+
# contact.email = "whoever@something.com"
|
75
|
+
# contact.phone.number = "12345"
|
76
|
+
# contact.address.line_1 = "LINE 1 OF THE ADDRESS"
|
77
|
+
# contact.address.line_2 = "LINE 2 OF THE ADDRESS"
|
78
|
+
# contact.address.line_3 = "LINE 3 OF THE ADDRESS"
|
79
|
+
# contact.address.line_4 = "LINE 4 OF THE ADDRESS"
|
80
|
+
# contact.address.city = "WELLINGTON"
|
81
|
+
# contact.address.region = "WELLINGTON"
|
82
|
+
# contact.address.country = "NEW ZEALAND"
|
83
|
+
# contact.address.post_code = "6021"
|
84
|
+
#
|
85
|
+
# create_contact(contact)
|
86
|
+
def create_contact(contact)
|
87
|
+
request_xml = XeroGateway::Messages::ContactMessage.build_xml(contact)
|
88
|
+
response_xml = http_put("#{@xero_url}/contact", request_xml, {})
|
89
|
+
|
90
|
+
doc = REXML::Document.new(response_xml)
|
91
|
+
|
92
|
+
# Create the response object
|
93
|
+
response = build_response(doc)
|
94
|
+
|
95
|
+
# Add the invoice to the response
|
96
|
+
if response.success?
|
97
|
+
response.response_item = XeroGateway::Messages::ContactMessage.from_xml(REXML::XPath.first(doc, "/Response/Contact"))
|
98
|
+
end
|
99
|
+
|
100
|
+
# Add the request and response XML to the response object
|
101
|
+
response.request_xml = request_xml
|
102
|
+
response.response_xml = response_xml
|
103
|
+
|
104
|
+
response
|
105
|
+
end
|
106
|
+
|
107
|
+
# Retrieves an invoice from Xero based on its GUID
|
108
|
+
#
|
109
|
+
# Usage : get_invoice_by_id("8c69117a-60ae-4d31-9eb4-7f5a76bc4947")
|
110
|
+
def get_invoice_by_id(invoice_id)
|
111
|
+
get_invoice(invoice_id)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Retrieves an invoice from Xero based on its number
|
115
|
+
#
|
116
|
+
# Usage : get_invoice_by_number("OIT00526")
|
117
|
+
def get_invoice_by_number(invoice_number)
|
118
|
+
get_invoice(nil, invoice_number)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Retrieves all invoices from Xero
|
122
|
+
#
|
123
|
+
# Usage : get_invoices
|
124
|
+
# get_invoices(modified_since)
|
125
|
+
def get_invoices(modified_since = nil)
|
126
|
+
request_params = modified_since ? {:modifiedSince => modified_since.strftime("%Y-%m-%d")} : {}
|
127
|
+
|
128
|
+
response_xml = http_get("#{@xero_url}/invoices", request_params)
|
129
|
+
|
130
|
+
doc = REXML::Document.new(response_xml)
|
131
|
+
|
132
|
+
# Create the response object
|
133
|
+
response = build_response(doc)
|
134
|
+
|
135
|
+
# Add the invoices to the response
|
136
|
+
if response.success?
|
137
|
+
response.response_item = []
|
138
|
+
REXML::XPath.first(doc, "/Response/Invoices").children.each do |invoice_element|
|
139
|
+
response.response_item << XeroGateway::Messages::InvoiceMessage.from_xml(invoice_element)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Add the request and response XML to the response object
|
144
|
+
response.request_params = request_params
|
145
|
+
response.response_xml = response_xml
|
146
|
+
response
|
147
|
+
end
|
148
|
+
|
149
|
+
# Creates an invoice in Xero based on an invoice object
|
150
|
+
#
|
151
|
+
# Usage :
|
152
|
+
#
|
153
|
+
# invoice = XeroGateway::Invoice.new({
|
154
|
+
# :invoice_type => "ACCREC",
|
155
|
+
# :due_date => 1.month.from_now,
|
156
|
+
# :invoice_number => "YOUR INVOICE NUMBER",
|
157
|
+
# :reference => "YOUR REFERENCE (NOT NECESSARILY UNIQUE!)",
|
158
|
+
# :includes_tax => false,
|
159
|
+
# :sub_total => 1000,
|
160
|
+
# :total_tax => 125,
|
161
|
+
# :total => 1125
|
162
|
+
# })
|
163
|
+
# invoice.contact = XeroGateway::Contact.new(:name => "THE NAME OF THE CONTACT")
|
164
|
+
# invoice.contact.phone.number = "12345"
|
165
|
+
# invoice.contact.address.line_1 = "LINE 1 OF THE ADDRESS"
|
166
|
+
# invoice.line_items << XeroGateway::LineItem.new(
|
167
|
+
# :description => "THE DESCRIPTION OF THE LINE ITEM",
|
168
|
+
# :unit_amount => 100,
|
169
|
+
# :tax_amount => 12.5,
|
170
|
+
# :line_amount => 125,
|
171
|
+
# :tracking_category => "THE TRACKING CATEGORY FOR THE LINE ITEM",
|
172
|
+
# :tracking_option => "THE TRACKING OPTION FOR THE LINE ITEM"
|
173
|
+
# )
|
174
|
+
#
|
175
|
+
# create_invoice(invoice)
|
176
|
+
def create_invoice(invoice)
|
177
|
+
request_xml = XeroGateway::Messages::InvoiceMessage.build_xml(invoice)
|
178
|
+
response_xml = http_put("#{@xero_url}/invoice", request_xml)
|
179
|
+
|
180
|
+
doc = REXML::Document.new(response_xml)
|
181
|
+
|
182
|
+
# Create the response object
|
183
|
+
response = build_response(doc)
|
184
|
+
|
185
|
+
# Add the invoice to the response
|
186
|
+
if response.success?
|
187
|
+
response.response_item = XeroGateway::Messages::InvoiceMessage.from_xml(REXML::XPath.first(doc, "/Response/Invoice"))
|
188
|
+
end
|
189
|
+
|
190
|
+
# Add the request and response XML to the response object
|
191
|
+
response.request_xml = request_xml
|
192
|
+
response.response_xml = response_xml
|
193
|
+
|
194
|
+
response
|
195
|
+
end
|
196
|
+
|
197
|
+
#
|
198
|
+
# Gets all accounts for a specific organization in Xero.
|
199
|
+
#
|
200
|
+
def get_accounts
|
201
|
+
response_xml = http_get("#{xero_url}/accounts")
|
202
|
+
|
203
|
+
doc = REXML::Document.new(response_xml)
|
204
|
+
|
205
|
+
# Create the response object
|
206
|
+
response = build_response(doc)
|
207
|
+
|
208
|
+
# Add the accounts to the response
|
209
|
+
response.response_item = []
|
210
|
+
REXML::XPath.first(doc, "/Response/Accounts").children.each do |account_element|
|
211
|
+
response.response_item << XeroGateway::Messages::AccountMessage.from_xml(account_element)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Add the request and response XML to the response object
|
215
|
+
response.response_xml = response_xml
|
216
|
+
response
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
private
|
222
|
+
|
223
|
+
def get_invoice(invoice_id = nil, invoice_number = nil)
|
224
|
+
request_params = invoice_id ? {:invoiceID => invoice_id} : {:invoiceNumber => invoice_number}
|
225
|
+
response_xml = http_get("#{@xero_url}/invoice", request_params)
|
226
|
+
|
227
|
+
doc = REXML::Document.new(response_xml)
|
228
|
+
|
229
|
+
# Create the response object
|
230
|
+
response = build_response(doc)
|
231
|
+
|
232
|
+
# Add the invoice to the response
|
233
|
+
response.response_item = XeroGateway::Messages::InvoiceMessage.from_xml(REXML::XPath.first(doc, "/Response/Invoice")) if response.success?
|
234
|
+
|
235
|
+
# Add the request and response XML to the response object
|
236
|
+
response.request_params = request_params
|
237
|
+
response.response_xml = response_xml
|
238
|
+
response
|
239
|
+
end
|
240
|
+
|
241
|
+
def get_contact(contact_id = nil, contact_number = nil)
|
242
|
+
request_params = contact_id ? {:contactID => contact_id} : {:contactNumber => contact_number}
|
243
|
+
response_xml = http_get("#{@xero_url}/contact", request_params)
|
244
|
+
|
245
|
+
doc = REXML::Document.new(response_xml)
|
246
|
+
|
247
|
+
# Create the response object
|
248
|
+
response = build_response(doc)
|
249
|
+
|
250
|
+
# Add the invoice to the response
|
251
|
+
response.response_item = XeroGateway::Messages::ContactMessage.from_xml(REXML::XPath.first(doc, "/Response/Contact")) if response.success?
|
252
|
+
|
253
|
+
# Add the request and response XML to the response object
|
254
|
+
response.request_params = request_params
|
255
|
+
response.response_xml = response_xml
|
256
|
+
response
|
257
|
+
end
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
def build_response(response_document)
|
262
|
+
response = XeroGateway::Response.new({
|
263
|
+
:id => REXML::XPath.first(response_document, "/Response/ID").text,
|
264
|
+
:status => REXML::XPath.first(response_document, "/Response/Status").text,
|
265
|
+
:provider => REXML::XPath.first(response_document, "/Response/ProviderName").text,
|
266
|
+
:date_time => REXML::XPath.first(response_document, "/Response/DateTimeUTC").text,
|
267
|
+
})
|
268
|
+
|
269
|
+
# Add any errors to the response object
|
270
|
+
if !response.success?
|
271
|
+
REXML::XPath.each(response_document, "/Response/Error") do |error|
|
272
|
+
response.errors << {
|
273
|
+
:date_time => REXML::XPath.first(error, "/DateTime").text,
|
274
|
+
:type => REXML::XPath.first(error, "/ExceptionType").text,
|
275
|
+
:message => REXML::XPath.first(error, "/Message").text
|
276
|
+
}
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
response
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|