xero_gateway 2.1.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -11
- data/README.md +212 -0
- data/Rakefile +0 -1
- data/lib/oauth/oauth_consumer.rb +25 -9
- data/lib/xero_gateway.rb +5 -1
- data/lib/xero_gateway/address.rb +29 -27
- data/lib/xero_gateway/bank_transaction.rb +11 -3
- data/lib/xero_gateway/base_record.rb +97 -0
- data/lib/xero_gateway/contact_group.rb +87 -0
- data/lib/xero_gateway/currency.rb +8 -54
- data/lib/xero_gateway/dates.rb +4 -0
- data/lib/xero_gateway/exceptions.rb +14 -13
- data/lib/xero_gateway/gateway.rb +90 -5
- data/lib/xero_gateway/http.rb +16 -8
- data/lib/xero_gateway/invoice.rb +9 -3
- data/lib/xero_gateway/item.rb +27 -0
- data/lib/xero_gateway/line_item_calculations.rb +3 -3
- data/lib/xero_gateway/manual_journal.rb +5 -2
- data/lib/xero_gateway/organisation.rb +22 -73
- data/lib/xero_gateway/payment.rb +22 -9
- data/lib/xero_gateway/phone.rb +2 -0
- data/lib/xero_gateway/report.rb +95 -0
- data/lib/xero_gateway/response.rb +12 -7
- data/lib/xero_gateway/tax_rate.rb +13 -61
- data/lib/xero_gateway/tracking_category.rb +39 -13
- data/lib/xero_gateway/version.rb +3 -0
- data/test/integration/get_items_test.rb +25 -0
- data/test/integration/get_payments_test.rb +54 -0
- data/test/test_helper.rb +51 -16
- data/test/unit/address_test.rb +34 -0
- data/test/unit/bank_transaction_test.rb +7 -0
- data/test/unit/contact_group_test.rb +47 -0
- data/test/unit/contact_test.rb +35 -16
- data/test/unit/credit_note_test.rb +2 -2
- data/test/unit/gateway_test.rb +170 -1
- data/test/unit/invoice_test.rb +27 -7
- data/test/unit/item_test.rb +51 -0
- data/test/unit/organisation_test.rb +1 -0
- data/test/unit/payment_test.rb +18 -11
- data/test/unit/report_test.rb +78 -0
- data/xero_gateway.gemspec +29 -13
- metadata +176 -89
- data/README.textile +0 -357
- data/init.rb +0 -1
data/lib/xero_gateway/http.rb
CHANGED
@@ -79,15 +79,20 @@ module XeroGateway
|
|
79
79
|
handle_oauth_error!(response)
|
80
80
|
when 404
|
81
81
|
handle_object_not_found!(response, url)
|
82
|
+
when 500..504
|
83
|
+
# Xero sends certain oauth errors back as 500 errors
|
84
|
+
handle_oauth_error!(response)
|
82
85
|
else
|
83
86
|
raise "Unknown response code: #{response.code.to_i}"
|
84
87
|
end
|
85
88
|
end
|
86
89
|
|
87
90
|
def handle_oauth_error!(response)
|
88
|
-
error_details = CGI.parse(response.plain_body)
|
91
|
+
error_details = CGI.parse(response.plain_body.strip)
|
89
92
|
description = error_details["oauth_problem_advice"].first
|
90
93
|
|
94
|
+
description = "No description found: #{response.plain_body}" if description.blank?
|
95
|
+
|
91
96
|
# see http://oauth.pbworks.com/ProblemReporting
|
92
97
|
# In addition to token_expired and token_rejected, Xero also returns
|
93
98
|
# 'rate limit exceeded' when more than 60 requests have been made in
|
@@ -97,7 +102,9 @@ module XeroGateway
|
|
97
102
|
when "consumer_key_unknown" then raise OAuth::TokenInvalid.new(description)
|
98
103
|
when "token_rejected" then raise OAuth::TokenInvalid.new(description)
|
99
104
|
when "rate limit exceeded" then raise OAuth::RateLimitExceeded.new(description)
|
100
|
-
else
|
105
|
+
else
|
106
|
+
message = (error_details["oauth_problem"].first || "Unknown Error") + ': ' + description
|
107
|
+
raise OAuth::UnknownError.new(message)
|
101
108
|
end
|
102
109
|
end
|
103
110
|
|
@@ -111,26 +118,27 @@ module XeroGateway
|
|
111
118
|
|
112
119
|
doc = REXML::Document.new(raw_response, :ignore_whitespace_nodes => :all)
|
113
120
|
|
114
|
-
if doc.root.name
|
121
|
+
if doc.root.nil? || doc.root.name != "ApiException"
|
122
|
+
|
123
|
+
raise "Unparseable 400 Response: #{raw_response}"
|
124
|
+
|
125
|
+
else
|
115
126
|
|
116
127
|
raise ApiException.new(doc.root.elements["Type"].text,
|
117
128
|
doc.root.elements["Message"].text,
|
118
129
|
request_xml,
|
119
130
|
raw_response)
|
120
131
|
|
121
|
-
else
|
122
|
-
|
123
|
-
raise "Unparseable 400 Response: #{raw_response}"
|
124
|
-
|
125
132
|
end
|
126
|
-
|
127
133
|
end
|
128
134
|
|
129
135
|
def handle_object_not_found!(response, request_url)
|
130
136
|
case(request_url)
|
131
137
|
when /Invoices/ then raise InvoiceNotFoundError.new("Invoice not found in Xero.")
|
132
138
|
when /BankTransactions/ then raise BankTransactionNotFoundError.new("Bank Transaction not found in Xero.")
|
139
|
+
when /Payments/ then raise PaymentNotFoundError.new("Payments not found in Xero.")
|
133
140
|
when /CreditNotes/ then raise CreditNoteNotFoundError.new("Credit Note not found in Xero.")
|
141
|
+
when /ManualJournals/ then raise ManualJournalNotFoundError.new("Manual Journal not found in Xero.")
|
134
142
|
else raise ObjectNotFound.new(request_url)
|
135
143
|
end
|
136
144
|
end
|
data/lib/xero_gateway/invoice.rb
CHANGED
@@ -37,9 +37,8 @@ module XeroGateway
|
|
37
37
|
attr_accessor :line_items_downloaded
|
38
38
|
|
39
39
|
# All accessible fields
|
40
|
-
attr_accessor :invoice_id, :invoice_number, :invoice_type, :invoice_status, :date, :due_date, :reference, :branding_theme_id, :line_amount_types, :currency_code, :line_items, :contact, :payments, :fully_paid_on, :amount_due, :amount_paid, :amount_credited, :sent_to_contact, :url
|
40
|
+
attr_accessor :invoice_id, :invoice_number, :invoice_type, :invoice_status, :date, :due_date, :reference, :branding_theme_id, :line_amount_types, :currency_code, :line_items, :contact, :payments, :fully_paid_on, :amount_due, :amount_paid, :amount_credited, :sent_to_contact, :url, :updated_date_utc
|
41
41
|
|
42
|
-
|
43
42
|
def initialize(params = {})
|
44
43
|
@errors ||= []
|
45
44
|
@payments ||= []
|
@@ -123,7 +122,13 @@ module XeroGateway
|
|
123
122
|
def line_items_downloaded?
|
124
123
|
@line_items_downloaded
|
125
124
|
end
|
126
|
-
|
125
|
+
|
126
|
+
%w(sub_total tax_total total).each do |line_item_total_type|
|
127
|
+
define_method("#{line_item_total_type}=") do |new_total|
|
128
|
+
instance_variable_set("@#{line_item_total_type}", new_total) unless line_items_downloaded?
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
127
132
|
# If line items are not downloaded, then attempt a download now (if this record was found to begin with).
|
128
133
|
def line_items
|
129
134
|
if line_items_downloaded?
|
@@ -215,6 +220,7 @@ module XeroGateway
|
|
215
220
|
when "Contact" then invoice.contact = Contact.from_xml(element)
|
216
221
|
when "Date" then invoice.date = parse_date(element.text)
|
217
222
|
when "DueDate" then invoice.due_date = parse_date(element.text)
|
223
|
+
when "UpdatedDateUTC" then invoice.updated_date_utc = parse_date(element.text)
|
218
224
|
when "Status" then invoice.invoice_status = element.text
|
219
225
|
when "Reference" then invoice.reference = element.text
|
220
226
|
when "BrandingThemeID" then invoice.branding_theme_id = element.text
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module XeroGateway
|
2
|
+
class Item < BaseRecord
|
3
|
+
attributes({
|
4
|
+
"ItemID" => :string,
|
5
|
+
"Code" => :string,
|
6
|
+
"InventoryAssetAccountCode" => :string,
|
7
|
+
"Name" => :string,
|
8
|
+
"IsSold" => :boolean,
|
9
|
+
"IsPurchased" => :boolean,
|
10
|
+
"Description" => :string,
|
11
|
+
"PurchaseDescription" => :string,
|
12
|
+
"IsTrackedAsInventory" => :boolean,
|
13
|
+
"TotalCostPool" => :float,
|
14
|
+
"QuantityOnHand" => :integer,
|
15
|
+
|
16
|
+
"SalesDetails" => {
|
17
|
+
"UnitPrice" => :float,
|
18
|
+
"AccountCode" => :string
|
19
|
+
},
|
20
|
+
|
21
|
+
"PurchaseDetails" => {
|
22
|
+
"UnitPrice" => :float,
|
23
|
+
"AccountCode" => :string
|
24
|
+
}
|
25
|
+
})
|
26
|
+
end
|
27
|
+
end
|
@@ -20,7 +20,7 @@ module XeroGateway
|
|
20
20
|
|
21
21
|
# Calculate the sub_total as the SUM(line_item.line_amount).
|
22
22
|
def sub_total
|
23
|
-
line_items.inject(BigDecimal.new('0')) { | sum, line_item | sum + BigDecimal.new(line_item.line_amount.to_s) }
|
23
|
+
!line_items_downloaded? && @sub_total || line_items.inject(BigDecimal.new('0')) { | sum, line_item | sum + BigDecimal.new(line_item.line_amount.to_s) }
|
24
24
|
end
|
25
25
|
|
26
26
|
# Deprecated (but API for setter remains).
|
@@ -32,7 +32,7 @@ module XeroGateway
|
|
32
32
|
|
33
33
|
# Calculate the total_tax as the SUM(line_item.tax_amount).
|
34
34
|
def total_tax
|
35
|
-
line_items.inject(BigDecimal.new('0')) { | sum, line_item | sum + BigDecimal.new(line_item.tax_amount.to_s) }
|
35
|
+
!line_items_downloaded? && @total_tax || line_items.inject(BigDecimal.new('0')) { | sum, line_item | sum + BigDecimal.new(line_item.tax_amount.to_s) }
|
36
36
|
end
|
37
37
|
|
38
38
|
# Deprecated (but API for setter remains).
|
@@ -44,7 +44,7 @@ module XeroGateway
|
|
44
44
|
|
45
45
|
# Calculate the toal as sub_total + total_tax.
|
46
46
|
def total
|
47
|
-
sub_total + total_tax
|
47
|
+
!line_items_downloaded? && @total || (sub_total + total_tax)
|
48
48
|
end
|
49
49
|
|
50
50
|
end
|
@@ -2,6 +2,9 @@ module XeroGateway
|
|
2
2
|
class ManualJournal
|
3
3
|
include Dates
|
4
4
|
|
5
|
+
class Error < RuntimeError; end
|
6
|
+
class NoGatewayError < Error; end
|
7
|
+
|
5
8
|
GUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/ unless defined?(GUID_REGEX)
|
6
9
|
|
7
10
|
STATUSES = {
|
@@ -121,7 +124,7 @@ module XeroGateway
|
|
121
124
|
def to_xml(b = Builder::XmlMarkup.new)
|
122
125
|
b.ManualJournal {
|
123
126
|
b.ManualJournalID manual_journal_id if manual_journal_id
|
124
|
-
b.Narration narration
|
127
|
+
b.Narration narration
|
125
128
|
b.JournalLines {
|
126
129
|
self.journal_lines.each do |journal_line|
|
127
130
|
journal_line.to_xml(b)
|
@@ -160,4 +163,4 @@ module XeroGateway
|
|
160
163
|
end
|
161
164
|
|
162
165
|
end
|
163
|
-
end
|
166
|
+
end
|
@@ -1,75 +1,24 @@
|
|
1
1
|
module XeroGateway
|
2
|
-
class Organisation
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
attr_accessor *ATTRS.keys.map(&:underscore)
|
25
|
-
|
26
|
-
def initialize(params = {})
|
27
|
-
params.each do |k,v|
|
28
|
-
self.send("#{k}=", v)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def ==(other)
|
33
|
-
ATTRS.keys.map(&:underscore).each do |field|
|
34
|
-
return false if send(field) != other.send(field)
|
35
|
-
end
|
36
|
-
return true
|
37
|
-
end
|
38
|
-
|
39
|
-
def to_xml
|
40
|
-
b = Builder::XmlMarkup.new
|
41
|
-
|
42
|
-
b.Organisation do
|
43
|
-
ATTRS.keys.each do |attr|
|
44
|
-
eval("b.#{attr} '#{self.send(attr.underscore.to_sym)}'")
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.from_xml(organisation_element)
|
50
|
-
Organisation.new.tap do |org|
|
51
|
-
organisation_element.children.each do |element|
|
52
|
-
|
53
|
-
attribute = element.name
|
54
|
-
underscored_attribute = element.name.underscore
|
55
|
-
|
56
|
-
if ATTRS.keys.include?(attribute)
|
57
|
-
|
58
|
-
case (ATTRS[attribute])
|
59
|
-
when :boolean then org.send("#{underscored_attribute}=", (element.text == "true"))
|
60
|
-
when :float then org.send("#{underscored_attribute}=", element.text.to_f)
|
61
|
-
else org.send("#{underscored_attribute}=", element.text)
|
62
|
-
end
|
63
|
-
|
64
|
-
else
|
65
|
-
|
66
|
-
warn "Ignoring unknown attribute: #{attribute}"
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
2
|
+
class Organisation < BaseRecord
|
3
|
+
attributes({
|
4
|
+
"Name" => :string, # Display name of organisation shown in Xero
|
5
|
+
"LegalName" => :string, # Organisation name shown on Reports
|
6
|
+
"PaysTax" => :boolean, # Boolean to describe if organisation is registered with a local tax authority i.e. true, false
|
7
|
+
"Version" => :string, # See Version Types
|
8
|
+
"BaseCurrency" => :string, # Default currency for organisation. See Currency types
|
9
|
+
"OrganisationType" => :string, # only returned for "real" (i.e non-demo) companies
|
10
|
+
"OrganisationStatus" => :string,
|
11
|
+
"IsDemoCompany" => :boolean,
|
12
|
+
"APIKey" => :string, # returned if organisations are linked via Xero Network
|
13
|
+
"CountryCode" => :string,
|
14
|
+
"TaxNumber" => :string,
|
15
|
+
"FinancialYearEndDay" => :string,
|
16
|
+
"FinancialYearEndMonth" => :string,
|
17
|
+
"PeriodLockDate" => :string,
|
18
|
+
"CreatedDateUTC" => :string,
|
19
|
+
"ShortCode" => :string,
|
20
|
+
"Timezone" => :string,
|
21
|
+
"LineOfBusiness" => :string
|
22
|
+
})
|
74
23
|
end
|
75
|
-
end
|
24
|
+
end
|
data/lib/xero_gateway/payment.rb
CHANGED
@@ -7,7 +7,8 @@ module XeroGateway
|
|
7
7
|
attr_reader :errors
|
8
8
|
|
9
9
|
# All accessible fields
|
10
|
-
attr_accessor :invoice_id, :invoice_number, :account_id, :code, :payment_id, :date, :amount, :reference, :currency_rate
|
10
|
+
attr_accessor :invoice_id, :invoice_number, :account_id, :code, :payment_id, :payment_type, :date, :amount, :reference, :currency_rate, :updated_at, :reconciled
|
11
|
+
alias_method :reconciled?, :reconciled
|
11
12
|
|
12
13
|
def initialize(params = {})
|
13
14
|
@errors ||= []
|
@@ -21,13 +22,18 @@ module XeroGateway
|
|
21
22
|
payment = Payment.new
|
22
23
|
payment_element.children.each do | element |
|
23
24
|
case element.name
|
24
|
-
when 'PaymentID'
|
25
|
-
when '
|
26
|
-
when '
|
27
|
-
when '
|
28
|
-
when '
|
29
|
-
when '
|
30
|
-
when '
|
25
|
+
when 'PaymentID' then payment.payment_id = element.text
|
26
|
+
when 'PaymentType' then payment.payment_type = element.text
|
27
|
+
when 'Date' then payment.date = parse_date_time(element.text)
|
28
|
+
when 'UpdatedDateUTC' then payment.updated_at = parse_date_time(element.text)
|
29
|
+
when 'Amount' then payment.amount = BigDecimal.new(element.text)
|
30
|
+
when 'Reference' then payment.reference = element.text
|
31
|
+
when 'CurrencyRate' then payment.currency_rate = BigDecimal.new(element.text)
|
32
|
+
when 'Invoice'
|
33
|
+
payment.invoice_id = element.elements["//InvoiceID"].text
|
34
|
+
payment.invoice_number = element.elements["//InvoiceNumber"].text
|
35
|
+
when 'IsReconciled' then payment.reconciled = (element.text == "true")
|
36
|
+
when 'Account' then payment.account_id = element.elements["//AccountID"].text
|
31
37
|
end
|
32
38
|
end
|
33
39
|
payment
|
@@ -43,6 +49,9 @@ module XeroGateway
|
|
43
49
|
def to_xml(b = Builder::XmlMarkup.new)
|
44
50
|
b.Payment do
|
45
51
|
|
52
|
+
b.PaymentID self.payment_id if self.payment_id
|
53
|
+
b.PaymentType self.payment_type if self.payment_type
|
54
|
+
|
46
55
|
if self.invoice_id || self.invoice_number
|
47
56
|
b.Invoice do |i|
|
48
57
|
i.InvoiceID self.invoice_id if self.invoice_id
|
@@ -61,10 +70,14 @@ module XeroGateway
|
|
61
70
|
b.CurrencyRate self.currency_rate if self.currency_rate
|
62
71
|
b.Reference self.reference if self.reference
|
63
72
|
|
73
|
+
if self.reconciled?
|
74
|
+
b.IsReconciled true
|
75
|
+
end
|
76
|
+
|
64
77
|
b.Date self.class.format_date(self.date || Date.today)
|
65
78
|
end
|
66
79
|
end
|
67
80
|
|
68
81
|
|
69
82
|
end
|
70
|
-
end
|
83
|
+
end
|
data/lib/xero_gateway/phone.rb
CHANGED
@@ -0,0 +1,95 @@
|
|
1
|
+
module XeroGateway
|
2
|
+
class Report
|
3
|
+
include Money
|
4
|
+
include Dates
|
5
|
+
|
6
|
+
attr_reader :errors
|
7
|
+
attr_accessor :report_id, :report_name, :report_type, :report_titles, :report_date, :updated_at,
|
8
|
+
:body, :column_names
|
9
|
+
|
10
|
+
def initialize(params={})
|
11
|
+
@errors ||= []
|
12
|
+
@report_titles ||= []
|
13
|
+
@body ||= []
|
14
|
+
|
15
|
+
params.each do |k,v|
|
16
|
+
self.send("#{k}=", v)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.from_xml(report_element)
|
21
|
+
report = Report.new
|
22
|
+
report_element.children.each do | element |
|
23
|
+
case element.name
|
24
|
+
when 'ReportID' then report.report_id = element.text
|
25
|
+
when 'ReportName' then report.report_name = element.text
|
26
|
+
when 'ReportType' then report.report_type = element.text
|
27
|
+
when 'ReportTitles'
|
28
|
+
each_title(element) do |title|
|
29
|
+
report.report_titles << title
|
30
|
+
end
|
31
|
+
when 'ReportDate' then report.report_date = Date.parse(element.text)
|
32
|
+
when 'UpdatedDateUTC' then report.updated_at = parse_date_time_utc(element.text)
|
33
|
+
when 'Rows'
|
34
|
+
report.column_names ||= find_body_column_names(element)
|
35
|
+
each_row_content(element) do |content_hash|
|
36
|
+
report.body << OpenStruct.new(content_hash)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
report
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def self.each_row_content(xml_element, &block)
|
46
|
+
column_names = find_body_column_names(xml_element).keys
|
47
|
+
xpath_body = REXML::XPath.first(xml_element, "//RowType[text()='Section']").parent
|
48
|
+
rows_contents = []
|
49
|
+
xpath_body.elements.each("Rows/Row") do |xpath_cells|
|
50
|
+
values = find_body_cell_values(xpath_cells)
|
51
|
+
content_hash = Hash[column_names.zip values]
|
52
|
+
rows_contents << content_hash
|
53
|
+
yield content_hash if block_given?
|
54
|
+
end
|
55
|
+
rows_contents
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.each_title(xml_element, &block)
|
59
|
+
xpath_titles = REXML::XPath.first(xml_element, "//ReportTitles")
|
60
|
+
xpath_titles.elements.each("//ReportTitle") do |xpath_title|
|
61
|
+
title = xpath_title.text.strip
|
62
|
+
yield title if block_given?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.find_body_cell_values(xml_cells)
|
67
|
+
values = []
|
68
|
+
xml_cells.elements.each("Cells/Cell") do |xml_cell|
|
69
|
+
if value = xml_cell.children.first # finds <Value>...</Value>
|
70
|
+
values << value.text.try(:strip)
|
71
|
+
next
|
72
|
+
end
|
73
|
+
values << nil
|
74
|
+
end
|
75
|
+
values
|
76
|
+
end
|
77
|
+
|
78
|
+
# returns something like { column_1: "Amount", column_2: "Description", ... }
|
79
|
+
def self.find_body_column_names(body)
|
80
|
+
header = REXML::XPath.first(body, "//RowType[text()='Header']")
|
81
|
+
names_map = {}
|
82
|
+
column_count = 0
|
83
|
+
header.parent.elements.each("Cells/Cell") do |header_cell|
|
84
|
+
column_count += 1
|
85
|
+
column_key = "column_#{column_count}".to_sym
|
86
|
+
column_name = nil
|
87
|
+
name_value = header_cell.children.first
|
88
|
+
column_name = name_value.text.strip unless name_value.blank? # finds <Value>...</Value>
|
89
|
+
names_map[column_key] = column_name
|
90
|
+
end
|
91
|
+
names_map
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
end
|
@@ -1,17 +1,20 @@
|
|
1
1
|
module XeroGateway
|
2
2
|
class Response
|
3
3
|
attr_accessor :response_id, :status, :errors, :provider, :date_time, :response_item, :request_params, :request_xml, :response_xml
|
4
|
-
|
4
|
+
|
5
5
|
def array_wrapped_response_item
|
6
6
|
Array(response_item)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
alias_method :invoice, :response_item
|
10
10
|
alias_method :credit_note, :response_item
|
11
11
|
alias_method :bank_transaction, :response_item
|
12
12
|
alias_method :manual_journal, :response_item
|
13
13
|
alias_method :contact, :response_item
|
14
|
+
alias_method :contact_group, :response_item
|
14
15
|
alias_method :organisation, :response_item
|
16
|
+
alias_method :report, :response_item
|
17
|
+
alias_method :contact_groups, :array_wrapped_response_item
|
15
18
|
alias_method :invoices, :array_wrapped_response_item
|
16
19
|
alias_method :credit_notes, :array_wrapped_response_item
|
17
20
|
alias_method :bank_transactions, :array_wrapped_response_item
|
@@ -20,22 +23,24 @@ module XeroGateway
|
|
20
23
|
alias_method :accounts, :array_wrapped_response_item
|
21
24
|
alias_method :tracking_categories, :array_wrapped_response_item
|
22
25
|
alias_method :tax_rates, :array_wrapped_response_item
|
26
|
+
alias_method :items, :array_wrapped_response_item
|
23
27
|
alias_method :currencies, :array_wrapped_response_item
|
24
|
-
|
28
|
+
alias_method :payments, :array_wrapped_response_item
|
29
|
+
|
25
30
|
def initialize(params = {})
|
26
31
|
params.each do |k,v|
|
27
32
|
self.send("#{k}=", v)
|
28
33
|
end
|
29
|
-
|
34
|
+
|
30
35
|
@errors ||= []
|
31
36
|
@response_item ||= []
|
32
37
|
end
|
33
|
-
|
34
|
-
|
38
|
+
|
39
|
+
|
35
40
|
def success?
|
36
41
|
status == "OK"
|
37
42
|
end
|
38
|
-
|
43
|
+
|
39
44
|
def error
|
40
45
|
errors.blank? ? nil : errors[0]
|
41
46
|
end
|