xeroizer 2.18.1 → 2.19.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 +86 -63
- data/lib/xeroizer.rb +1 -0
- data/lib/xeroizer/generic_application.rb +2 -1
- data/lib/xeroizer/http.rb +2 -0
- data/lib/xeroizer/models/bank_account.rb +1 -0
- data/lib/xeroizer/models/branding_theme.rb +49 -9
- data/lib/xeroizer/models/credit_note.rb +3 -2
- data/lib/xeroizer/models/from_bank_account.rb +1 -0
- data/lib/xeroizer/models/invoice.rb +9 -2
- data/lib/xeroizer/models/line_item.rb +9 -2
- data/lib/xeroizer/models/organisation.rb +2 -0
- data/lib/xeroizer/models/payment_service.rb +22 -0
- data/lib/xeroizer/models/prepayment.rb +1 -0
- data/lib/xeroizer/models/purchase_order.rb +6 -6
- data/lib/xeroizer/models/schedule.rb +1 -0
- data/lib/xeroizer/models/to_bank_account.rb +1 -0
- data/lib/xeroizer/record/base.rb +1 -1
- data/lib/xeroizer/record/base_model_http_proxy.rb +3 -0
- data/lib/xeroizer/record/model_definition_helper.rb +1 -1
- data/lib/xeroizer/record/xml_helper.rb +2 -2
- data/lib/xeroizer/report/aged_receivables_by_contact.rb +1 -1
- data/lib/xeroizer/report/cell_xml_helper.rb +1 -1
- data/lib/xeroizer/version.rb +1 -1
- data/test/acceptance/about_fetching_bank_transactions_test.rb +2 -2
- data/test/stub_responses/organisations.xml +10 -0
- data/test/stub_responses/payment_service.xml +15 -0
- data/test/unit/http_test.rb +5 -5
- data/test/unit/models/line_item_test.rb +8 -0
- data/test/unit/models/organisation_test.rb +14 -0
- data/test/unit/models/payment_service_test.rb +29 -0
- data/test/unit/models/repeating_invoice_test.rb +1 -1
- data/test/unit/record/base_test.rb +10 -0
- metadata +8 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1ca2b2dffb8f864a2f4c82295bbfddcdeea61c1b
|
4
|
+
data.tar.gz: 4b9f39d61e7027ba84df0d548826cccbc0695d08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e27f5e7d6b66833b4ef226ce27c9fd67b26ba434eaa35b2ea750106db4ad6c334e566132d4779192b3ccfa964811657b9ef123b552d8a4a185be0d9f78c899d
|
7
|
+
data.tar.gz: 6ea509718550d68b1560507fc0204c19406df17924c44ba2ebcc2ac0f27d7652929b7fd9716b9a489e564f274304a3d4cb6e72556031186b7150c304aad5a7cc
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ Xeroizer API Library ![Project status](http://stillmaintained.com/waynerobinson/
|
|
5
5
|
**Git**: [git://github.com/waynerobinson/xeroizer.git](git://github.com/waynerobinson/xeroizer.git)
|
6
6
|
**Github**: [https://github.com/waynerobinson/xeroizer](https://github.com/waynerobinson/xeroizer)
|
7
7
|
**Author**: Wayne Robinson [http://www.wayne-robinson.com](http://www.wayne-robinson.com)
|
8
|
-
**Contributors**: See Contributors section below
|
8
|
+
**Contributors**: See Contributors section below
|
9
9
|
**Copyright**: 2007-2013
|
10
10
|
**License**: MIT License
|
11
11
|
|
@@ -34,7 +34,7 @@ client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CON
|
|
34
34
|
# Retrieve list of contacts (note: all communication must be made through the client).
|
35
35
|
contacts = client.Contact.all(:order => 'Name')
|
36
36
|
```
|
37
|
-
|
37
|
+
|
38
38
|
Authentication
|
39
39
|
--------------
|
40
40
|
|
@@ -44,13 +44,13 @@ There are three methods of authentication detailed below:
|
|
44
44
|
|
45
45
|
### All: Consumer Key/Secret
|
46
46
|
|
47
|
-
All methods of authentication require your OAuth consumer key and secret. This can be found for your application
|
47
|
+
All methods of authentication require your OAuth consumer key and secret. This can be found for your application
|
48
48
|
in the API management console at [http://api.xero.com](http://api.xero.com).
|
49
49
|
|
50
50
|
### Public Applications
|
51
51
|
|
52
|
-
Public applications use a 3-legged authorisation process. A user will need to authorise your
|
53
|
-
application against each organisation that you want access to. Your application can have access
|
52
|
+
Public applications use a 3-legged authorisation process. A user will need to authorise your
|
53
|
+
application against each organisation that you want access to. Your application can have access
|
54
54
|
to many organisations at once by going through the authorisation process for each organisation.
|
55
55
|
|
56
56
|
The access token received will expire after 30 minutes. If you want access for longer you will need
|
@@ -75,69 +75,69 @@ redirect_to request_token.authorize_url
|
|
75
75
|
|
76
76
|
# 3. Exchange RequestToken for AccessToken.
|
77
77
|
# This access token will be used for all subsequent requests but it is stored within the client
|
78
|
-
# application so you don't have to record it.
|
78
|
+
# application so you don't have to record it.
|
79
79
|
#
|
80
80
|
# Note: This example assumes the callback URL is a Rails action.
|
81
81
|
client.authorize_from_request(request_token.token, request_token.secret, :oauth_verifier => params[:oauth_verifier])
|
82
82
|
```
|
83
|
-
|
83
|
+
|
84
84
|
You can now use the client to access the Xero API methods, e.g.
|
85
85
|
|
86
86
|
```ruby
|
87
87
|
contacts = client.Contact.all
|
88
88
|
```
|
89
|
-
|
89
|
+
|
90
90
|
#### Example Rails Controller
|
91
91
|
|
92
92
|
```ruby
|
93
93
|
class XeroSessionController < ApplicationController
|
94
94
|
|
95
95
|
before_filter :get_xero_client
|
96
|
-
|
96
|
+
|
97
97
|
public
|
98
|
-
|
98
|
+
|
99
99
|
def new
|
100
100
|
request_token = @xero_client.request_token(:oauth_callback => 'http://yourapp.com/xero_session/create')
|
101
101
|
session[:request_token] = request_token.token
|
102
102
|
session[:request_secret] = request_token.secret
|
103
|
-
|
103
|
+
|
104
104
|
redirect_to request_token.authorize_url
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
def create
|
108
108
|
@xero_client.authorize_from_request(
|
109
|
-
session[:request_token],
|
110
|
-
session[:request_secret],
|
109
|
+
session[:request_token],
|
110
|
+
session[:request_secret],
|
111
111
|
:oauth_verifier => params[:oauth_verifier] )
|
112
|
-
|
112
|
+
|
113
113
|
session[:xero_auth] = {
|
114
114
|
:access_token => @xero_client.access_token.token,
|
115
115
|
:access_key => @xero_client.access_token.secret }
|
116
|
-
|
116
|
+
|
117
117
|
session.data.delete(:request_token)
|
118
118
|
session.data.delete(:request_secret)
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
def destroy
|
122
122
|
session.data.delete(:xero_auth)
|
123
123
|
end
|
124
|
-
|
124
|
+
|
125
125
|
private
|
126
|
-
|
126
|
+
|
127
127
|
def get_xero_client
|
128
128
|
@xero_client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
|
129
|
-
|
129
|
+
|
130
130
|
# Add AccessToken if authorised previously.
|
131
131
|
if session[:xero_auth]
|
132
132
|
@xero_client.authorize_from_access(
|
133
|
-
session[:xero_auth][:access_token],
|
133
|
+
session[:xero_auth][:access_token],
|
134
134
|
session[:xero_auth][:access_key] )
|
135
135
|
end
|
136
136
|
end
|
137
137
|
end
|
138
138
|
```
|
139
|
-
|
140
|
-
#### Storing AccessToken
|
139
|
+
|
140
|
+
#### Storing AccessToken
|
141
141
|
|
142
142
|
You can store the access token/secret pair so you can access the API again without user intervention. Currently these
|
143
143
|
tokens are only valid for 30 minutes and will raise a `Xeroizer::OAuth::TokenExpired` exception if you try to access
|
@@ -152,9 +152,9 @@ access_secret = client.access_token.secret
|
|
152
152
|
|
153
153
|
### Private Applications
|
154
154
|
|
155
|
-
Private applications use a 2-legged authorisation process. When you register your application, you will select
|
156
|
-
the organisation that is authorised to your application. This cannot be changed afterwards, although you can
|
157
|
-
register another private application if you have multiple organisations.
|
155
|
+
Private applications use a 2-legged authorisation process. When you register your application, you will select
|
156
|
+
the organisation that is authorised to your application. This cannot be changed afterwards, although you can
|
157
|
+
register another private application if you have multiple organisations.
|
158
158
|
|
159
159
|
Note: You can only register organisations you are authorised to yourself.
|
160
160
|
|
@@ -178,7 +178,7 @@ contacts = client.Contact.all
|
|
178
178
|
|
179
179
|
Partner applications use a combination of 3-legged authorisation and private key message signing.
|
180
180
|
|
181
|
-
|
181
|
+
Visit the [https://developer.xero.com/partner/app-partner](Becoming an app partner) page to get permission to create a partner application.
|
182
182
|
|
183
183
|
After you have followed the instructions provided by Xero for partner applications and uploaded your certificate you can
|
184
184
|
access the partner application in a similar way to public applications.
|
@@ -188,7 +188,7 @@ Authentication occcurs in 3 steps:
|
|
188
188
|
```ruby
|
189
189
|
client = Xeroizer::PartnerApplication.new(
|
190
190
|
YOUR_OAUTH_CONSUMER_KEY,
|
191
|
-
YOUR_OAUTH_CONSUMER_SECRET,
|
191
|
+
YOUR_OAUTH_CONSUMER_SECRET,
|
192
192
|
"/path/to/privatekey.pem"
|
193
193
|
)
|
194
194
|
|
@@ -206,7 +206,7 @@ redirect_to request_token.authorize_url
|
|
206
206
|
|
207
207
|
# 3. Exchange RequestToken for AccessToken.
|
208
208
|
# This access token will be used for all subsequent requests but it is stored within the client
|
209
|
-
# application so you don't have to record it.
|
209
|
+
# application so you don't have to record it.
|
210
210
|
#
|
211
211
|
# Note: This example assumes the callback URL is a Rails action.
|
212
212
|
client.authorize_from_request(request_token.token, request_token.secret, :oauth_verifier => params[:oauth_verifier])
|
@@ -221,7 +221,7 @@ session_handle = client.session_handle
|
|
221
221
|
access_key = client.access_token.token
|
222
222
|
access_secret = client.access_token.secret
|
223
223
|
```
|
224
|
-
|
224
|
+
|
225
225
|
Two other interesting attributes of the PartnerApplication client are:
|
226
226
|
|
227
227
|
> **`#expires_at`**: Time this AccessToken will expire (usually 30 minutes into the future).
|
@@ -245,6 +245,10 @@ session.
|
|
245
245
|
|
246
246
|
If you lose these details at any stage you can always reauthorise by redirecting the user back to the Xero OAuth gateway.
|
247
247
|
|
248
|
+
#### Branding Themes API
|
249
|
+
|
250
|
+
Once you are approved as a Xero Partner you can request unofficial documentation to do with customizing Payment Services and Branding Themes using the API. There is more info on that [here]( https://github.com/waynerobinson/xeroizer/pull/439).
|
251
|
+
|
248
252
|
Retrieving Data
|
249
253
|
---------------
|
250
254
|
|
@@ -264,10 +268,10 @@ saved = new_contact.save
|
|
264
268
|
|
265
269
|
### \#all([options])
|
266
270
|
|
267
|
-
Retrieves list of all records with matching options.
|
271
|
+
Retrieves list of all records with matching options.
|
268
272
|
|
269
273
|
**Note:** Some records (Invoice, CreditNote) only return summary information for the contact and no line items
|
270
|
-
when returning them this list operation. This library takes care of automatically retrieving the
|
274
|
+
when returning them this list operation. This library takes care of automatically retrieving the
|
271
275
|
contact and line items from Xero on first access however, this first access has a large performance penalty
|
272
276
|
and will count as an extra query towards your 5,000/day and 60/minute request per organisation limit.
|
273
277
|
|
@@ -281,6 +285,18 @@ Valid options are:
|
|
281
285
|
|
282
286
|
> Field to order by. Should be formatted as Xero-based field (e.g. 'Name', 'ContactID', etc)
|
283
287
|
|
288
|
+
> **:status**
|
289
|
+
|
290
|
+
> Status field for PurchaseOrder. Should be a valid Xero purchase order status.
|
291
|
+
|
292
|
+
> **:date_from**
|
293
|
+
|
294
|
+
> DateFrom field for PurchaseOrder. Should be in YYYY-MM-DD format.
|
295
|
+
|
296
|
+
> **:date_to**
|
297
|
+
|
298
|
+
> DateTo field for PurchaseOrder. Should be in YYYY-MM-DD format.
|
299
|
+
|
284
300
|
> **:where**
|
285
301
|
|
286
302
|
> __See *Where Filters* section below.__
|
@@ -305,11 +321,11 @@ You can specify find filters by providing the :where option with a hash. For exa
|
|
305
321
|
```ruby
|
306
322
|
invoices = Xero.Invoice.all(:where => {:type => 'ACCREC', :amount_due_is_not => 0})
|
307
323
|
```
|
308
|
-
|
324
|
+
|
309
325
|
will automatically create the Xero string:
|
310
326
|
|
311
327
|
Type=="ACCREC"&&AmountDue<>0
|
312
|
-
|
328
|
+
|
313
329
|
The default method for filtering is the equality '==' operator however, these can be overridden
|
314
330
|
by modifying the postfix of the attribute name (as you can see for the :amount\_due field above).
|
315
331
|
|
@@ -318,9 +334,9 @@ by modifying the postfix of the attribute name (as you can see for the :amount\_
|
|
318
334
|
\{attribute_name}_is_greater_than_or_equal_to will use '>='
|
319
335
|
\{attribute_name}_is_less_than will use '<'
|
320
336
|
\{attribute_name}_is_less_than_or_equal_to will use '<='
|
321
|
-
|
337
|
+
|
322
338
|
The default is '=='
|
323
|
-
|
339
|
+
|
324
340
|
**Note:** Currently, the hash-conversion library only allows for AND-based criteria and doesn't
|
325
341
|
take into account associations. For these, please use the custom filter method below.
|
326
342
|
|
@@ -332,15 +348,15 @@ in the resulting response, including all nested XML elements.
|
|
332
348
|
**Example 1: Retrieve all invoices for a specific contact ID:**
|
333
349
|
|
334
350
|
invoices = xero.Invoice.all(:where => 'Contact.ContactID.ToString()=="cd09aa49-134d-40fb-a52b-b63c6a91d712"')
|
335
|
-
|
351
|
+
|
336
352
|
**Example 2: Retrieve all unpaid ACCREC Invoices against a particular Contact Name:**
|
337
|
-
|
353
|
+
|
338
354
|
invoices = xero.Invoice.all(:where => 'Contact.Name=="Basket Case" && Type=="ACCREC" && AmountDue<>0')
|
339
|
-
|
355
|
+
|
340
356
|
**Example 3: Retrieve all Invoices PAID between certain dates**
|
341
|
-
|
357
|
+
|
342
358
|
invoices = xero.Invoice.all(:where => 'FullyPaidOnDate>=DateTime.Parse("2010-01-01T00:00:00")&&FullyPaidOnDate<=DateTime.Parse("2010-01-08T00:00:00")')
|
343
|
-
|
359
|
+
|
344
360
|
**Example 4: Retrieve all Invoices using Paging (batches of 100)**
|
345
361
|
|
346
362
|
invoices = xero.Invoice.find_in_batches({page_number: 1}) do |invoice_batch|
|
@@ -348,15 +364,15 @@ in the resulting response, including all nested XML elements.
|
|
348
364
|
...
|
349
365
|
end
|
350
366
|
end
|
351
|
-
|
367
|
+
|
352
368
|
**Example 5: Retrieve all Bank Accounts:**
|
353
|
-
|
369
|
+
|
354
370
|
accounts = xero.Account.all(:where => 'Type=="BANK"')
|
355
|
-
|
371
|
+
|
356
372
|
**Example 6: Retrieve all DELETED or VOIDED Invoices:**
|
357
|
-
|
373
|
+
|
358
374
|
invoices = xero.Invoice.all(:where => 'Status=="VOIDED" OR Status=="DELETED"')
|
359
|
-
|
375
|
+
|
360
376
|
**Example 7: Retrieve all contacts with specific text in the contact name:**
|
361
377
|
|
362
378
|
contacts = xero.Contact.all(:where => 'Name.Contains("Peter")')
|
@@ -376,7 +392,7 @@ invoice.line_items.each do | line_item |
|
|
376
392
|
puts "Line Description: #{line_item.description}"
|
377
393
|
end
|
378
394
|
```
|
379
|
-
|
395
|
+
|
380
396
|
**belongs\_to example:**
|
381
397
|
|
382
398
|
```ruby
|
@@ -430,21 +446,21 @@ contact.add_phone(:type => 'DEFAULT', :area_code => '07', :number => '3033 1234'
|
|
430
446
|
contact.add_phone(:type => 'MOBILE', :number => '0412 123 456')
|
431
447
|
contact.save
|
432
448
|
```
|
433
|
-
|
449
|
+
|
434
450
|
To add to a `has_many` association use the `add_{association}` method. For example:
|
435
451
|
|
436
452
|
```ruby
|
437
453
|
contact.add_address(:type => 'STREET', :line1 => '12 Testing Lane', :city => 'Brisbane')
|
438
454
|
```
|
439
|
-
|
455
|
+
|
440
456
|
To add to a `belongs_to` association use the `build_{association}` method. For example:
|
441
|
-
|
457
|
+
|
442
458
|
```ruby
|
443
459
|
invoice.build_contact(:name => 'ABC Company')
|
444
460
|
```
|
445
461
|
|
446
462
|
### Updating
|
447
|
-
|
463
|
+
|
448
464
|
If the primary GUID for the record is present, the library will attempt to update the record instead of
|
449
465
|
creating it. It is important that this record is downloaded from the Xero API first before attempting
|
450
466
|
an update. For example:
|
@@ -454,10 +470,17 @@ contact = xero.Contact.find("cd09aa49-134d-40fb-a52b-b63c6a91d712")
|
|
454
470
|
contact.name = "Another Name Change"
|
455
471
|
contact.save
|
456
472
|
```
|
457
|
-
|
458
|
-
Have a look at the models in `lib/xeroizer/models/` to see the valid attributes, associations and
|
473
|
+
|
474
|
+
Have a look at the models in `lib/xeroizer/models/` to see the valid attributes, associations and
|
459
475
|
minimum validation requirements for each of the record types.
|
460
476
|
|
477
|
+
Some Xero endpoints, such as Payment, will only accept specific attributes for updates. Because the library does not have this knowledge encoded (and doesn't do dirty tracking of attributes), it's necessary to construct new objects instead of using the ones retrieved from Xero:
|
478
|
+
|
479
|
+
```ruby
|
480
|
+
delete_payment = gateway.Payment.build(id: payment.id, status: 'DELETED')
|
481
|
+
delete_payment.save
|
482
|
+
```
|
483
|
+
|
461
484
|
### Bulk Creates & Updates
|
462
485
|
|
463
486
|
Xero has a hard daily limit on the number of API requests you can make (currently 5,000 requests
|
@@ -501,7 +524,7 @@ saved = contact.save
|
|
501
524
|
|
502
525
|
# contact.errors will contain [[:name, "can't be blank"]]
|
503
526
|
```
|
504
|
-
|
527
|
+
|
505
528
|
\#errors\_for(:attribute\_name) is a helper method to return just the errors associated with
|
506
529
|
that attribute. For example:
|
507
530
|
|
@@ -530,7 +553,7 @@ invoice.save
|
|
530
553
|
# An invoice created without a status will default to 'DRAFT'
|
531
554
|
invoice.approved?
|
532
555
|
|
533
|
-
# Payments can only be created against '
|
556
|
+
# Payments can only be created against 'AUTHORISED' invoices
|
534
557
|
invoice.approve!
|
535
558
|
|
536
559
|
# Find the first bank account
|
@@ -582,16 +605,16 @@ trial_balance.rows.each do | row |
|
|
582
605
|
case row
|
583
606
|
when Xeroizer::Report::HeaderRow
|
584
607
|
# do something with header
|
585
|
-
|
608
|
+
|
586
609
|
when Xeroizer::Report::SectionRow
|
587
610
|
# do something with section, will need to step into the rows for this section
|
588
|
-
|
611
|
+
|
589
612
|
when Xeroizer::Report::Row
|
590
613
|
# do something for standard report rows
|
591
|
-
|
614
|
+
|
592
615
|
when Xeroizer::Report::SummaryRow
|
593
616
|
# do something for summary rows
|
594
|
-
|
617
|
+
|
595
618
|
end
|
596
619
|
end
|
597
620
|
```
|
@@ -660,7 +683,7 @@ throttling and logging:
|
|
660
683
|
Xeroizer::PublicApplication.new(
|
661
684
|
credentials[:key], credentials[:secret],
|
662
685
|
before_request: ->(request) { puts "Hitting this URL: #{request.url}" },
|
663
|
-
after_request: ->(request, response) { puts "Got this response: #{response.code}" }
|
686
|
+
after_request: ->(request, response) { puts "Got this response: #{response.code}" },
|
664
687
|
around_request: -> (request, &block) { puts "About to send request"; block.call; puts "After request"}
|
665
688
|
)
|
666
689
|
```
|
@@ -686,7 +709,7 @@ This option adds the unitdp=4 query string parameter to all requests for models
|
|
686
709
|
Tests
|
687
710
|
-----
|
688
711
|
|
689
|
-
The tests within the repository can be run by setting up a [Private App](https://developer.xero.com/documentation/auth-and-limits/private-applications). You can create a Private App in the [developer portal](https://developer.xero.com/myapps/), it's suggested that you create it against the [Demo Company](https://developer.xero.com/documentation/getting-started/development-accounts)
|
712
|
+
The tests within the repository can be run by setting up a [Private App](https://developer.xero.com/documentation/auth-and-limits/private-applications). You can create a Private App in the [developer portal](https://developer.xero.com/myapps/), it's suggested that you create it against the [Demo Company (AU)](https://developer.xero.com/documentation/getting-started/development-accounts). Demo Company expires after 28 days, so you will need to reset it and create a new Private App if you Demo Company has expired. Make sure you create the Demo Company in Australia region.
|
690
713
|
|
691
714
|
Once you have created your Private App, set these environment variables:
|
692
715
|
```
|
@@ -704,6 +727,6 @@ rake test
|
|
704
727
|
|
705
728
|
|
706
729
|
### Contributors
|
707
|
-
Xeroizer was inspired by the https://github.com/tlconnor/xero_gateway gem created by Tim Connor
|
708
|
-
and Nik Wakelin and portions of the networking and authentication code are based completely off
|
730
|
+
Xeroizer was inspired by the https://github.com/tlconnor/xero_gateway gem created by Tim Connor
|
731
|
+
and Nik Wakelin and portions of the networking and authentication code are based completely off
|
709
732
|
this project. Copyright for these components remains held in the name of Tim Connor.
|
data/lib/xeroizer.rb
CHANGED
@@ -56,6 +56,7 @@ require 'xeroizer/models/manual_journal_line'
|
|
56
56
|
require 'xeroizer/models/option'
|
57
57
|
require 'xeroizer/models/organisation'
|
58
58
|
require 'xeroizer/models/payment'
|
59
|
+
require 'xeroizer/models/payment_service'
|
59
60
|
require 'xeroizer/models/prepayment'
|
60
61
|
require 'xeroizer/models/overpayment'
|
61
62
|
require 'xeroizer/models/phone'
|
@@ -32,6 +32,7 @@ module Xeroizer
|
|
32
32
|
record :ManualJournal
|
33
33
|
record :Organisation
|
34
34
|
record :Payment
|
35
|
+
record :PaymentService
|
35
36
|
record :Prepayment
|
36
37
|
record :Overpayment
|
37
38
|
record :PurchaseOrder
|
@@ -80,6 +81,6 @@ module Xeroizer
|
|
80
81
|
xero_client.xero_url = options[:xero_url] || "https://api.xero.com/payroll.xro/1.0"
|
81
82
|
@payroll ||= PayrollApplication.new(xero_client)
|
82
83
|
end
|
83
|
-
|
84
|
+
|
84
85
|
end
|
85
86
|
end
|
data/lib/xeroizer/http.rb
CHANGED
@@ -1,22 +1,62 @@
|
|
1
|
+
require "xeroizer/models/payment_service"
|
2
|
+
|
1
3
|
module Xeroizer
|
2
4
|
module Record
|
3
|
-
|
5
|
+
|
4
6
|
class BrandingThemeModel < BaseModel
|
5
|
-
|
6
|
-
set_permissions :read
|
7
|
-
|
7
|
+
|
8
|
+
set_permissions :read, :write
|
9
|
+
|
10
|
+
public
|
11
|
+
|
12
|
+
def payment_services(id)
|
13
|
+
@payment_services ||= @application.http_get(@application.client, payment_services_endpoint(id))
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_payment_service(id:, payment_service_id:)
|
17
|
+
xml = {
|
18
|
+
PaymentService: {
|
19
|
+
PaymentServiceID: payment_service_id
|
20
|
+
}
|
21
|
+
}.to_xml
|
22
|
+
|
23
|
+
@application.http_post(@application.client, payment_services_endpoint(id), xml)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def payment_services_endpoint(id)
|
29
|
+
"#{url}/#{id}/PaymentServices"
|
30
|
+
end
|
31
|
+
|
8
32
|
end
|
9
|
-
|
33
|
+
|
10
34
|
class BrandingTheme < Base
|
11
|
-
|
35
|
+
|
12
36
|
set_primary_key :branding_theme_id
|
13
|
-
|
37
|
+
|
14
38
|
guid :branding_theme_id
|
15
39
|
string :name
|
16
40
|
integer :sort_order
|
17
41
|
datetime_utc :created_date_utc, :api_name => 'CreatedDateUTC'
|
18
42
|
|
43
|
+
# Unfortunately, this part of the API does not work the same as the rest.
|
44
|
+
# You cannot POST child records to Branding Themes.
|
45
|
+
#
|
46
|
+
# The endpoints are:
|
47
|
+
# GET /BrandingThemes/{BrandingThemeID}/PaymentServices
|
48
|
+
# POST /BrandingThemes/{BrandingThemeID}/PaymentServices
|
49
|
+
#
|
50
|
+
# has_one :payment_service, :model_name => 'PaymentService', :list_complete => true
|
51
|
+
|
52
|
+
def payment_services
|
53
|
+
parent.payment_services(id)
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_payment_service(payment_service_id)
|
57
|
+
parent.add_payment_service(id: id, payment_service_id: payment_service_id)
|
58
|
+
end
|
19
59
|
end
|
20
|
-
|
60
|
+
|
21
61
|
end
|
22
|
-
end
|
62
|
+
end
|
@@ -66,6 +66,7 @@ module Xeroizer
|
|
66
66
|
datetime :fully_paid_on_date
|
67
67
|
boolean :sent_to_contact
|
68
68
|
decimal :remaining_credit
|
69
|
+
decimal :applied_amount
|
69
70
|
boolean :has_attachments
|
70
71
|
|
71
72
|
belongs_to :contact
|
@@ -100,7 +101,7 @@ module Xeroizer
|
|
100
101
|
# Calculate sub_total from line_items.
|
101
102
|
def sub_total(always_summary = false)
|
102
103
|
if !always_summary && (new_record? || (!new_record? && line_items && line_items.size > 0))
|
103
|
-
overall_sum = (line_items || []).inject(BigDecimal
|
104
|
+
overall_sum = (line_items || []).inject(BigDecimal('0')) { | sum, line_item | sum + line_item.line_amount }
|
104
105
|
|
105
106
|
# If the default amount types are inclusive of 'tax' then remove the tax amount from this sub-total.
|
106
107
|
overall_sum -= total_tax if line_amount_types == 'Inclusive'
|
@@ -113,7 +114,7 @@ module Xeroizer
|
|
113
114
|
# Calculate total_tax from line_items.
|
114
115
|
def total_tax(always_summary = false)
|
115
116
|
if !always_summary && (new_record? || (!new_record? && line_items && line_items.size > 0))
|
116
|
-
(line_items || []).inject(BigDecimal
|
117
|
+
(line_items || []).inject(BigDecimal('0')) { | sum, line_item | sum + line_item.tax_amount }
|
117
118
|
else
|
118
119
|
attributes[:total_tax]
|
119
120
|
end
|
@@ -89,6 +89,7 @@ module Xeroizer
|
|
89
89
|
has_many :line_items, :complete_on_page => true
|
90
90
|
has_many :payments
|
91
91
|
has_many :credit_notes
|
92
|
+
has_many :prepayments
|
92
93
|
|
93
94
|
validates_presence_of :date, :due_date, :unless => :new_record?
|
94
95
|
validates_inclusion_of :type, :in => INVOICE_TYPES
|
@@ -151,7 +152,7 @@ module Xeroizer
|
|
151
152
|
# Calculate sub_total from line_items.
|
152
153
|
def sub_total(always_summary = false)
|
153
154
|
if !@sub_total_is_set && not_summary_or_loaded_record(always_summary)
|
154
|
-
overall_sum = (line_items || []).inject(BigDecimal
|
155
|
+
overall_sum = (line_items || []).inject(BigDecimal('0')) { | sum, line_item | sum + line_item.line_amount }
|
155
156
|
|
156
157
|
# If the default amount types are inclusive of 'tax' then remove the tax amount from this sub-total.
|
157
158
|
overall_sum -= total_tax if line_amount_types == 'Inclusive'
|
@@ -164,7 +165,7 @@ module Xeroizer
|
|
164
165
|
# Calculate total_tax from line_items.
|
165
166
|
def total_tax(always_summary = false)
|
166
167
|
if !@total_tax_is_set && not_summary_or_loaded_record(always_summary)
|
167
|
-
(line_items || []).inject(BigDecimal
|
168
|
+
(line_items || []).inject(BigDecimal('0')) { | sum, line_item | sum + line_item.tax_amount }
|
168
169
|
else
|
169
170
|
attributes[:total_tax]
|
170
171
|
end
|
@@ -209,6 +210,12 @@ module Xeroizer
|
|
209
210
|
change_status!('AUTHORISED')
|
210
211
|
end
|
211
212
|
|
213
|
+
# Send an email containing the invoice.
|
214
|
+
def email
|
215
|
+
email_url = "#{parent.url}/#{CGI.escape(id)}/Email"
|
216
|
+
parent.application.http_post(parent.application.client, email_url, "")
|
217
|
+
end
|
218
|
+
|
212
219
|
protected
|
213
220
|
|
214
221
|
def change_status!(new_status)
|
@@ -39,7 +39,7 @@ module Xeroizer
|
|
39
39
|
return attributes[:line_amount] if summary_only || @line_amount_set
|
40
40
|
|
41
41
|
if quantity && unit_amount
|
42
|
-
total = quantity * unit_amount
|
42
|
+
total = coerce_numeric(quantity) * coerce_numeric(unit_amount)
|
43
43
|
if discount_rate
|
44
44
|
BigDecimal((total * ((100 - discount_rate) / 100)).to_s).round(2)
|
45
45
|
else
|
@@ -48,7 +48,14 @@ module Xeroizer
|
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
+
private
|
52
|
+
|
53
|
+
def coerce_numeric(number)
|
54
|
+
return number if number.is_a? Numeric
|
55
|
+
BigDecimal(number)
|
56
|
+
end
|
57
|
+
|
51
58
|
end
|
52
|
-
|
59
|
+
|
53
60
|
end
|
54
61
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "xeroizer/models/payment_terms"
|
1
2
|
module Xeroizer
|
2
3
|
module Record
|
3
4
|
|
@@ -62,6 +63,7 @@ module Xeroizer
|
|
62
63
|
has_many :addresses
|
63
64
|
has_many :phones
|
64
65
|
has_many :external_links
|
66
|
+
has_one :payment_terms, :model_name => 'PaymentTerms'
|
65
67
|
|
66
68
|
validates :sales_tax_basis, :message => "is not a valid option" do
|
67
69
|
valid = true
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Xeroizer
|
2
|
+
module Record
|
3
|
+
|
4
|
+
class PaymentServiceModel < BaseModel
|
5
|
+
|
6
|
+
set_permissions :read, :write, :update
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class PaymentService < Base
|
11
|
+
|
12
|
+
set_primary_key :payment_service_id
|
13
|
+
|
14
|
+
guid :payment_service_id
|
15
|
+
string :payment_service_name
|
16
|
+
string :payment_service_url
|
17
|
+
string :payment_service_type
|
18
|
+
string :pay_now_text
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -30,15 +30,15 @@ module Xeroizer
|
|
30
30
|
boolean :is_discounted
|
31
31
|
string :reference
|
32
32
|
string :type
|
33
|
-
|
33
|
+
decimal :currency_rate
|
34
34
|
string :currency_code
|
35
|
-
guid
|
35
|
+
guid :branding_theme_id
|
36
36
|
string :status
|
37
37
|
string :line_amount_types
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
decimal :sub_total
|
39
|
+
decimal :total_tax
|
40
|
+
decimal :total
|
41
|
+
datetime_utc :updated_date_utc, :api_name => 'UpdatedDateUTC'
|
42
42
|
boolean :has_attachments
|
43
43
|
|
44
44
|
has_many :line_items
|
data/lib/xeroizer/record/base.rb
CHANGED
@@ -30,7 +30,7 @@ module Xeroizer
|
|
30
30
|
def build(attributes, parent)
|
31
31
|
record = new(parent)
|
32
32
|
attributes.each do | key, value |
|
33
|
-
attr = record.respond_to?("#{key}=") ? key : record.class.fields[key][:internal_name]
|
33
|
+
attr = record.respond_to?("#{key}=") || record.class.fields[key].nil? ? key : record.class.fields[key][:internal_name]
|
34
34
|
record.send("#{attr}=", value)
|
35
35
|
end
|
36
36
|
record
|
@@ -33,6 +33,9 @@ module Xeroizer
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
params[:offset] = options[:offset] if options[:offset]
|
36
|
+
params[:Status] = options[:status] if options[:status]
|
37
|
+
params[:DateFrom] = options[:date_from] if options[:date_from]
|
38
|
+
params[:DateTo] = options[:date_to] if options[:date_to]
|
36
39
|
params[:page] = options[:page] if options[:page]
|
37
40
|
params
|
38
41
|
end
|
@@ -22,7 +22,7 @@ module Xeroizer
|
|
22
22
|
when :string then element.text
|
23
23
|
when :boolean then (element.text == 'true')
|
24
24
|
when :integer then element.text.to_i
|
25
|
-
when :decimal then BigDecimal
|
25
|
+
when :decimal then BigDecimal(element.text)
|
26
26
|
when :date then Date.parse(element.text)
|
27
27
|
when :datetime then Time.parse(element.text)
|
28
28
|
when :datetime_utc then ActiveSupport::TimeZone['UTC'].parse(element.text).utc
|
@@ -98,7 +98,7 @@ module Xeroizer
|
|
98
98
|
when :decimal
|
99
99
|
real_value = case value
|
100
100
|
when BigDecimal then value.to_s
|
101
|
-
when String then BigDecimal
|
101
|
+
when String then BigDecimal(value).to_s
|
102
102
|
else value
|
103
103
|
end
|
104
104
|
b.tag!(field[:api_name], real_value)
|
@@ -31,7 +31,7 @@ module Xeroizer
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def sum(column_name, &block)
|
34
|
-
sections.first.rows.inject(BigDecimal
|
34
|
+
sections.first.rows.inject(BigDecimal('0')) do | sum, row |
|
35
35
|
sum += row.cell(column_name).value if row.class == Xeroizer::Report::Row && (block.nil? || block.call(row))
|
36
36
|
sum
|
37
37
|
end
|
@@ -47,7 +47,7 @@ module Xeroizer
|
|
47
47
|
|
48
48
|
def parse_value(value)
|
49
49
|
case value
|
50
|
-
when /^[-]?\d+(\.\d+)?$/ then BigDecimal
|
50
|
+
when /^[-]?\d+(\.\d+)?$/ then BigDecimal(value)
|
51
51
|
when /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/ then Time.xmlschema(value)
|
52
52
|
else value
|
53
53
|
end
|
data/lib/xeroizer/version.rb
CHANGED
@@ -18,7 +18,7 @@ class AboutFetchingBankTransactions < Test::Unit::TestCase
|
|
18
18
|
keys = [:line_amount_types, :contact, :date, :status, :line_items,
|
19
19
|
:updated_date_utc, :currency_code, :bank_transaction_id,
|
20
20
|
:bank_account, :type, :reference, :is_reconciled, :currency_rate]
|
21
|
-
assert_equal(@a_new_bank_transaction.attributes.keys
|
21
|
+
assert_equal(keys, @a_new_bank_transaction.attributes.keys)
|
22
22
|
end
|
23
23
|
|
24
24
|
it "returns full line item details" do
|
@@ -38,7 +38,7 @@ class AboutFetchingBankTransactions < Test::Unit::TestCase
|
|
38
38
|
keys = [:line_amount_types, :contact, :date, :status, :updated_date_utc,
|
39
39
|
:currency_code, :bank_transaction_id, :bank_account, :type, :reference,
|
40
40
|
:is_reconciled]
|
41
|
-
assert_equal(@the_first_bank_transaction.attributes.keys
|
41
|
+
assert_equal(keys, @the_first_bank_transaction.attributes.keys)
|
42
42
|
end
|
43
43
|
|
44
44
|
it "returns contact" do
|
@@ -20,6 +20,16 @@
|
|
20
20
|
<FinancialYearEndMonth>6</FinancialYearEndMonth>
|
21
21
|
<PeriodLockDate>2008-06-30T00:00:00</PeriodLockDate>
|
22
22
|
<CreatedDateUTC>2011-05-19T05:26:03.95</CreatedDateUTC>
|
23
|
+
<PaymentTerms>
|
24
|
+
<Bills>
|
25
|
+
<Day>4</Day>
|
26
|
+
<Type>OFFOLLOWINGMONTH</Type>
|
27
|
+
</Bills>
|
28
|
+
<Sales>
|
29
|
+
<Day>2</Day>
|
30
|
+
<Type>OFFOLLOWINGMONTH</Type>
|
31
|
+
</Sales>
|
32
|
+
</PaymentTerms>
|
23
33
|
</Organisation>
|
24
34
|
</Organisations>
|
25
35
|
</Response>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
2
|
+
<Id>42d8b00c-2fdd-4a8a-9b84-82cfe78ff34a</Id>
|
3
|
+
<Status>OK</Status>
|
4
|
+
<ProviderName>Test Provider Name</ProviderName>
|
5
|
+
<DateTimeUTC>2018-06-18T04:13:44.7828584Z</DateTimeUTC>
|
6
|
+
<PaymentServices>
|
7
|
+
<PaymentService>
|
8
|
+
<PaymentServiceID>4d7f4335-6f16-437a-86e3-a856ebc576b8</PaymentServiceID>
|
9
|
+
<PaymentServiceName>Custom Service</PaymentServiceName>
|
10
|
+
<PaymentServiceType>Custom</PaymentServiceType>
|
11
|
+
<PaymentServiceUrl>http://example.com</PaymentServiceUrl>
|
12
|
+
<PayNowText>Pay Me</PayNowText>
|
13
|
+
</PaymentService>
|
14
|
+
</PaymentServices>
|
15
|
+
</Response>
|
data/test/unit/http_test.rb
CHANGED
@@ -3,12 +3,12 @@ require 'test_helper'
|
|
3
3
|
class HttpTest < Test::Unit::TestCase
|
4
4
|
include TestHelper
|
5
5
|
|
6
|
-
def setup
|
7
|
-
@headers = {"User-Agent" => "Xeroizer/2.15.5"}
|
8
|
-
@application = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET, :default_headers => @headers)
|
9
|
-
end
|
10
|
-
|
11
6
|
context "default_headers" do
|
7
|
+
setup do
|
8
|
+
@headers = { "User-Agent" => "Xeroizer/2.15.5" }
|
9
|
+
@application = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET, :default_headers => @headers)
|
10
|
+
end
|
11
|
+
|
12
12
|
should "recognize default_headers" do
|
13
13
|
Xeroizer::OAuth.any_instance.expects(:get).with("/test", has_entry(@headers)).returns(stub(:plain_body => "", :code => "200"))
|
14
14
|
@application.http_get(@application.client, "http://example.com/test")
|
@@ -75,4 +75,12 @@ class LineItemTest < Test::Unit::TestCase
|
|
75
75
|
assert_equal "0.0", line_item.line_amount.to_s,
|
76
76
|
"expected line amount to be zero when unit_amount is zero"
|
77
77
|
end
|
78
|
+
|
79
|
+
it "coerces decimals when calculating line amount" do
|
80
|
+
line_item = LineItem.new(nil)
|
81
|
+
line_item.quantity = "1"
|
82
|
+
line_item.unit_amount = 50
|
83
|
+
assert_equal 50, line_item.line_amount,
|
84
|
+
"expected line amount to be calculated from coerced values"
|
85
|
+
end
|
78
86
|
end
|
@@ -35,4 +35,18 @@ class OrganisationTest < Test::Unit::TestCase
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
+
context "parse response" do
|
39
|
+
it "includes payment_terms" do
|
40
|
+
@instance = Xeroizer::Record::OrganisationModel.new(nil, "Organisation")
|
41
|
+
some_xml = get_record_xml("organisations")
|
42
|
+
|
43
|
+
result = @instance.parse_response(some_xml)
|
44
|
+
organisation = result.response_items.first
|
45
|
+
|
46
|
+
assert_equal(organisation.payment_terms.bills.day, "4")
|
47
|
+
assert_equal(organisation.payment_terms.bills.type, "OFFOLLOWINGMONTH")
|
48
|
+
assert_equal(organisation.payment_terms.sales.day, "2")
|
49
|
+
assert_equal(organisation.payment_terms.sales.type, "OFFOLLOWINGMONTH")
|
50
|
+
end
|
51
|
+
end
|
38
52
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PaymentServiceTest < Test::Unit::TestCase
|
4
|
+
include TestHelper
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@client = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "response parsing" do
|
11
|
+
it "parses default attributes" do
|
12
|
+
@instance = Xeroizer::Record::PaymentServiceModel.new(nil, "PaymentService")
|
13
|
+
|
14
|
+
some_xml = get_record_xml("payment_service")
|
15
|
+
|
16
|
+
result = @instance.parse_response(some_xml)
|
17
|
+
payment_service = result.response_items.first
|
18
|
+
|
19
|
+
keys = [:payment_service_id,
|
20
|
+
:payment_service_name,
|
21
|
+
:payment_service_type,
|
22
|
+
:payment_service_url,
|
23
|
+
:pay_now_text
|
24
|
+
]
|
25
|
+
|
26
|
+
assert_equal(payment_service.attributes.keys, keys)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -18,7 +18,7 @@ class RepeatingInvoiceTest < Test::Unit::TestCase
|
|
18
18
|
repeating_invoice = repeating_invoices.first
|
19
19
|
|
20
20
|
assert_equal "PowerDirect", repeating_invoice.contact_name
|
21
|
-
assert_equal BigDecimal
|
21
|
+
assert_equal BigDecimal(90), repeating_invoice.total
|
22
22
|
assert_equal true, repeating_invoice.accounts_payable?
|
23
23
|
|
24
24
|
schedule = repeating_invoice.schedule
|
@@ -104,6 +104,16 @@ class RecordBaseTest < Test::Unit::TestCase
|
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
107
|
+
context 'build' do
|
108
|
+
|
109
|
+
should "raise an undefined method error with useful message" do
|
110
|
+
assert_raise_message("undefined method `this_method_does_not_exist=' for #<Xeroizer::Record::Contact >") do
|
111
|
+
@client.Contact.build(:this_method_does_not_exist => true)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
107
117
|
context 'saving' do
|
108
118
|
context 'invalid record' do
|
109
119
|
setup do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xeroizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wayne Robinson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: rest-client
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: turn
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -297,6 +283,7 @@ files:
|
|
297
283
|
- lib/xeroizer/models/organisation.rb
|
298
284
|
- lib/xeroizer/models/overpayment.rb
|
299
285
|
- lib/xeroizer/models/payment.rb
|
286
|
+
- lib/xeroizer/models/payment_service.rb
|
300
287
|
- lib/xeroizer/models/payment_terms.rb
|
301
288
|
- lib/xeroizer/models/payroll/bank_account.rb
|
302
289
|
- lib/xeroizer/models/payroll/employee.rb
|
@@ -382,6 +369,7 @@ files:
|
|
382
369
|
- test/stub_responses/nonce_used
|
383
370
|
- test/stub_responses/organisation.xml
|
384
371
|
- test/stub_responses/organisations.xml
|
372
|
+
- test/stub_responses/payment_service.xml
|
385
373
|
- test/stub_responses/payments.xml
|
386
374
|
- test/stub_responses/prepayments.xml
|
387
375
|
- test/stub_responses/rate_limit_exceeded
|
@@ -611,6 +599,7 @@ files:
|
|
611
599
|
- test/unit/models/line_item_test.rb
|
612
600
|
- test/unit/models/manual_journal_test.rb
|
613
601
|
- test/unit/models/organisation_test.rb
|
602
|
+
- test/unit/models/payment_service_test.rb
|
614
603
|
- test/unit/models/phone_test.rb
|
615
604
|
- test/unit/models/prepayment_test.rb
|
616
605
|
- test/unit/models/repeating_invoice_test.rb
|
@@ -654,7 +643,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
654
643
|
version: '0'
|
655
644
|
requirements: []
|
656
645
|
rubyforge_project:
|
657
|
-
rubygems_version: 2.
|
646
|
+
rubygems_version: 2.5.1
|
658
647
|
signing_key:
|
659
648
|
specification_version: 4
|
660
649
|
summary: Ruby Library for Xero accounting API
|
@@ -693,6 +682,7 @@ test_files:
|
|
693
682
|
- test/stub_responses/nonce_used
|
694
683
|
- test/stub_responses/organisation.xml
|
695
684
|
- test/stub_responses/organisations.xml
|
685
|
+
- test/stub_responses/payment_service.xml
|
696
686
|
- test/stub_responses/payments.xml
|
697
687
|
- test/stub_responses/prepayments.xml
|
698
688
|
- test/stub_responses/rate_limit_exceeded
|
@@ -922,6 +912,7 @@ test_files:
|
|
922
912
|
- test/unit/models/line_item_test.rb
|
923
913
|
- test/unit/models/manual_journal_test.rb
|
924
914
|
- test/unit/models/organisation_test.rb
|
915
|
+
- test/unit/models/payment_service_test.rb
|
925
916
|
- test/unit/models/phone_test.rb
|
926
917
|
- test/unit/models/prepayment_test.rb
|
927
918
|
- test/unit/models/repeating_invoice_test.rb
|