xero 0.0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/Guardfile +8 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +29 -0
  7. data/Rakefile +1 -0
  8. data/lib/active_support/inflection_config.rb +4 -0
  9. data/lib/active_support/inflections.rb +3 -0
  10. data/lib/oauth/consumer.rb +13 -0
  11. data/lib/xero/associations/belongs_to.rb +24 -0
  12. data/lib/xero/associations/has_many.rb +40 -0
  13. data/lib/xero/associations/has_many_proxy.rb +20 -0
  14. data/lib/xero/associations/has_one.rb +25 -0
  15. data/lib/xero/associations.rb +11 -0
  16. data/lib/xero/client.rb +83 -0
  17. data/lib/xero/clients/partner_application.rb +6 -0
  18. data/lib/xero/clients/private_application.rb +12 -0
  19. data/lib/xero/configuration.rb +14 -0
  20. data/lib/xero/connection.rb +62 -0
  21. data/lib/xero/models/account.rb +66 -0
  22. data/lib/xero/models/address.rb +28 -0
  23. data/lib/xero/models/base_model.rb +52 -0
  24. data/lib/xero/models/contact.rb +27 -0
  25. data/lib/xero/models/invoice.rb +37 -0
  26. data/lib/xero/models/item.rb +26 -0
  27. data/lib/xero/models/item_detail.rb +14 -0
  28. data/lib/xero/models/line_item.rb +16 -0
  29. data/lib/xero/models/payment.rb +21 -0
  30. data/lib/xero/models/phone.rb +18 -0
  31. data/lib/xero/models/tracking_category.rb +12 -0
  32. data/lib/xero/models/tracking_category_option.rb +12 -0
  33. data/lib/xero/version.rb +3 -0
  34. data/lib/xero.rb +39 -0
  35. data/spec/lib/xero/client_spec.rb +4 -0
  36. data/spec/lib/xero/clients/private_application_spec.rb +216 -0
  37. data/spec/lib/xero/models/account_spec.rb +38 -0
  38. data/spec/lib/xero/models/address_spec.rb +21 -0
  39. data/spec/lib/xero/models/base_model_spec.rb +37 -0
  40. data/spec/lib/xero/models/contact_spec.rb +4 -0
  41. data/spec/lib/xero/models/invoice_spec.rb +6 -0
  42. data/spec/lib/xero/models/item_detail_spec.rb +10 -0
  43. data/spec/lib/xero/models/item_spec.rb +119 -0
  44. data/spec/lib/xero/models/line_item_spec.rb +12 -0
  45. data/spec/lib/xero/models/payment_spec.rb +4 -0
  46. data/spec/lib/xero/models/phone_spec.rb +15 -0
  47. data/spec/lib/xero/models/tracking_category_option_spec.rb +4 -0
  48. data/spec/lib/xero/models/tracking_category_spec.rb +4 -0
  49. data/spec/spec_helper.rb +28 -0
  50. data/spec/support/find_account.xml +13 -0
  51. data/spec/support/helpers.rb +9 -0
  52. data/spec/support/vcr.rb +6 -0
  53. data/spec/vcr_cassettes/contact.yml +66 -0
  54. data/spec/vcr_cassettes/contacts.yml +66 -0
  55. data/spec/vcr_cassettes/create_item.yml +67 -0
  56. data/spec/vcr_cassettes/get_invoice.yml +79 -0
  57. data/spec/vcr_cassettes/get_item.yml +61 -0
  58. data/spec/vcr_cassettes/get_items.yml +67 -0
  59. data/spec/vcr_cassettes/invoices.yml +62 -0
  60. data/xero.gemspec +30 -0
  61. metadata +274 -0
