tlconnor-xero_gateway 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.textile +8 -2
- data/lib/xero_gateway/account.rb +27 -0
- data/lib/xero_gateway/contact.rb +88 -0
- data/lib/xero_gateway/error.rb +19 -0
- data/lib/xero_gateway/gateway.rb +54 -157
- data/lib/xero_gateway/invoice.rb +116 -0
- data/lib/xero_gateway/response.rb +1 -0
- data/lib/xero_gateway/tracking_category.rb +26 -0
- data/lib/xero_gateway.rb +1 -4
- data/test/integration/create_contact_test.rb +3 -1
- data/test/integration/create_invoice_test.rb +3 -1
- data/test/integration/get_accounts_test.rb +3 -2
- data/test/integration/get_contact_test.rb +3 -1
- data/test/integration/get_contacts_test.rb +3 -1
- data/test/integration/get_invoice_test.rb +5 -1
- data/test/integration/get_invoices_test.rb +5 -1
- data/test/integration/get_tracking_categories_test.rb +4 -1
- data/test/integration/update_contact_test.rb +3 -1
- data/test/stub_responses/accounts.xml +1 -0
- data/test/{integration/stub_responses → stub_responses}/contact.xml +0 -0
- data/test/{integration/stub_responses → stub_responses}/contacts.xml +0 -0
- data/test/stub_responses/invalid_api_key_error.xml +1 -0
- data/test/stub_responses/invalid_customer_key_error.xml +1 -0
- data/test/{integration/stub_responses → stub_responses}/invoice.xml +0 -0
- data/test/stub_responses/invoice_not_found_error.xml +1 -0
- data/test/{integration/stub_responses → stub_responses}/invoices.xml +0 -0
- data/test/{integration/stub_responses → stub_responses}/tracking_categories.xml +0 -0
- data/test/stub_responses/unknown_error.xml +1 -0
- data/test/test_helper.rb +65 -1
- data/test/unit/{messages/account_message_test.rb → account_test.rb} +4 -4
- data/test/unit/{messages/contact_message_test.rb → contact_test.rb} +6 -6
- data/test/unit/gateway_test.rb +66 -0
- data/test/unit/{messages/invoice_message_test.rb → invoice_test.rb} +6 -6
- data/test/unit/{messages/tracking_category_message_test.rb → tracking_category_test.rb} +4 -4
- data/xero_gateway.gemspec +18 -17
- metadata +18 -17
- data/lib/xero_gateway/messages/account_message.rb +0 -33
- data/lib/xero_gateway/messages/contact_message.rb +0 -93
- data/lib/xero_gateway/messages/invoice_message.rb +0 -122
- data/lib/xero_gateway/messages/tracking_category_message.rb +0 -32
- data/test/integration/integration_test_methods.rb +0 -64
- data/test/integration/stub_responses/accounts.xml +0 -1
data/CHANGELOG.textile
CHANGED
@@ -1,9 +1,15 @@
|
|
1
|
-
h2. 1.0.
|
1
|
+
h2. 1.0.3, released 09/12/2008
|
2
|
+
|
3
|
+
* Major refactorings to DRY out gateway.rb
|
4
|
+
* Removed all messages classes in favour of invoice.to_xml and Invoice.from_xml(element)
|
5
|
+
* Added unit tests for the handing of errors from Xero
|
6
|
+
|
7
|
+
h2. 1.0.2, released 04/12/2008
|
2
8
|
|
3
9
|
* Added implementation of GET /api.xro/1.0/tracking
|
4
10
|
|
5
11
|
|
6
|
-
h2. 1.0.1,
|
12
|
+
h2. 1.0.1, released 02/12/2008
|
7
13
|
|
8
14
|
* Added implementation of GET /api.xro/1.0/accounts
|
9
15
|
* Replaced Invoice.id, Contact.id etc with Invoice.invoice_id, Contact.contact_id to avoid Object.id errors
|
data/lib/xero_gateway/account.rb
CHANGED
@@ -15,5 +15,32 @@ module XeroGateway
|
|
15
15
|
end
|
16
16
|
return true
|
17
17
|
end
|
18
|
+
|
19
|
+
def to_xml
|
20
|
+
b = Builder::XmlMarkup.new
|
21
|
+
|
22
|
+
b.Account {
|
23
|
+
b.Code self.code
|
24
|
+
b.Name self.name
|
25
|
+
b.Type self.type
|
26
|
+
b.TaxType self.tax_type
|
27
|
+
b.Description self.description
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.from_xml(account_element)
|
32
|
+
account = Account.new
|
33
|
+
account_element.children.each do |element|
|
34
|
+
case(element.name)
|
35
|
+
when "Code" then account.code = element.text
|
36
|
+
when "Name" then account.name = element.text
|
37
|
+
when "Type" then account.type = element.text
|
38
|
+
when "TaxType" then account.tax_type = element.text
|
39
|
+
when "Description" then account.description = element.text
|
40
|
+
end
|
41
|
+
end
|
42
|
+
account
|
43
|
+
end
|
44
|
+
|
18
45
|
end
|
19
46
|
end
|
data/lib/xero_gateway/contact.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module XeroGateway
|
2
2
|
class Contact
|
3
|
+
include Dates
|
4
|
+
|
3
5
|
attr_accessor :contact_id, :contact_number, :status, :name, :email, :addresses, :phones, :updated_at
|
4
6
|
|
5
7
|
def initialize(params = {})
|
@@ -39,5 +41,91 @@ module XeroGateway
|
|
39
41
|
end
|
40
42
|
return true
|
41
43
|
end
|
44
|
+
|
45
|
+
def to_xml
|
46
|
+
b = Builder::XmlMarkup.new
|
47
|
+
|
48
|
+
b.Contact {
|
49
|
+
b.ContactID self.contact_id if self.contact_id
|
50
|
+
b.ContactNumber self.contact_number if self.contact_number
|
51
|
+
b.Name self.name
|
52
|
+
b.EmailAddress self.email if self.email
|
53
|
+
b.Addresses {
|
54
|
+
self.addresses.each do |address|
|
55
|
+
b.Address {
|
56
|
+
b.AddressType address.address_type
|
57
|
+
b.AddressLine1 address.line_1 if address.line_1
|
58
|
+
b.AddressLine2 address.line_2 if address.line_2
|
59
|
+
b.AddressLine3 address.line_3 if address.line_3
|
60
|
+
b.AddressLine4 address.line_4 if address.line_4
|
61
|
+
b.City address.city if address.city
|
62
|
+
b.Region address.region if address.region
|
63
|
+
b.PostalCode address.post_code if address.post_code
|
64
|
+
b.Country address.country if address.country
|
65
|
+
}
|
66
|
+
end
|
67
|
+
}
|
68
|
+
b.Phones {
|
69
|
+
self.phones.each do |phone|
|
70
|
+
b.Phone {
|
71
|
+
b.PhoneType phone.phone_type
|
72
|
+
b.PhoneNumber phone.number
|
73
|
+
b.PhoneAreaCode phone.area_code if phone.area_code
|
74
|
+
b.PhoneCountryCode phone.country_code if phone.country_code
|
75
|
+
}
|
76
|
+
end
|
77
|
+
}
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
# Take a Contact element and convert it into an Contact object
|
82
|
+
def self.from_xml(contact_element)
|
83
|
+
contact = Contact.new
|
84
|
+
contact_element.children.each do |element|
|
85
|
+
case(element.name)
|
86
|
+
when "ContactID" then contact.contact_id = element.text
|
87
|
+
when "ContactNumber" then contact.contact_number = element.text
|
88
|
+
when "ContactStatus" then contact.status = element.text
|
89
|
+
when "Name" then contact.name = element.text
|
90
|
+
when "EmailAddress" then contact.email = element.text
|
91
|
+
when "Addresses" then element.children.each {|address| contact.addresses << parse_address(address)}
|
92
|
+
when "Phones" then element.children.each {|phone| contact.phones << parse_phone(phone)}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
contact
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def self.parse_address(address_element)
|
101
|
+
address = Address.new
|
102
|
+
address_element.children.each do |element|
|
103
|
+
case(element.name)
|
104
|
+
when "AddressType" then address.address_type = element.text
|
105
|
+
when "AddressLine1" then address.line_1 = element.text
|
106
|
+
when "AddressLine2" then address.line_2 = element.text
|
107
|
+
when "AddressLine3" then address.line_3 = element.text
|
108
|
+
when "AddressLine4" then address.line_4 = element.text
|
109
|
+
when "City" then address.city = element.text
|
110
|
+
when "Region" then address.region = element.text
|
111
|
+
when "PostalCode" then address.post_code = element.text
|
112
|
+
when "Country" then address.country = element.text
|
113
|
+
end
|
114
|
+
end
|
115
|
+
address
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.parse_phone(phone_element)
|
119
|
+
phone = Phone.new
|
120
|
+
phone_element.children.each do |element|
|
121
|
+
case(element.name)
|
122
|
+
when "PhoneType" then phone.phone_type = element.text
|
123
|
+
when "PhoneNumber" then phone.number = element.text
|
124
|
+
when "PhoneAreaCode" then phone.area_code = element.text
|
125
|
+
when "PhoneCountryCode" then phone.country_code = element.text
|
126
|
+
end
|
127
|
+
end
|
128
|
+
phone
|
129
|
+
end
|
42
130
|
end
|
43
131
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module XeroGateway
|
2
|
+
class Error
|
3
|
+
attr_accessor :description, :date_time, :type, :message
|
4
|
+
|
5
|
+
def initialize(params = {})
|
6
|
+
params.each do |k,v|
|
7
|
+
self.instance_variable_set("@#{k}", v) ## create and initialize an instance variable for this key/value pair
|
8
|
+
self.send("#{k}=", v)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
[:description, :date_time, :type, :message].each do |field|
|
14
|
+
return false if send(field) != other.send(field)
|
15
|
+
end
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/xero_gateway/gateway.rb
CHANGED
@@ -20,23 +20,7 @@ module XeroGateway
|
|
20
20
|
|
21
21
|
response_xml = http_get("#{@xero_url}/contacts", request_params)
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
# Create the response object
|
26
|
-
response = build_response(doc)
|
27
|
-
|
28
|
-
# Add the contacts to the response
|
29
|
-
if response.success?
|
30
|
-
response.response_item = []
|
31
|
-
REXML::XPath.each(doc, "/Response/Contacts/Contact") do |contact_element|
|
32
|
-
response.response_item << XeroGateway::Messages::ContactMessage.from_xml(contact_element)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
# Add the request and response XML to the response object
|
37
|
-
response.request_params = request_params
|
38
|
-
response.response_xml = response_xml
|
39
|
-
response
|
23
|
+
parse_response(response_xml, :request_params => request_params)
|
40
24
|
end
|
41
25
|
|
42
26
|
# Retrieve a contact from Xero
|
@@ -70,23 +54,10 @@ module XeroGateway
|
|
70
54
|
#
|
71
55
|
# create_contact(contact)
|
72
56
|
def create_contact(contact)
|
73
|
-
request_xml =
|
57
|
+
request_xml = contact.to_xml
|
74
58
|
response_xml = http_put("#{@xero_url}/contact", request_xml, {})
|
75
59
|
|
76
|
-
|
77
|
-
|
78
|
-
# Create the response object
|
79
|
-
response = build_response(doc)
|
80
|
-
|
81
|
-
# Add the invoice to the response
|
82
|
-
if response.success?
|
83
|
-
response.response_item = XeroGateway::Messages::ContactMessage.from_xml(REXML::XPath.first(doc, "/Response/Contact"))
|
84
|
-
end
|
85
|
-
|
86
|
-
# Add the request and response XML to the response object
|
87
|
-
response.request_xml = request_xml
|
88
|
-
response.response_xml = response_xml
|
89
|
-
response
|
60
|
+
parse_response(response_xml, :request_xml => request_xml)
|
90
61
|
end
|
91
62
|
|
92
63
|
#
|
@@ -101,24 +72,10 @@ module XeroGateway
|
|
101
72
|
def update_contact(contact)
|
102
73
|
raise "contact_id or contact_number is required for updating contacts" if contact.contact_id.nil? and contact.contact_number.nil?
|
103
74
|
|
104
|
-
request_xml =
|
75
|
+
request_xml = contact.to_xml
|
105
76
|
response_xml = http_post("#{@xero_url}/contact", request_xml, {})
|
106
77
|
|
107
|
-
|
108
|
-
|
109
|
-
# Create the response object
|
110
|
-
response = build_response(doc)
|
111
|
-
|
112
|
-
# Add the invoice to the response
|
113
|
-
if response.success?
|
114
|
-
response.response_item = XeroGateway::Messages::ContactMessage.from_xml(REXML::XPath.first(doc, "/Response/Contact"))
|
115
|
-
end
|
116
|
-
|
117
|
-
# Add the request and response XML to the response object
|
118
|
-
response.request_xml = request_xml
|
119
|
-
response.response_xml = response_xml
|
120
|
-
|
121
|
-
response
|
78
|
+
parse_response(response_xml, :request_xml => request_xml)
|
122
79
|
end
|
123
80
|
|
124
81
|
# Retrieves an invoice from Xero based on its GUID
|
@@ -144,23 +101,7 @@ module XeroGateway
|
|
144
101
|
|
145
102
|
response_xml = http_get("#{@xero_url}/invoices", request_params)
|
146
103
|
|
147
|
-
|
148
|
-
|
149
|
-
# Create the response object
|
150
|
-
response = build_response(doc)
|
151
|
-
|
152
|
-
# Add the invoices to the response
|
153
|
-
if response.success?
|
154
|
-
response.response_item = []
|
155
|
-
REXML::XPath.first(doc, "/Response/Invoices").children.each do |invoice_element|
|
156
|
-
response.response_item << XeroGateway::Messages::InvoiceMessage.from_xml(invoice_element)
|
157
|
-
end
|
158
|
-
end
|
159
|
-
|
160
|
-
# Add the request and response XML to the response object
|
161
|
-
response.request_params = request_params
|
162
|
-
response.response_xml = response_xml
|
163
|
-
response
|
104
|
+
parse_response(response_xml, :request_params => request_params)
|
164
105
|
end
|
165
106
|
|
166
107
|
# Creates an invoice in Xero based on an invoice object
|
@@ -191,24 +132,10 @@ module XeroGateway
|
|
191
132
|
#
|
192
133
|
# create_invoice(invoice)
|
193
134
|
def create_invoice(invoice)
|
194
|
-
request_xml =
|
135
|
+
request_xml = invoice.to_xml
|
195
136
|
response_xml = http_put("#{@xero_url}/invoice", request_xml)
|
196
137
|
|
197
|
-
|
198
|
-
|
199
|
-
# Create the response object
|
200
|
-
response = build_response(doc)
|
201
|
-
|
202
|
-
# Add the invoice to the response
|
203
|
-
if response.success?
|
204
|
-
response.response_item = XeroGateway::Messages::InvoiceMessage.from_xml(REXML::XPath.first(doc, "/Response/Invoice"))
|
205
|
-
end
|
206
|
-
|
207
|
-
# Add the request and response XML to the response object
|
208
|
-
response.request_xml = request_xml
|
209
|
-
response.response_xml = response_xml
|
210
|
-
|
211
|
-
response
|
138
|
+
parse_response(response_xml, :request_xml => request_xml)
|
212
139
|
end
|
213
140
|
|
214
141
|
#
|
@@ -216,21 +143,7 @@ module XeroGateway
|
|
216
143
|
#
|
217
144
|
def get_accounts
|
218
145
|
response_xml = http_get("#{xero_url}/accounts")
|
219
|
-
|
220
|
-
doc = REXML::Document.new(response_xml)
|
221
|
-
|
222
|
-
# Create the response object
|
223
|
-
response = build_response(doc)
|
224
|
-
|
225
|
-
# Add the accounts to the response
|
226
|
-
response.response_item = []
|
227
|
-
REXML::XPath.first(doc, "/Response/Accounts").children.each do |account_element|
|
228
|
-
response.response_item << XeroGateway::Messages::AccountMessage.from_xml(account_element)
|
229
|
-
end
|
230
|
-
|
231
|
-
# Add the request and response XML to the response object
|
232
|
-
response.response_xml = response_xml
|
233
|
-
response
|
146
|
+
parse_response(response_xml)
|
234
147
|
end
|
235
148
|
|
236
149
|
#
|
@@ -238,21 +151,7 @@ module XeroGateway
|
|
238
151
|
#
|
239
152
|
def get_tracking_categories
|
240
153
|
response_xml = http_get("#{xero_url}/tracking")
|
241
|
-
|
242
|
-
doc = REXML::Document.new(response_xml)
|
243
|
-
|
244
|
-
# Create the response object
|
245
|
-
response = build_response(doc)
|
246
|
-
|
247
|
-
# Add the accounts to the response
|
248
|
-
response.response_item = []
|
249
|
-
REXML::XPath.first(doc, "/Response/Tracking").children.each do |tracking_category_element|
|
250
|
-
response.response_item << XeroGateway::Messages::TrackingCategoryMessage.from_xml(tracking_category_element)
|
251
|
-
end
|
252
|
-
|
253
|
-
# Add the request and response XML to the response object
|
254
|
-
response.response_xml = response_xml
|
255
|
-
response
|
154
|
+
parse_response(response_xml)
|
256
155
|
end
|
257
156
|
|
258
157
|
|
@@ -261,61 +160,59 @@ module XeroGateway
|
|
261
160
|
def get_invoice(invoice_id = nil, invoice_number = nil)
|
262
161
|
request_params = invoice_id ? {:invoiceID => invoice_id} : {:invoiceNumber => invoice_number}
|
263
162
|
response_xml = http_get("#{@xero_url}/invoice", request_params)
|
264
|
-
|
265
|
-
doc = REXML::Document.new(response_xml)
|
266
|
-
|
267
|
-
# Create the response object
|
268
|
-
response = build_response(doc)
|
269
163
|
|
270
|
-
|
271
|
-
response.response_item = XeroGateway::Messages::InvoiceMessage.from_xml(REXML::XPath.first(doc, "/Response/Invoice")) if response.success?
|
272
|
-
|
273
|
-
# Add the request and response XML to the response object
|
274
|
-
response.request_params = request_params
|
275
|
-
response.response_xml = response_xml
|
276
|
-
response
|
164
|
+
parse_response(response_xml, :request_params => request_params)
|
277
165
|
end
|
278
166
|
|
279
167
|
def get_contact(contact_id = nil, contact_number = nil)
|
280
168
|
request_params = contact_id ? {:contactID => contact_id} : {:contactNumber => contact_number}
|
281
169
|
response_xml = http_get("#{@xero_url}/contact", request_params)
|
282
|
-
|
283
|
-
doc = REXML::Document.new(response_xml)
|
284
|
-
|
285
|
-
# Create the response object
|
286
|
-
response = build_response(doc)
|
287
170
|
|
288
|
-
|
289
|
-
response.response_item = XeroGateway::Messages::ContactMessage.from_xml(REXML::XPath.first(doc, "/Response/Contact")) if response.success?
|
290
|
-
|
291
|
-
# Add the request and response XML to the response object
|
292
|
-
response.request_params = request_params
|
293
|
-
response.response_xml = response_xml
|
294
|
-
response
|
171
|
+
parse_response(response_xml, :request_params => request_params)
|
295
172
|
end
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
response = XeroGateway::Response.new
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
173
|
+
|
174
|
+
def parse_response(response_xml, request = {})
|
175
|
+
doc = REXML::Document.new(response_xml)
|
176
|
+
|
177
|
+
response = XeroGateway::Response.new
|
178
|
+
|
179
|
+
response_element = REXML::XPath.first(doc, "/Response")
|
180
|
+
|
181
|
+
if response_element.nil?
|
182
|
+
# The Xero API documentation states that it will always return valid XML with
|
183
|
+
# a response element, unless an invalid API key is provided.
|
184
|
+
response.status = "INVALID_API_KEY"
|
185
|
+
else
|
186
|
+
response_element.children.each do |element|
|
187
|
+
case(element.name)
|
188
|
+
when "ID" then response.response_id = element.text
|
189
|
+
when "Status" then response.status = element.text
|
190
|
+
when "ProviderName" then response.provider = element.text
|
191
|
+
when "DateTimeUTC" then response.date_time = element.text
|
192
|
+
when "Contact" then response.response_item = Contact.from_xml(element)
|
193
|
+
when "Invoice" then response.response_item = Invoice.from_xml(element)
|
194
|
+
when "Contacts" then element.children.each {|child| response.response_item << Contact.from_xml(child) }
|
195
|
+
when "Invoices" then element.children.each {|child| response.response_item << Invoice.from_xml(child) }
|
196
|
+
when "Accounts" then element.children.each {|child| response.response_item << Account.from_xml(child) }
|
197
|
+
when "Tracking" then element.children.each {|child| response.response_item << TrackingCategory.from_xml(child) }
|
198
|
+
when "Errors" then element.children.each { |error| parse_error(error, response) }
|
199
|
+
end
|
315
200
|
end
|
316
201
|
end
|
317
|
-
|
318
|
-
response
|
202
|
+
|
203
|
+
response.request_params = request[:request_params]
|
204
|
+
response.request_xml = request[:request_xml]
|
205
|
+
response.response_xml = response_xml
|
206
|
+
response
|
207
|
+
end
|
208
|
+
|
209
|
+
def parse_error(error_element, response)
|
210
|
+
response.errors << Error.new(
|
211
|
+
:description => REXML::XPath.first(error_element, "Description").text,
|
212
|
+
:date_time => REXML::XPath.first(error_element, "//DateTime").text,
|
213
|
+
:type => REXML::XPath.first(error_element, "//ExceptionType").text,
|
214
|
+
:message => REXML::XPath.first(error_element, "//Message").text
|
215
|
+
)
|
319
216
|
end
|
320
|
-
end
|
217
|
+
end
|
321
218
|
end
|
data/lib/xero_gateway/invoice.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module XeroGateway
|
2
2
|
class Invoice
|
3
|
+
include Dates
|
4
|
+
include Money
|
5
|
+
|
3
6
|
# All accessible fields
|
4
7
|
attr_accessor :invoice_id, :invoice_number, :invoice_type, :invoice_status, :date, :due_date, :reference, :tax_inclusive, :includes_tax, :sub_total, :total_tax, :total, :line_items, :contact
|
5
8
|
|
@@ -28,5 +31,118 @@ module XeroGateway
|
|
28
31
|
end
|
29
32
|
return true
|
30
33
|
end
|
34
|
+
|
35
|
+
def to_xml
|
36
|
+
b = Builder::XmlMarkup.new
|
37
|
+
|
38
|
+
b.Invoice {
|
39
|
+
b.InvoiceType self.invoice_type
|
40
|
+
b.Contact {
|
41
|
+
b.ContactID self.contact.contact_id if self.contact.contact_id
|
42
|
+
b.Name self.contact.name
|
43
|
+
b.EmailAddress self.contact.email if self.contact.email
|
44
|
+
b.Addresses {
|
45
|
+
self.contact.addresses.each do |address|
|
46
|
+
b.Address {
|
47
|
+
b.AddressType address.address_type
|
48
|
+
b.AddressLine1 address.line_1 if address.line_1
|
49
|
+
b.AddressLine2 address.line_2 if address.line_2
|
50
|
+
b.AddressLine3 address.line_3 if address.line_3
|
51
|
+
b.AddressLine4 address.line_4 if address.line_4
|
52
|
+
b.City address.city if address.city
|
53
|
+
b.Region address.region if address.region
|
54
|
+
b.PostalCode address.post_code if address.post_code
|
55
|
+
b.Country address.country if address.country
|
56
|
+
}
|
57
|
+
end
|
58
|
+
}
|
59
|
+
b.Phones {
|
60
|
+
self.contact.phones.each do |phone|
|
61
|
+
b.Phone {
|
62
|
+
b.PhoneType phone.phone_type
|
63
|
+
b.PhoneNumber phone.number
|
64
|
+
b.PhoneAreaCode phone.area_code if phone.area_code
|
65
|
+
b.PhoneCountryCode phone.country_code if phone.country_code
|
66
|
+
}
|
67
|
+
end
|
68
|
+
}
|
69
|
+
}
|
70
|
+
b.InvoiceDate Invoice.format_date_time(self.date)
|
71
|
+
b.DueDate Invoice.format_date_time(self.due_date) if self.due_date
|
72
|
+
b.InvoiceNumber self.invoice_number
|
73
|
+
b.Reference self.reference if self.reference
|
74
|
+
b.TaxInclusive self.tax_inclusive if self.tax_inclusive
|
75
|
+
b.IncludesTax self.includes_tax
|
76
|
+
b.SubTotal Invoice.format_money(self.sub_total) if self.sub_total
|
77
|
+
b.TotalTax Invoice.format_money(self.total_tax) if self.total_tax
|
78
|
+
b.Total Invoice.format_money(self.total) if self.total
|
79
|
+
b.LineItems {
|
80
|
+
self.line_items.each do |line_item|
|
81
|
+
b.LineItem {
|
82
|
+
b.Description line_item.description
|
83
|
+
b.Quantity line_item.quantity if line_item.quantity
|
84
|
+
b.UnitAmount Invoice.format_money(line_item.unit_amount)
|
85
|
+
b.TaxType line_item.tax_type if line_item.tax_type
|
86
|
+
b.TaxAmount Invoice.format_money(line_item.tax_amount) if line_item.tax_amount
|
87
|
+
b.LineAmount Invoice.format_money(line_item.line_amount)
|
88
|
+
b.AccountCode line_item.account_code || 200
|
89
|
+
b.Tracking {
|
90
|
+
b.TrackingCategory {
|
91
|
+
b.Name line_item.tracking_category
|
92
|
+
b.Option line_item.tracking_option
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
end
|
97
|
+
}
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.from_xml(invoice_element)
|
102
|
+
invoice = Invoice.new
|
103
|
+
invoice_element.children.each do |element|
|
104
|
+
case(element.name)
|
105
|
+
when "InvoiceStatus" then invoice.invoice_status = element.text
|
106
|
+
when "InvoiceID" then invoice.invoice_id = element.text
|
107
|
+
when "InvoiceNumber" then invoice.invoice_number = element.text
|
108
|
+
when "InvoiceType" then invoice.invoice_type = element.text
|
109
|
+
when "InvoiceDate" then invoice.date = parse_date_time(element.text)
|
110
|
+
when "DueDate" then invoice.due_date = parse_date_time(element.text)
|
111
|
+
when "Reference" then invoice.reference = element.text
|
112
|
+
when "TaxInclusive" then invoice.tax_inclusive = (element.text == "true")
|
113
|
+
when "IncludesTax" then invoice.includes_tax = (element.text == "true")
|
114
|
+
when "SubTotal" then invoice.sub_total = BigDecimal.new(element.text)
|
115
|
+
when "TotalTax" then invoice.total_tax = BigDecimal.new(element.text)
|
116
|
+
when "Total" then invoice.total = BigDecimal.new(element.text)
|
117
|
+
when "Contact" then invoice.contact = Contact.from_xml(element)
|
118
|
+
when "LineItems" then element.children.each {|line_item| invoice.line_items << parse_line_item(line_item)}
|
119
|
+
end
|
120
|
+
end
|
121
|
+
invoice
|
122
|
+
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def self.parse_line_item(line_item_element)
|
127
|
+
line_item = LineItem.new
|
128
|
+
line_item_element.children.each do |element|
|
129
|
+
case(element.name)
|
130
|
+
when "LineItemID" then line_item.line_item_id = element.text
|
131
|
+
when "Description" then line_item.description = element.text
|
132
|
+
when "Quantity" then line_item.quantity = element.text.to_i
|
133
|
+
when "UnitAmount" then line_item.unit_amount = BigDecimal.new(element.text)
|
134
|
+
when "TaxType" then line_item.tax_type = element.text
|
135
|
+
when "TaxAmount" then line_item.tax_amount = BigDecimal.new(element.text)
|
136
|
+
when "LineAmount" then line_item.line_amount = BigDecimal.new(element.text)
|
137
|
+
when "AccountCode" then line_item.account_code = element.text
|
138
|
+
when "Tracking" then
|
139
|
+
if element.elements['TrackingCategory']
|
140
|
+
line_item.tracking_category = element.elements['TrackingCategory/Name'].text
|
141
|
+
line_item.tracking_option = element.elements['TrackingCategory/Option'].text
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
line_item
|
146
|
+
end
|
31
147
|
end
|
32
148
|
end
|
@@ -16,5 +16,31 @@ module XeroGateway
|
|
16
16
|
end
|
17
17
|
return true
|
18
18
|
end
|
19
|
+
|
20
|
+
def to_xml
|
21
|
+
b = Builder::XmlMarkup.new
|
22
|
+
|
23
|
+
b.TrackingCategory {
|
24
|
+
b.Name self.name
|
25
|
+
b.Options {
|
26
|
+
self.options.each do |option|
|
27
|
+
b.Option {
|
28
|
+
b.Name option
|
29
|
+
}
|
30
|
+
end
|
31
|
+
}
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.from_xml(tracking_category_element)
|
36
|
+
tracking_category = TrackingCategory.new
|
37
|
+
tracking_category_element.children.each do |element|
|
38
|
+
case(element.name)
|
39
|
+
when "Name" then tracking_category.name = element.text
|
40
|
+
when "Options" then element.children.each {|option| tracking_category.options << option.children.first.text}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
tracking_category
|
44
|
+
end
|
19
45
|
end
|
20
46
|
end
|
data/lib/xero_gateway.rb
CHANGED
@@ -15,9 +15,6 @@ require File.dirname(__FILE__) + "/xero_gateway/contact"
|
|
15
15
|
require File.dirname(__FILE__) + "/xero_gateway/address"
|
16
16
|
require File.dirname(__FILE__) + "/xero_gateway/phone"
|
17
17
|
require File.dirname(__FILE__) + "/xero_gateway/account"
|
18
|
+
require File.dirname(__FILE__) + "/xero_gateway/error"
|
18
19
|
require File.dirname(__FILE__) + "/xero_gateway/tracking_category"
|
19
|
-
require File.dirname(__FILE__) + "/xero_gateway/messages/contact_message"
|
20
|
-
require File.dirname(__FILE__) + "/xero_gateway/messages/invoice_message"
|
21
|
-
require File.dirname(__FILE__) + "/xero_gateway/messages/account_message"
|
22
|
-
require File.dirname(__FILE__) + "/xero_gateway/messages/tracking_category_message"
|
23
20
|
require File.dirname(__FILE__) + "/xero_gateway/gateway"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../test_helper'
|
2
2
|
|
3
3
|
class CreateContactTest < Test::Unit::TestCase
|
4
|
-
include
|
4
|
+
include TestHelper
|
5
5
|
|
6
6
|
def setup
|
7
7
|
@gateway = XeroGateway::Gateway.new(
|
@@ -22,6 +22,8 @@ class CreateContactTest < Test::Unit::TestCase
|
|
22
22
|
result = @gateway.create_contact(example_contact)
|
23
23
|
assert result.success?
|
24
24
|
assert !result.contact.contact_id.nil?
|
25
|
+
assert !result.request_xml.nil?
|
26
|
+
assert !result.response_xml.nil?
|
25
27
|
assert_equal result.contact.name, example_contact.name
|
26
28
|
end
|
27
29
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../test_helper'
|
2
2
|
|
3
3
|
class CreateInvoiceTest < Test::Unit::TestCase
|
4
|
-
include
|
4
|
+
include TestHelper
|
5
5
|
|
6
6
|
def setup
|
7
7
|
@gateway = XeroGateway::Gateway.new(
|
@@ -21,6 +21,8 @@ class CreateInvoiceTest < Test::Unit::TestCase
|
|
21
21
|
|
22
22
|
result = @gateway.create_invoice(example_invoice)
|
23
23
|
assert result.success?
|
24
|
+
assert !result.request_xml.nil?
|
25
|
+
assert !result.response_xml.nil?
|
24
26
|
assert !result.invoice.invoice_id.nil?
|
25
27
|
assert result.invoice.invoice_number == example_invoice.invoice_number
|
26
28
|
end
|