xero_gateway 2.3.0 → 2.4.0
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.
- 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={})
|