@@ -0,0 +1,14 @@
1
+ module Xero
2
+ module Models
3
+ class ItemDetail < BaseModel
4
+
5
+ attribute :unit_price, type: Float
6
+ attribute :account_code
7
+ attribute :tax_type
8
+
9
+ validates :unit_price, presence: true
10
+ validates :account_code, presence: true
11
+ validates :tax_type, presence: true
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Xero
2
+ module Models
3
+ class LineItem < Xero::Models::BaseModel
4
+
5
+ attribute :description
6
+ attribute :quantity, type: Float
7
+ attribute :unit_amount, type: Float
8
+ attribute :account_code
9
+
10
+ validates :description, presence: true
11
+ validates :quantity, presence: true
12
+ validates :unit_amount, presence: true
13
+ validates :account_code, presence: true
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module Xero
2
+ module Models
3
+ class Payment < Xero::Models::BaseModel
4
+
5
+ self.path = 'Payments'
6
+
7
+ attribute :date, type: Date
8
+ attribute :currency_rate, type: Float
9
+ attribute :amount, type: Float
10
+ attribute :reference
11
+
12
+ belongs_to :invoice
13
+ belongs_to :account
14
+
15
+ validates :amount, presence: true
16
+ validates :date, presence: true
17
+ validates :invoice, presence: true
18
+ validates :account, presence: true
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,18 @@
1
+ module Xero
2
+ module Models
3
+ class Phone < BaseModel
4
+
5
+ attribute :phone_type
6
+ attribute :number
7
+ attribute :area_code
8
+ attribute :country_code
9
+
10
+ validates :phone_type, presence: true
11
+ validates :number, presence: true
12
+ validates :area_code, presence: true
13
+ validates :country_code, presence: true
14
+
15
+ belongs_to :invoice
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Xero
2
+ module Models
3
+ class TrackingCategory < Xero::Models::BaseModel
4
+
5
+ self.path = 'TrackingCategories'
6
+
7
+ attribute :name
8
+
9
+ has_many :tracking_category_options
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Xero
2
+ module Models
3
+ class TrackingCategoryOption < Xero::Models::BaseModel
4
+
5
+ attribute :name
6
+
7
+ validates :name, presence: true
8
+
9
+ belongs_to :tracking_category
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module Xero
2
+ VERSION = "0.0.1.1"
3
+ end
data/lib/xero.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'active_attr'
2
+ require 'active_support/core_ext'
3
+ require 'active_support/inflection_config'
4
+ require 'oauth'
5
+ require 'xero/associations/belongs_to'
6
+ require 'xero/associations/has_many'
7
+ require 'xero/associations/has_many_proxy'
8
+ require 'xero/associations/has_one'
9
+ require 'xero/associations'
10
+ require 'xero/client'
11
+ require 'xero/clients/partner_application'
12
+ require 'xero/clients/private_application'
13
+ require 'xero/configuration'
14
+ require 'xero/connection'
15
+ require 'xero/models/base_model'
16
+ require 'xero/models/account'
17
+ require 'xero/models/address'
18
+ require 'xero/models/contact'
19
+ require 'xero/models/invoice'
20
+ require 'xero/models/item'
21
+ require 'xero/models/item_detail'
22
+ require 'xero/models/line_item'
23
+ require 'xero/models/payment'
24
+ require 'xero/models/phone'
25
+ require 'xero/models/tracking_category'
26
+ require 'xero/models/tracking_category_option'
27
+ require 'xero/version'
28
+
29
+ module Xero
30
+ class << self
31
+ attr_accessor :configuration
32
+ end
33
+
34
+ def self.configure
35
+ self.configuration = Xero::Configuration.new
36
+ yield(configuration)
37
+ return self.configuration
38
+ end
39
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Client do
4
+ end
@@ -0,0 +1,216 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Clients::PrivateApplication do
4
+
5
+ let(:client) { Xero::Clients::PrivateApplication.new }
6
+
7
+ describe '#contacts' do
8
+ before { configure }
9
+
10
+ let(:contacts) do
11
+ VCR.use_cassette('contacts') { client.contacts }
12
+ end
13
+
14
+ it 'should return an array' do
15
+ contacts.should be_a(Array)
16
+ end
17
+
18
+ it 'should contain contacts' do
19
+ contacts.first.should be_a(Xero::Models::Contact)
20
+ end
21
+
22
+ it 'should populate the contacts id' do
23
+ contacts.first.id.should_not be_blank
24
+ end
25
+ end
26
+
27
+ describe '#get_contact' do
28
+ before { configure }
29
+
30
+ let(:contacts) do
31
+ VCR.use_cassette('contacts') { client.contacts }
32
+ end
33
+
34
+ let(:contact) do
35
+ VCR.use_cassette('contact') do
36
+ client.get_contact(contacts.first.id)
37
+ end
38
+ end
39
+
40
+ it 'should return a contact' do
41
+ contact.should be_a(Xero::Models::Contact)
42
+ end
43
+
44
+ it 'should populate the contact id' do
45
+ contact.id.should_not be_blank
46
+ end
47
+
48
+ it 'should populate the contact addresses' do
49
+ contact.addresses.first.should be_a(Xero::Models::Address)
50
+ end
51
+ end
52
+
53
+ describe '#get_invoice' do
54
+ before { configure }
55
+
56
+ let(:invoice) do
57
+ VCR.use_cassette('get_invoice') do
58
+ client.get_invoice('7f9e9823-f6d7-4302-90a1-ba59f6884ce9')
59
+ end
60
+ end
61
+
62
+ it 'should return an invoice' do
63
+ invoice.should be_a(Xero::Models::Invoice)
64
+ end
65
+
66
+ it 'should populate the type' do
67
+ invoice.type.should_not be_blank
68
+ end
69
+
70
+ it 'should populate the date' do
71
+ invoice.date.should_not be_blank
72
+ end
73
+
74
+ it 'should populate the due date' do
75
+ invoice.due_date.should_not be_blank
76
+ end
77
+
78
+ it 'should populate the invoice number' do
79
+ invoice.invoice_number.should_not be_blank
80
+ end
81
+
82
+ it 'should populate the total' do
83
+ invoice.total.should_not be_blank
84
+ end
85
+
86
+ it 'should populate the currency code' do
87
+ invoice.currency_code.should_not be_blank
88
+ end
89
+
90
+ it 'should populate the id' do
91
+ invoice.id.should_not be_blank
92
+ end
93
+
94
+ it 'should populate the total tax' do
95
+ invoice.total_tax.should_not be_blank
96
+ end
97
+
98
+ it 'should populate the invoice status' do
99
+ invoice.status.should eql('AUTHORISED')
100
+ end
101
+
102
+ it 'should populate the invoice contact' do
103
+ invoice.contact.should be_a(Xero::Models::Contact)
104
+ end
105
+
106
+ it 'should populate the contact data' do
107
+ invoice.contact.id.should_not be_blank
108
+ end
109
+ end
110
+
111
+ describe '#invoices' do
112
+ before { configure }
113
+
114
+ let(:invoices) do
115
+ VCR.use_cassette('invoices') { client.invoices }
116
+ end
117
+
118
+ it 'should return an array' do
119
+ invoices.should be_a(Array)
120
+ end
121
+
122
+ it 'should contain invoices' do
123
+ invoices.first.should be_a(Xero::Models::Invoice)
124
+ end
125
+
126
+ it 'should populate the invoice data' do
127
+ invoices.first.id.should_not be_blank
128
+ end
129
+ end
130
+
131
+ describe '#save' do
132
+ before { configure }
133
+
134
+ let(:item) do
135
+ Xero::Models::Item.new code: 'test-product',
136
+ description: 'just testing',
137
+ purchase_details: purchase_detail_attributes,
138
+ sales_details: sales_detail_attributes
139
+ end
140
+
141
+ let(:purchase_detail_attributes) do
142
+ { unit_price: 100, account_code: '620', tax_type: 'NONE' }
143
+ end
144
+
145
+ let(:sales_detail_attributes) do
146
+ { unit_price: 550, account_code: '200', tax_type: 'NONE' }
147
+ end
148
+
149
+ before do
150
+ VCR.use_cassette('create_item') { client.save(item) }
151
+ end
152
+
153
+ it 'should populate the item id' do
154
+ item.id.should_not be_blank
155
+ end
156
+
157
+ it 'should be persisted' do
158
+ item.should be_persisted
159
+ end
160
+ end
161
+
162
+ describe '#get_item' do
163
+
164
+ before { configure }
165
+
166
+ let(:item) do
167
+ client.get_item '99213658-83c4-438a-b104-1172b1e69790'
168
+ end
169
+
170
+ it 'should return an item' do
171
+ VCR.use_cassette('get_item') do
172
+ item.should be_a(Xero::Models::Item)
173
+ end
174
+ end
175
+ end
176
+
177
+ describe '#items' do
178
+ before { configure }
179
+
180
+ let(:items) do
181
+ VCR.use_cassette('get_items') { client.items }
182
+ end
183
+
184
+ it 'should return an array' do
185
+ items.should be_a(Array)
186
+ end
187
+
188
+ it 'should contain items' do
189
+ items.first.should be_a(Xero::Models::Item)
190
+ end
191
+
192
+ it 'should populate the id' do
193
+ items.first.id.should_not be_blank
194
+ end
195
+
196
+ it 'should populate the item code' do
197
+ items.first.code.should_not be_blank
198
+ end
199
+
200
+ it 'should populate the item description' do
201
+ items.first.description.should_not be_blank
202
+ end
203
+
204
+ it 'should populate the item purchase detail' do
205
+ items.first.purchase_details.should be_a(Xero::Models::ItemDetail)
206
+ end
207
+
208
+ it 'should populate the item sales detail' do
209
+ items.first.sales_details.should be_a(Xero::Models::ItemDetail)
210
+ end
211
+
212
+ it 'should populate the item purchase detail account code' do
213
+ items.first.purchase_details.account_code.should_not be_blank
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::Account do
4
+
5
+ # describe '.from_xml' do
6
+ # let(:account) do
7
+ # Xero::Models::Account.from_xml(File.read('spec/support/find_account.xml'))
8
+ # end
9
+
10
+ # it 'should populate the account id' do
11
+ # account.id.should eql('297c2dc5-cc47-4afd-8ec8-74990b8761e9')
12
+ # end
13
+
14
+ # it 'should populate the name' do
15
+ # account.name.should eql('BNZ Cheque Account')
16
+ # end
17
+
18
+ # it 'should populate the account type' do
19
+ # account.account_type.should eql('BANK')
20
+ # end
21
+
22
+ # it 'should populate the tax type' do
23
+ # account.tax_type.should eql('NONE')
24
+ # end
25
+
26
+ # it 'should populate enable payments to account' do
27
+ # account.enable_payments_to_account.should eql(false)
28
+ # end
29
+
30
+ # it 'should populate bank account number' do
31
+ # account.bank_account_number.should eql('3809087654321500')
32
+ # end
33
+
34
+ # it 'should populate the currency code' do
35
+ # account.currency_code.should eql('NZD')
36
+ # end
37
+ # end
38
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::Address do
4
+
5
+ describe 'validations' do
6
+
7
+ it { should validate_presence_of(:address_type) }
8
+
9
+ it { should validate_presence_of(:attention_to) }
10
+
11
+ it { should validate_presence_of(:address_line1) }
12
+
13
+ it { should validate_presence_of(:city) }
14
+
15
+ it { should validate_presence_of(:region) }
16
+
17
+ it { should validate_presence_of(:postal_code) }
18
+
19
+ it { should validate_presence_of(:country) }
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::BaseModel do
4
+
5
+ describe '#initialize' do
6
+ let(:model) { Xero::Models::BaseModel.new }
7
+
8
+ it 'should set new_record to true' do
9
+ model.new_record.should be_true
10
+ end
11
+ end
12
+
13
+ describe '#save' do
14
+ context 'when client is blank' do
15
+ let(:model) { Xero::Models::BaseModel.new }
16
+
17
+ it 'should raise an error' do
18
+ expect { model.save }.to raise_error
19
+ end
20
+ end
21
+ end
22
+
23
+ describe '#xero_attributes' do
24
+ let(:model) do
25
+ Xero::Models::BaseModel.new id: 'asdf'
26
+ end
27
+
28
+
29
+ it 'should not include the id' do
30
+ model.xero_attributes['BaseModelId'].should be_blank
31
+ end
32
+
33
+ it 'should camelize the attributes' do
34
+ model.xero_attributes(x_attr: 'something')['XAttr'].should eql('something')
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::Contact do
4
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::Invoice do
4
+
5
+ it { should validate_presence_of(:type) }
6
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::ItemDetail do
4
+
5
+ it { should validate_presence_of(:unit_price) }
6
+
7
+ it { should validate_presence_of(:account_code) }
8
+
9
+ it { should validate_presence_of(:tax_type) }
10
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::Item do
4
+
5
+ describe 'validations' do
6
+ it { should validate_presence_of(:code) }
7
+ end
8
+
9
+ describe 'to_xero_xml' do
10
+ let(:item) do
11
+ Xero::Models::Item.new(
12
+ purchase_details: purchase_detail_attributes,
13
+ sales_details: sales_detail_attributes,
14
+ id: '34b3fc86-483e-4112-8106-9b23d36f925c',
15
+ code: 'Monster',
16
+ description: 'Test description'
17
+ )
18
+ end
19
+
20
+ let(:purchase_detail_attributes) do
21
+ { unit_price: 100, account_code: '620', tax_type: 'NONE' }
22
+ end
23
+
24
+ let(:sales_detail_attributes) do
25
+ { unit_price: 550, account_code: '200', tax_type: 'NONE' }
26
+ end
27
+
28
+ subject { item.to_xero_xml }
29
+
30
+ it 'should include the purchase detail' do
31
+ subject.should match(/PurchaseDetails/)
32
+ end
33
+
34
+ it 'should include the sales detail' do
35
+ subject.should match(/SalesDetails/)
36
+ end
37
+
38
+ it 'should not include the id' do
39
+ subject.should_not match(/ItemId/)
40
+ end
41
+
42
+ it 'should not include the id value' do
43
+ subject.should_not match(/34b3fc86\-483e\-4112\-8106\-9b23d36f925c/)
44
+ end
45
+
46
+ it 'should include the code' do
47
+ subject.should match(/Code/)
48
+ end
49
+
50
+ it 'should include the code value' do
51
+ subject.should match(/Monster/)
52
+ end
53
+
54
+ it 'should include the unit price' do
55
+ subject.should match(/UnitPrice/)
56
+ end
57
+
58
+ it 'should include the description' do
59
+ subject.should match(/Description/)
60
+ end
61
+
62
+ it 'should include the description value' do
63
+ subject.should match(/Test description/)
64
+ end
65
+ end
66
+
67
+ describe '#purchase_details=' do
68
+
69
+ let(:item) { Xero::Models::Item.new }
70
+
71
+ before do
72
+ item.purchase_details = {
73
+ unit_price: 100, account_code: '620', tax_type: 'NONE'
74
+ }
75
+ end
76
+
77
+ it 'should add a new item detail to the item' do
78
+ item.purchase_details.should be_a(Xero::Models::ItemDetail)
79
+ end
80
+
81
+ it 'should set the unit price' do
82
+ item.purchase_details.unit_price.should eql(100.0)
83
+ end
84
+
85
+ it 'should set the account code' do
86
+ item.purchase_details.account_code.should eql('620')
87
+ end
88
+
89
+ it 'should set the tax type' do
90
+ item.purchase_details.tax_type.should eql('NONE')
91
+ end
92
+ end
93
+
94
+ describe '#sales_details=' do
95
+ let(:item) { Xero::Models::Item.new }
96
+
97
+ before do
98
+ item.sales_details = {
99
+ unit_price: 550, account_code: '200', tax_type: 'NONE'
100
+ }
101
+ end
102
+
103
+ it 'should add a new item detail to the item' do
104
+ item.sales_details.should be_a(Xero::Models::ItemDetail)
105
+ end
106
+
107
+ it 'should set the unit price' do
108
+ item.sales_details.unit_price.should eql(550.0)
109
+ end
110
+
111
+ it 'should set the account code' do
112
+ item.sales_details.account_code.should eql('200')
113
+ end
114
+
115
+ it 'should set the tax type' do
116
+ item.sales_details.tax_type.should eql('NONE')
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::LineItem do
4
+
5
+ it { should validate_presence_of(:description) }
6
+
7
+ it { should validate_presence_of(:quantity) }
8
+
9
+ it { should validate_presence_of(:unit_amount) }
10
+
11
+ it { should validate_presence_of(:account_code) }
12
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::Payment do
4
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::Phone do
4
+
5
+ describe 'validations' do
6
+
7
+ it { should validate_presence_of(:phone_type) }
8
+
9
+ it { should validate_presence_of(:number) }
10
+
11
+ it { should validate_presence_of(:area_code) }
12
+
13
+ it { should validate_presence_of(:country_code) }
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::TrackingCategoryOption do
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xero::Models::TrackingCategory do
4
+ end
@@ -0,0 +1,28 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # Require this file using `require "spec_helper"` to ensure that it is only
4
+ # loaded once.
5
+ #
6
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
7
+
8
+ require 'active_attr/rspec'
9
+ require 'bundler/setup'
10
+ require 'xero'
11
+ require 'rubygems'
12
+ require 'shoulda-matchers'
13
+ require 'support/helpers'
14
+ require 'support/vcr'
15
+
16
+ RSpec.configure do |config|
17
+ config.treat_symbols_as_metadata_keys_with_true_values = true
18
+ config.run_all_when_everything_filtered = true
19
+ config.filter_run :focus
20
+
21
+ # Run specs in random order to surface order dependencies. If you find an
22
+ # order dependency and want to debug it, you can fix the order by providing
23
+ # the seed, which is printed after each run.
24
+ # --seed 1234
25
+ config.order = 'random'
26
+
27
+ config.include Helpers
28
+ end