xero_gateway 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +87 -82
- data/examples/partner_app.rb +0 -4
- data/examples/private_app.rb +18 -0
- data/lib/xero_gateway/account.rb +29 -12
- data/lib/xero_gateway/bank_transaction.rb +6 -11
- data/lib/xero_gateway/base_record.rb +26 -7
- data/lib/xero_gateway/contact.rb +40 -38
- data/lib/xero_gateway/contact_group.rb +12 -10
- data/lib/xero_gateway/credit_note.rb +42 -50
- data/lib/xero_gateway/gateway.rb +10 -7
- data/lib/xero_gateway/invoice.rb +53 -54
- data/lib/xero_gateway/line_item_calculations.rb +20 -22
- data/lib/xero_gateway/manual_journal.rb +2 -1
- data/lib/xero_gateway/organisation.rb +8 -1
- data/lib/xero_gateway/partner_app.rb +14 -20
- data/lib/xero_gateway/tax_rate.rb +1 -0
- data/lib/xero_gateway/version.rb +1 -1
- data/test/integration/get_invoices_test.rb +31 -22
- data/test/integration/get_organisation_test.rb +8 -7
- data/test/integration/get_tax_rates_test.rb +8 -8
- data/test/test_helper.rb +1 -1
- data/test/unit/account_test.rb +10 -6
- data/test/unit/bank_transaction_test.rb +11 -2
- data/test/unit/contact_test.rb +62 -0
- data/test/unit/credit_note_test.rb +51 -63
- data/test/unit/gateway_test.rb +16 -4
- data/test/unit/invoice_test.rb +91 -55
- data/test/unit/manual_journal_test.rb +7 -7
- data/test/unit/organisation_test.rb +52 -7
- data/test/unit/tax_rate_test.rb +8 -7
- data/xero_gateway.gemspec +7 -2
- metadata +8 -7
data/lib/xero_gateway/invoice.rb
CHANGED
@@ -3,18 +3,18 @@ module XeroGateway
|
|
3
3
|
include Dates
|
4
4
|
include Money
|
5
5
|
include LineItemCalculations
|
6
|
-
|
6
|
+
|
7
7
|
INVOICE_TYPE = {
|
8
8
|
'ACCREC' => 'Accounts Receivable',
|
9
9
|
'ACCPAY' => 'Accounts Payable'
|
10
10
|
} unless defined?(INVOICE_TYPE)
|
11
|
-
|
11
|
+
|
12
12
|
LINE_AMOUNT_TYPES = {
|
13
13
|
"Inclusive" => 'Invoice lines are inclusive tax',
|
14
14
|
"Exclusive" => 'Invoice lines are exclusive of tax (default)',
|
15
15
|
"NoTax" => 'Invoices lines have no tax'
|
16
16
|
} unless defined?(LINE_AMOUNT_TYPES)
|
17
|
-
|
17
|
+
|
18
18
|
INVOICE_STATUS = {
|
19
19
|
'AUTHORISED' => 'Approved invoices awaiting payment',
|
20
20
|
'DELETED' => 'Draft invoices that are deleted',
|
@@ -23,49 +23,52 @@ module XeroGateway
|
|
23
23
|
'SUBMITTED' => 'Invoices entered by an employee awaiting approval',
|
24
24
|
'VOID' => 'Approved invoices that are voided'
|
25
25
|
} unless defined?(INVOICE_STATUS)
|
26
|
-
|
26
|
+
|
27
27
|
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)
|
28
|
-
|
28
|
+
|
29
29
|
# Xero::Gateway associated with this invoice.
|
30
30
|
attr_accessor :gateway
|
31
|
-
|
31
|
+
|
32
32
|
# Any errors that occurred when the #valid? method called.
|
33
33
|
# Or errors that were within the XML payload from Xero
|
34
34
|
attr_accessor :errors
|
35
35
|
|
36
36
|
# Represents whether the line_items have been downloaded when getting from GET /API.XRO/2.0/INVOICES
|
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,
|
40
|
+
attr_accessor :invoice_id, :invoice_number, :invoice_type, :invoice_status, :date, :due_date, :reference, :branding_theme_id,
|
41
|
+
:line_amount_types, :currency_code, :currency_rate, :payments, :fully_paid_on, :amount_due, :amount_paid, :amount_credited,
|
42
|
+
:sent_to_contact, :url, :updated_date_utc
|
43
|
+
attr_writer :contact, :line_items
|
41
44
|
|
42
45
|
def initialize(params = {})
|
43
46
|
@errors ||= []
|
44
47
|
@payments ||= []
|
45
|
-
|
48
|
+
|
46
49
|
# Check if the line items have been downloaded.
|
47
50
|
@line_items_downloaded = (params.delete(:line_items_downloaded) == true)
|
48
|
-
|
51
|
+
|
49
52
|
params = {
|
50
53
|
:line_amount_types => "Exclusive"
|
51
54
|
}.merge(params)
|
52
|
-
|
55
|
+
|
53
56
|
params.each do |k,v|
|
54
57
|
self.send("#{k}=", v)
|
55
58
|
end
|
56
|
-
|
59
|
+
|
57
60
|
@line_items ||= []
|
58
61
|
end
|
59
|
-
|
62
|
+
|
60
63
|
# Validate the Address record according to what will be valid by the gateway.
|
61
64
|
#
|
62
|
-
# Usage:
|
65
|
+
# Usage:
|
63
66
|
# address.valid? # Returns true/false
|
64
|
-
#
|
67
|
+
#
|
65
68
|
# Additionally sets address.errors array to an array of field/error.
|
66
69
|
def valid?
|
67
70
|
@errors = []
|
68
|
-
|
71
|
+
|
69
72
|
if !INVOICE_TYPE[invoice_type]
|
70
73
|
@errors << ['invoice_type', "must be one of #{INVOICE_TYPE.keys.join('/')}"]
|
71
74
|
end
|
@@ -73,7 +76,7 @@ module XeroGateway
|
|
73
76
|
if !invoice_id.nil? && invoice_id !~ GUID_REGEX
|
74
77
|
@errors << ['invoice_id', 'must be blank or a valid Xero GUID']
|
75
78
|
end
|
76
|
-
|
79
|
+
|
77
80
|
if invoice_status && !INVOICE_STATUS[invoice_status]
|
78
81
|
@errors << ['invoice_status', "must be one of #{INVOICE_STATUS.keys.join('/')}"]
|
79
82
|
end
|
@@ -81,87 +84,73 @@ module XeroGateway
|
|
81
84
|
if line_amount_types && !LINE_AMOUNT_TYPES[line_amount_types]
|
82
85
|
@errors << ['line_amount_types', "must be one of #{LINE_AMOUNT_TYPES.keys.join('/')}"]
|
83
86
|
end
|
84
|
-
|
87
|
+
|
85
88
|
unless date
|
86
89
|
@errors << ['invoice_date', "can't be blank"]
|
87
90
|
end
|
88
|
-
|
91
|
+
|
89
92
|
# Make sure contact is valid.
|
90
93
|
unless @contact && @contact.valid?
|
91
94
|
@errors << ['contact', 'is invalid']
|
92
95
|
end
|
93
|
-
|
96
|
+
|
94
97
|
# Make sure all line_items are valid.
|
95
98
|
unless line_items.all? { | line_item | line_item.valid? }
|
96
99
|
@errors << ['line_items', "at least one line item invalid"]
|
97
100
|
end
|
98
|
-
|
101
|
+
|
99
102
|
@errors.size == 0
|
100
103
|
end
|
101
|
-
|
104
|
+
|
102
105
|
# Helper method to create the associated contact object.
|
103
106
|
def build_contact(params = {})
|
104
107
|
self.contact = gateway ? gateway.build_contact(params) : Contact.new(params)
|
105
108
|
end
|
106
|
-
|
109
|
+
|
107
110
|
def contact
|
108
111
|
@contact ||= build_contact
|
109
112
|
end
|
110
|
-
|
113
|
+
|
111
114
|
# Helper method to check if the invoice is accounts payable.
|
112
115
|
def accounts_payable?
|
113
116
|
invoice_type == 'ACCPAY'
|
114
117
|
end
|
115
|
-
|
118
|
+
|
116
119
|
# Helper method to check if the invoice is accounts receivable.
|
117
120
|
def accounts_receivable?
|
118
121
|
invoice_type == 'ACCREC'
|
119
122
|
end
|
120
|
-
|
123
|
+
|
121
124
|
# Whether or not the line_items have been downloaded (GET/invoices does not download line items).
|
122
125
|
def line_items_downloaded?
|
123
126
|
@line_items_downloaded
|
124
127
|
end
|
125
128
|
|
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
|
-
|
132
129
|
# If line items are not downloaded, then attempt a download now (if this record was found to begin with).
|
133
130
|
def line_items
|
134
131
|
if line_items_downloaded?
|
135
132
|
@line_items
|
136
|
-
|
137
133
|
elsif invoice_id =~ GUID_REGEX && @gateway
|
138
134
|
# There is an invoice_id so we can assume this record was loaded from Xero.
|
139
135
|
# Let's attempt to download the line_item records (if there is a gateway)
|
140
|
-
|
141
|
-
raise InvoiceNotFoundError, "Invoice with ID #{invoice_id} not found in Xero." unless response.success? && response.invoice.is_a?(XeroGateway::Invoice)
|
142
|
-
|
143
|
-
@line_items = response.invoice.line_items
|
144
|
-
@line_items_downloaded = true
|
145
|
-
|
146
|
-
@line_items
|
147
|
-
|
148
|
-
# Otherwise, this is a new invoice, so return the line_items reference.
|
136
|
+
@line_items = download_line_items
|
149
137
|
else
|
138
|
+
# Otherwise, this is a new invoice, so return the line_items reference.
|
150
139
|
@line_items
|
151
140
|
end
|
152
141
|
end
|
153
|
-
|
142
|
+
|
154
143
|
def ==(other)
|
155
|
-
["invoice_number", "invoice_type", "invoice_status", "reference", "currency_code", "line_amount_types", "contact", "line_items"].each do |field|
|
144
|
+
["invoice_number", "invoice_type", "invoice_status", "reference", "currency_code", "currency_rate", "line_amount_types", "contact", "line_items"].each do |field|
|
156
145
|
return false if send(field) != other.send(field)
|
157
146
|
end
|
158
|
-
|
147
|
+
|
159
148
|
["date", "due_date"].each do |field|
|
160
149
|
return false if send(field).to_s != other.send(field).to_s
|
161
150
|
end
|
162
151
|
return true
|
163
152
|
end
|
164
|
-
|
153
|
+
|
165
154
|
# General purpose create/save method.
|
166
155
|
# If invoice_id is nil then create, otherwise, attempt to save.
|
167
156
|
def save
|
@@ -171,27 +160,28 @@ module XeroGateway
|
|
171
160
|
update
|
172
161
|
end
|
173
162
|
end
|
174
|
-
|
163
|
+
|
175
164
|
# Creates this invoice record (using gateway.create_invoice) with the associated gateway.
|
176
165
|
# If no gateway set, raise a NoGatewayError exception.
|
177
166
|
def create
|
178
167
|
raise NoGatewayError unless gateway
|
179
168
|
gateway.create_invoice(self)
|
180
169
|
end
|
181
|
-
|
170
|
+
|
182
171
|
# Updates this invoice record (using gateway.update_invoice) with the associated gateway.
|
183
172
|
# If no gateway set, raise a NoGatewayError exception.
|
184
173
|
def update
|
185
174
|
raise NoGatewayError unless gateway
|
186
175
|
gateway.update_invoice(self)
|
187
176
|
end
|
188
|
-
|
177
|
+
|
189
178
|
def to_xml(b = Builder::XmlMarkup.new)
|
190
179
|
b.Invoice {
|
191
180
|
b.InvoiceID self.invoice_id if self.invoice_id
|
192
181
|
b.InvoiceNumber self.invoice_number if invoice_number
|
193
182
|
b.Type self.invoice_type
|
194
|
-
b.CurrencyCode
|
183
|
+
b.CurrencyCode currency_code if currency_code
|
184
|
+
b.CurrencyRate currency_rate if currency_rate
|
195
185
|
contact.to_xml(b)
|
196
186
|
b.Date Invoice.format_date(self.date || Date.today)
|
197
187
|
b.DueDate Invoice.format_date(self.due_date) if self.due_date
|
@@ -207,16 +197,17 @@ module XeroGateway
|
|
207
197
|
b.Url url if url
|
208
198
|
}
|
209
199
|
end
|
210
|
-
|
200
|
+
|
211
201
|
#TODO UpdatedDateUTC
|
212
202
|
def self.from_xml(invoice_element, gateway = nil, options = {})
|
213
203
|
invoice = Invoice.new(options.merge({:gateway => gateway}))
|
214
204
|
invoice_element.children.each do |element|
|
215
205
|
case(element.name)
|
216
206
|
when "InvoiceID" then invoice.invoice_id = element.text
|
217
|
-
when "InvoiceNumber" then invoice.invoice_number = element.text
|
207
|
+
when "InvoiceNumber" then invoice.invoice_number = element.text
|
218
208
|
when "Type" then invoice.invoice_type = element.text
|
219
209
|
when "CurrencyCode" then invoice.currency_code = element.text
|
210
|
+
when "CurrencyRate" then invoice.currency_rate = BigDecimal.new(element.text)
|
220
211
|
when "Contact" then invoice.contact = Contact.from_xml(element)
|
221
212
|
when "Date" then invoice.date = parse_date(element.text)
|
222
213
|
when "DueDate" then invoice.due_date = parse_date(element.text)
|
@@ -229,8 +220,6 @@ module XeroGateway
|
|
229
220
|
when "SubTotal" then invoice.sub_total = BigDecimal.new(element.text)
|
230
221
|
when "TotalTax" then invoice.total_tax = BigDecimal.new(element.text)
|
231
222
|
when "Total" then invoice.total = BigDecimal.new(element.text)
|
232
|
-
when "InvoiceID" then invoice.invoice_id = element.text
|
233
|
-
when "InvoiceNumber" then invoice.invoice_number = element.text
|
234
223
|
when "Payments" then element.children.each { | payment | invoice.payments << Payment.from_xml(payment) }
|
235
224
|
when "AmountDue" then invoice.amount_due = BigDecimal.new(element.text)
|
236
225
|
when "AmountPaid" then invoice.amount_paid = BigDecimal.new(element.text)
|
@@ -242,5 +231,15 @@ module XeroGateway
|
|
242
231
|
end
|
243
232
|
invoice
|
244
233
|
end
|
234
|
+
|
235
|
+
private
|
236
|
+
|
237
|
+
def download_line_items
|
238
|
+
response = @gateway.get_invoice(invoice_id)
|
239
|
+
raise InvoiceNotFoundError, "Invoice with ID #{invoice_id} not found in Xero." unless response.success? && response.invoice.is_a?(XeroGateway::Invoice)
|
240
|
+
|
241
|
+
@line_items_downloaded = true
|
242
|
+
@line_items = response.invoice.line_items
|
243
|
+
end
|
245
244
|
end
|
246
245
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module XeroGateway
|
2
2
|
module LineItemCalculations
|
3
|
+
|
3
4
|
def add_line_item(params = {})
|
4
5
|
line_item = nil
|
5
6
|
case params
|
@@ -11,41 +12,38 @@ module XeroGateway
|
|
11
12
|
line_item
|
12
13
|
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
def sub_total=(value)
|
15
|
+
%w(sub_total total_tax total).each do |line_item_total_type|
|
16
|
+
define_method("#{line_item_total_type}=") do |new_total|
|
17
|
+
instance_variable_set("@#{line_item_total_type}", new_total) unless line_items_downloaded?
|
18
|
+
end
|
19
19
|
end
|
20
20
|
|
21
21
|
# Calculate the sub_total as the SUM(line_item.line_amount).
|
22
22
|
def sub_total
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
# Deprecated (but API for setter remains).
|
27
|
-
#
|
28
|
-
# As total_tax must equal SUM(line_item.tax_amount) for the API call to pass, this is now
|
29
|
-
# automatically calculated in the total_tax method.
|
30
|
-
def total_tax=(value)
|
23
|
+
total_cache(:sub_total) || sum_line_items(line_items, :line_amount)
|
31
24
|
end
|
32
25
|
|
33
26
|
# Calculate the total_tax as the SUM(line_item.tax_amount).
|
34
27
|
def total_tax
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
# Deprecated (but API for setter remains).
|
39
|
-
#
|
40
|
-
# As total must equal sub_total + total_tax for the API call to pass, this is now
|
41
|
-
# automatically calculated in the total method.
|
42
|
-
def total=(value)
|
28
|
+
total_cache(:total_tax) || sum_line_items(line_items, :tax_amount)
|
43
29
|
end
|
44
30
|
|
45
31
|
# Calculate the toal as sub_total + total_tax.
|
46
32
|
def total
|
47
|
-
|
33
|
+
total_cache(:total) || (sub_total + total_tax)
|
48
34
|
end
|
49
35
|
|
36
|
+
private
|
37
|
+
|
38
|
+
def total_cache(name)
|
39
|
+
instance_variable_defined?("@#{name}") && instance_variable_get("@#{name}")
|
40
|
+
end
|
41
|
+
|
42
|
+
def sum_line_items(lines, sum_type = :line_amount)
|
43
|
+
lines.inject(BigDecimal.new('0')) do |sum, line|
|
44
|
+
sum + BigDecimal.new(line.send(sum_type).to_s)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
50
48
|
end
|
51
49
|
end
|
@@ -24,7 +24,8 @@ module XeroGateway
|
|
24
24
|
attr_accessor :journal_lines_downloaded
|
25
25
|
|
26
26
|
# accessible fields
|
27
|
-
attr_accessor :manual_journal_id, :narration, :date, :status, :
|
27
|
+
attr_accessor :manual_journal_id, :narration, :date, :status, :url, :show_on_cash_basis_reports
|
28
|
+
attr_writer :journal_lines
|
28
29
|
|
29
30
|
def initialize(params = {})
|
30
31
|
@errors ||= []
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module XeroGateway
|
2
2
|
class Organisation < BaseRecord
|
3
3
|
attributes({
|
4
|
+
"OrganisationID" => :string,
|
4
5
|
"Name" => :string, # Display name of organisation shown in Xero
|
5
6
|
"LegalName" => :string, # Organisation name shown on Reports
|
6
7
|
"PaysTax" => :boolean, # Boolean to describe if organisation is registered with a local tax authority i.e. true, false
|
@@ -18,7 +19,13 @@ module XeroGateway
|
|
18
19
|
"CreatedDateUTC" => :string,
|
19
20
|
"ShortCode" => :string,
|
20
21
|
"Timezone" => :string,
|
21
|
-
"LineOfBusiness" => :string
|
22
|
+
"LineOfBusiness" => :string,
|
23
|
+
"Addresses" => [Address]
|
22
24
|
})
|
25
|
+
|
26
|
+
def add_address(address_params)
|
27
|
+
self.addresses ||= []
|
28
|
+
self.addresses << Address.new(address_params)
|
29
|
+
end
|
23
30
|
end
|
24
31
|
end
|
@@ -1,35 +1,29 @@
|
|
1
1
|
module XeroGateway
|
2
2
|
class PartnerApp < Gateway
|
3
|
-
|
3
|
+
|
4
4
|
class CertificateRequired < StandardError; end
|
5
|
-
|
6
|
-
NO_SSL_CLIENT_CERT_MESSAGE = "You need to provide a client ssl certificate and key pair (these are the ones you got from Entrust and should not be password protected) as :ssl_client_cert and :ssl_client_key (should be .crt or .pem files)"
|
5
|
+
|
7
6
|
NO_PRIVATE_KEY_ERROR_MESSAGE = "You need to provide your private key (corresponds to the public key you uploaded at api.xero.com) as :private_key_file (should be .crt or .pem files)"
|
8
|
-
|
7
|
+
|
9
8
|
def_delegators :client, :session_handle, :renew_access_token, :authorization_expires_at
|
10
|
-
|
9
|
+
|
11
10
|
def initialize(consumer_key, consumer_secret, options = {})
|
12
|
-
|
13
|
-
raise CertificateRequired.new(NO_SSL_CLIENT_CERT_MESSAGE) unless options[:ssl_client_cert]
|
14
|
-
raise CertificateRequired.new(NO_SSL_CLIENT_CERT_MESSAGE) unless options[:ssl_client_key]
|
15
11
|
raise CertificateRequired.new(NO_PRIVATE_KEY_ERROR_MESSAGE) unless options[:private_key_file]
|
16
|
-
|
17
|
-
|
18
|
-
:site => "https://api
|
19
|
-
:authorize_url => 'https://api.xero.com/oauth/Authorize',
|
12
|
+
|
13
|
+
defaults = {
|
14
|
+
:site => "https://api.xero.com",
|
15
|
+
:authorize_url => 'https://api.xero.com/oauth/Authorize',
|
20
16
|
:signature_method => 'RSA-SHA1',
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
@xero_url = options[:xero_url] || "https://api-partner.xero.com/api.xro/2.0"
|
27
|
-
@client = OAuth.new(consumer_key, consumer_secret, options)
|
17
|
+
}
|
18
|
+
|
19
|
+
options = defaults.merge(options)
|
20
|
+
|
21
|
+
super(consumer_key, consumer_secret, defaults.merge(options))
|
28
22
|
end
|
29
23
|
|
30
24
|
def set_session_handle(handle)
|
31
25
|
client.session_handle = handle
|
32
26
|
end
|
33
|
-
|
27
|
+
|
34
28
|
end
|
35
29
|
end
|
data/lib/xero_gateway/version.rb
CHANGED
@@ -2,91 +2,100 @@ require File.dirname(__FILE__) + '/../test_helper'
|
|
2
2
|
|
3
3
|
class GetInvoicesTest < Test::Unit::TestCase
|
4
4
|
include TestHelper
|
5
|
-
|
5
|
+
|
6
6
|
INVALID_INVOICE_ID = "99999999-9999-9999-9999-999999999999" unless defined?(INVALID_INVOICE_ID)
|
7
|
-
|
7
|
+
INVOICE_GET_URL = /\/Invoices\/a99a9aaa-9999-99a9-9aa9-aaaaaa9a9999/
|
8
|
+
|
8
9
|
def setup
|
9
10
|
@gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
|
10
|
-
|
11
|
+
|
11
12
|
if STUB_XERO_CALLS
|
12
13
|
@gateway.xero_url = "DUMMY_URL"
|
13
|
-
|
14
|
+
|
14
15
|
@gateway.stubs(:http_get).with {|client, url, params| url =~ /Invoices/ }.returns(get_file_as_string("invoices.xml"))
|
15
16
|
@gateway.stubs(:http_put).with {|client, url, body, params| url =~ /Invoices$/ }.returns(get_file_as_string("create_invoice.xml"))
|
16
17
|
|
17
18
|
# Get an invoice with an invalid ID number.
|
18
19
|
@gateway.stubs(:http_get).with {|client, url, params| url =~ Regexp.new("Invoices/#{INVALID_INVOICE_ID}") }.returns(get_file_as_string("invoice_not_found_error.xml"))
|
20
|
+
|
21
|
+
# Get referenced invoice with line items
|
22
|
+
@gateway.stubs(:http_get).with {|client, url, params, headers| url =~ INVOICE_GET_URL && headers["Accept"].blank? }.returns(get_file_as_string("invoice.xml"))
|
19
23
|
end
|
20
24
|
end
|
21
|
-
|
25
|
+
|
22
26
|
def test_get_invoices
|
23
27
|
# Make sure there is an invoice in Xero to retrieve
|
24
28
|
invoice = @gateway.create_invoice(dummy_invoice).invoice
|
25
|
-
|
29
|
+
|
26
30
|
result = @gateway.get_invoices
|
27
31
|
assert result.success?
|
28
32
|
assert !result.request_params.nil?
|
29
|
-
assert !result.response_xml.nil?
|
33
|
+
assert !result.response_xml.nil?
|
30
34
|
assert result.invoices.collect {|i| i.invoice_number}.include?(invoice.invoice_number)
|
31
35
|
assert result.invoices[0].sent_to_contact == true
|
32
36
|
assert result.invoices[1].sent_to_contact == false
|
33
37
|
end
|
34
|
-
|
38
|
+
|
35
39
|
def test_get_invoices_with_modified_since_date
|
36
40
|
# Create a test invoice
|
37
41
|
invoice = dummy_invoice
|
38
42
|
@gateway.create_invoice(invoice)
|
39
|
-
|
43
|
+
|
40
44
|
# Check that it is returned
|
41
45
|
result = @gateway.get_invoices(:modified_since => Date.today - 1)
|
42
46
|
assert result.success?
|
43
47
|
assert !result.request_params.nil?
|
44
|
-
assert !result.response_xml.nil?
|
48
|
+
assert !result.response_xml.nil?
|
45
49
|
assert result.request_params.keys.include?(:ModifiedAfter) # make sure the flag was sent
|
46
50
|
assert result.invoices.collect {|response_invoice| response_invoice.invoice_number}.include?(invoice.invoice_number)
|
47
51
|
end
|
48
|
-
|
52
|
+
|
49
53
|
def test_line_items_downloaded_set_correctly
|
50
54
|
# No line items.
|
51
55
|
response = @gateway.get_invoices
|
52
56
|
assert_equal(true, response.success?)
|
53
|
-
|
57
|
+
|
54
58
|
invoice = response.invoices.first
|
55
59
|
assert_kind_of(XeroGateway::Invoice, invoice)
|
56
60
|
assert_equal(false, invoice.line_items_downloaded?)
|
61
|
+
assert_equal 1, invoice.line_items.size
|
62
|
+
line_item = invoice.line_items.first
|
63
|
+
assert_kind_of(XeroGateway::LineItem, line_item)
|
64
|
+
assert_equal 'A LINE ITEM', line_item.description
|
65
|
+
assert_equal 12.34, line_item.unit_amount
|
57
66
|
end
|
58
|
-
|
67
|
+
|
59
68
|
# Make sure that a reference to gateway is passed when the get_invoices response is parsed.
|
60
69
|
def test_get_contacts_gateway_reference
|
61
70
|
result = @gateway.get_invoices
|
62
71
|
assert(result.success?)
|
63
72
|
assert_not_equal(0, result.invoices.size)
|
64
|
-
|
73
|
+
|
65
74
|
result.invoices.each do | invoice |
|
66
75
|
assert(invoice.gateway === @gateway)
|
67
76
|
end
|
68
77
|
end
|
69
|
-
|
78
|
+
|
70
79
|
# Test to make sure that we correctly error when an invoice doesn't have an ID.
|
71
80
|
# This should usually never be ecountered, but might if a draft invoice is deleted from Xero.
|
72
81
|
def test_to_ensure_that_an_invoice_with_invalid_id_errors
|
73
82
|
# Make sure there is an invoice to retrieve, even though we will mangle it later.
|
74
83
|
invoice = @gateway.create_invoice(dummy_invoice).invoice
|
75
|
-
|
84
|
+
|
76
85
|
result = @gateway.get_invoices
|
77
86
|
assert_equal(true, result.success?)
|
78
|
-
|
87
|
+
|
79
88
|
invoice = result.invoices.first
|
80
89
|
assert_equal(false, invoice.line_items_downloaded?)
|
81
|
-
|
90
|
+
|
82
91
|
# Mangle invoice_id to invalid one.
|
83
92
|
invoice.invoice_id = INVALID_INVOICE_ID
|
84
|
-
|
93
|
+
|
85
94
|
# Make sure we fail here.
|
86
95
|
line_items = nil
|
87
96
|
assert_raise(XeroGateway::InvoiceNotFoundError) { line_items = invoice.line_items }
|
88
97
|
assert_nil(line_items)
|
89
|
-
|
98
|
+
|
90
99
|
end
|
91
|
-
|
92
|
-
end
|
100
|
+
|
101
|
+
end
|
@@ -2,23 +2,24 @@ require File.dirname(__FILE__) + '/../test_helper'
|
|
2
2
|
|
3
3
|
class GetOrganisationTest < Test::Unit::TestCase
|
4
4
|
include TestHelper
|
5
|
-
|
5
|
+
|
6
6
|
def setup
|
7
7
|
@gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
|
8
|
-
|
8
|
+
|
9
9
|
if STUB_XERO_CALLS
|
10
10
|
@gateway.xero_url = "DUMMY_URL"
|
11
|
-
|
12
|
-
@gateway.stubs(:http_get).with {|client, url, params| url =~ /Organisation$/ }.returns(get_file_as_string("organisation.xml"))
|
11
|
+
|
12
|
+
@gateway.stubs(:http_get).with {|client, url, params| url =~ /Organisation$/ }.returns(get_file_as_string("organisation.xml"))
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def test_get_organisation
|
17
17
|
result = @gateway.get_organisation
|
18
18
|
assert result.success?
|
19
19
|
assert !result.response_xml.nil?
|
20
|
-
|
20
|
+
|
21
21
|
assert_equal XeroGateway::Organisation, result.organisation.class
|
22
22
|
assert_equal "Demo Company (NZ)", result.organisation.name
|
23
|
+
assert_equal "c3d5e782-2153-4cda-bdb4-cec791ceb90d", result.organisation.organisation_id
|
23
24
|
end
|
24
|
-
end
|
25
|
+
end
|
@@ -2,24 +2,24 @@ require File.dirname(__FILE__) + '/../test_helper'
|
|
2
2
|
|
3
3
|
class GetTaxRatesTest < Test::Unit::TestCase
|
4
4
|
include TestHelper
|
5
|
-
|
5
|
+
|
6
6
|
def setup
|
7
7
|
@gateway = XeroGateway::Gateway.new(CONSUMER_KEY, CONSUMER_SECRET)
|
8
|
-
|
8
|
+
|
9
9
|
if STUB_XERO_CALLS
|
10
10
|
@gateway.xero_url = "DUMMY_URL"
|
11
|
-
|
12
|
-
@gateway.stubs(:http_get).with {|client, url, params| url =~ /TaxRates$/ }.returns(get_file_as_string("tax_rates.xml"))
|
11
|
+
|
12
|
+
@gateway.stubs(:http_get).with {|client, url, params| url =~ /TaxRates$/ }.returns(get_file_as_string("tax_rates.xml"))
|
13
13
|
end
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def test_get_tax_rates
|
17
17
|
result = @gateway.get_tax_rates
|
18
18
|
assert result.success?
|
19
19
|
assert !result.response_xml.nil?
|
20
|
-
|
20
|
+
|
21
21
|
assert result.tax_rates.size > 0
|
22
22
|
assert_equal XeroGateway::TaxRate, result.tax_rates.first.class
|
23
|
-
assert_equal "GST on Expenses", result.tax_rates.first.name
|
23
|
+
assert_equal "15% GST on Expenses", result.tax_rates.first.name
|
24
24
|
end
|
25
|
-
end
|
25
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -102,7 +102,7 @@ module TestHelper
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def get_file(filename)
|
105
|
-
|
105
|
+
File.read( File.dirname(__FILE__) + "/stub_responses/" + filename)
|
106
106
|
end
|
107
107
|
|
108
108
|
def create_test_bank_transaction(params={}, contact_params={}, line_item_params={})
|