xero 0.0.1.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +5 -2
- data/lib/xero/associations/belongs_to.rb +0 -1
- data/lib/xero/associations/has_many.rb +8 -11
- data/lib/xero/associations/has_many_proxy.rb +4 -0
- data/lib/xero/client.rb +4 -2
- data/lib/xero/models/base_model.rb +7 -2
- data/lib/xero/models/contact.rb +2 -0
- data/lib/xero/models/invoice.rb +14 -1
- data/lib/xero/version.rb +1 -1
- data/spec/lib/xero/clients/private_application_spec.rb +56 -19
- data/spec/lib/xero/models/contact_spec.rb +2 -0
- data/spec/lib/xero/models/invoice_spec.rb +4 -0
- data/spec/vcr_cassettes/save_invoice.yml +83 -0
- metadata +4 -2
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Xero
|
2
2
|
|
3
|
-
|
3
|
+
ActiveModel compliant library for talking with the Xero API
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -18,7 +18,10 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
client = Xero::Clients::PrivateApplication.new
|
22
|
+
contacts = client.contacts
|
23
|
+
invoices = client.invoices
|
24
|
+
items = client.items
|
22
25
|
|
23
26
|
## Contributing
|
24
27
|
|
@@ -16,22 +16,19 @@ module Xero
|
|
16
16
|
end
|
17
17
|
|
18
18
|
define_method "#{association_name}=" do |value|
|
19
|
+
klass = options[:class_name] || association_name.to_s.singularize
|
20
|
+
klass = "Xero::Models::#{klass.to_s.classify}".constantize
|
21
|
+
|
19
22
|
if value.is_a?(Hash) && value[value.keys.first].is_a?(Array)
|
20
|
-
klass = options[:class_name] || association_name.to_s.singularize
|
21
|
-
klass = "Xero::Models::#{klass.to_s.classify}".constantize
|
22
23
|
value[value.keys.first].each do |item|
|
23
24
|
self.send(association_name).send :<<, klass.new(item)
|
24
25
|
end
|
26
|
+
elsif value.is_a?(Array) && value.all? { |a| a.is_a?(klass) }
|
27
|
+
instance_variable_set(
|
28
|
+
:"@#{association_name}", HasManyProxy.new(value)
|
29
|
+
)
|
25
30
|
end
|
26
|
-
|
27
|
-
# if value.is_a?(Hash)
|
28
|
-
# klass = options[:class_name] || association_name.to_s.singularize
|
29
|
-
# value = "Xero::Models::#{klass.to_s.classify}".constantize.
|
30
|
-
# new(value)
|
31
|
-
# end
|
32
|
-
# instance_variable_set(
|
33
|
-
# :"@#{association_name}", HasManyProxy.new(value)
|
34
|
-
# )
|
31
|
+
self.send(association_name)
|
35
32
|
end
|
36
33
|
end
|
37
34
|
end
|
data/lib/xero/client.rb
CHANGED
@@ -53,8 +53,10 @@ module Xero
|
|
53
53
|
def save(model)
|
54
54
|
model.tap do |item|
|
55
55
|
response = self.connection.post(model.class.path, model.to_xero_xml)
|
56
|
-
attrs = Hash.from_xml(response.body)['Response'][
|
57
|
-
|
56
|
+
attrs = Hash.from_xml(response.body)['Response'][
|
57
|
+
"#{model.class.to_s.demodulize.pluralize}"
|
58
|
+
][model.class.to_s.demodulize]
|
59
|
+
model.attributes = attrs
|
58
60
|
model.new_record = false
|
59
61
|
end
|
60
62
|
end
|
@@ -14,7 +14,11 @@ module Xero
|
|
14
14
|
|
15
15
|
def initialize(attributes = {})
|
16
16
|
@new_record = true
|
17
|
-
|
17
|
+
self.attributes = attributes
|
18
|
+
end
|
19
|
+
|
20
|
+
def attributes=(attrs)
|
21
|
+
cleanup_hash(attrs).each { |key, value| send("#{key}=", value) }
|
18
22
|
end
|
19
23
|
|
20
24
|
def save
|
@@ -25,10 +29,11 @@ module Xero
|
|
25
29
|
def xero_attributes(attrs = nil)
|
26
30
|
attrs ||= attributes.clone
|
27
31
|
attrs.delete('id')
|
32
|
+
attrs.delete('updated_date_utc')
|
28
33
|
attrs.keys.each do |key|
|
29
34
|
value = attrs.delete(key)
|
30
35
|
value = xero_attributes(value) if value.is_a?(Hash)
|
31
|
-
attrs[key.to_s.camelize] = value.to_s
|
36
|
+
attrs[key.to_s.camelize] = value.to_s unless value.blank?
|
32
37
|
end
|
33
38
|
attrs
|
34
39
|
end
|
data/lib/xero/models/contact.rb
CHANGED
data/lib/xero/models/invoice.rb
CHANGED
@@ -4,6 +4,8 @@ module Xero
|
|
4
4
|
|
5
5
|
self.path = 'Invoices'
|
6
6
|
|
7
|
+
TYPES = ['ACCPAY', 'ACCREC']
|
8
|
+
|
7
9
|
attribute :type
|
8
10
|
attribute :date, type: Date
|
9
11
|
attribute :due_date, type: Date
|
@@ -27,11 +29,22 @@ module Xero
|
|
27
29
|
attribute :sent_to_contact, type: Boolean
|
28
30
|
attribute :currency_rate
|
29
31
|
|
30
|
-
has_one
|
32
|
+
has_one :contact
|
31
33
|
has_many :line_items
|
32
34
|
has_many :payments
|
33
35
|
|
34
36
|
validates :type, presence: true
|
37
|
+
validates :contact, presence: true
|
38
|
+
validates :line_items, presence: true
|
39
|
+
|
40
|
+
def to_xero_xml
|
41
|
+
xero_attributes(attributes.clone).
|
42
|
+
merge('Contact' => contact.xero_attributes).
|
43
|
+
merge('LineItems' => line_items.xero_attributes).
|
44
|
+
merge('Payments' => payments.xero_attributes).
|
45
|
+
to_xml(root: 'Invoice')
|
46
|
+
end
|
47
|
+
|
35
48
|
end
|
36
49
|
end
|
37
50
|
end
|
data/lib/xero/version.rb
CHANGED
@@ -131,31 +131,68 @@ describe Xero::Clients::PrivateApplication do
|
|
131
131
|
describe '#save' do
|
132
132
|
before { configure }
|
133
133
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
134
|
+
context 'when saving an item' do
|
135
|
+
let(:item) do
|
136
|
+
Xero::Models::Item.new code: 'test-product',
|
137
|
+
description: 'just testing',
|
138
|
+
purchase_details: purchase_detail_attributes,
|
139
|
+
sales_details: sales_detail_attributes
|
140
|
+
end
|
140
141
|
|
141
|
-
|
142
|
-
|
143
|
-
|
142
|
+
let(:purchase_detail_attributes) do
|
143
|
+
{ unit_price: 100, account_code: '620', tax_type: 'NONE' }
|
144
|
+
end
|
144
145
|
|
145
|
-
|
146
|
-
|
147
|
-
|
146
|
+
let(:sales_detail_attributes) do
|
147
|
+
{ unit_price: 550, account_code: '200', tax_type: 'NONE' }
|
148
|
+
end
|
148
149
|
|
149
|
-
|
150
|
-
|
151
|
-
|
150
|
+
before do
|
151
|
+
VCR.use_cassette('create_item') { client.save(item) }
|
152
|
+
end
|
152
153
|
|
153
|
-
|
154
|
-
|
154
|
+
it 'should populate the item id' do
|
155
|
+
item.id.should_not be_blank
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'should be persisted' do
|
159
|
+
item.should be_persisted
|
160
|
+
end
|
155
161
|
end
|
156
162
|
|
157
|
-
|
158
|
-
|
163
|
+
context 'when saving an invoice' do
|
164
|
+
let(:invoice) do
|
165
|
+
Xero::Models::Invoice.new(
|
166
|
+
type: 'ACCREC', contact: contact, line_items: line_items
|
167
|
+
)
|
168
|
+
end
|
169
|
+
|
170
|
+
let(:contact) do
|
171
|
+
Xero::Models::Contact.new(name: 'Xero Gem Test Contact')
|
172
|
+
end
|
173
|
+
|
174
|
+
let(:line_items) { [line_item] }
|
175
|
+
|
176
|
+
let(:line_item) do
|
177
|
+
Xero::Models::LineItem.new(
|
178
|
+
description: 'A test line item from the xero gem',
|
179
|
+
quantity: 2.0,
|
180
|
+
unit_amount: 150.5,
|
181
|
+
account_code: 200
|
182
|
+
)
|
183
|
+
end
|
184
|
+
|
185
|
+
before do
|
186
|
+
VCR.use_cassette('save_invoice') { client.save(invoice) }
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should persist the invoice' do
|
190
|
+
invoice.should be_persisted
|
191
|
+
end
|
192
|
+
|
193
|
+
it 'should populate the contact id' do
|
194
|
+
invoice.contact.id.should_not be_blank
|
195
|
+
end
|
159
196
|
end
|
160
197
|
end
|
161
198
|
|
@@ -0,0 +1,83 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: https://api.xero.com/api.xro/2.0/Invoices
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: xml=%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%0A%3CInvoice%3E%0A%20%20%3CType%3EACCREC%3C%2FType%3E%0A%20%20%3CContact%3E%0A%20%20%20%20%3CName%3EXero%20Gem%20Test%20Contact%3C%2FName%3E%0A%20%20%3C%2FContact%3E%0A%20%20%3CLineItems%20type%3D%22array%22%3E%0A%20%20%20%20%3CLineItem%3E%0A%20%20%20%20%20%20%3CDescription%3EA%20test%20line%20item%20from%20the%20xero%20gem%3C%2FDescription%3E%0A%20%20%20%20%20%20%3CQuantity%3E2.0%3C%2FQuantity%3E%0A%20%20%20%20%20%20%3CUnitAmount%3E150.5%3C%2FUnitAmount%3E%0A%20%20%20%20%20%20%3CAccountCode%3E200%3C%2FAccountCode%3E%0A%20%20%20%20%3C%2FLineItem%3E%0A%20%20%3C%2FLineItems%3E%0A%20%20%3CPayments%20type%3D%22array%22%2F%3E%0A%3C%2FInvoice%3E%0A
|
9
|
+
headers:
|
10
|
+
charset:
|
11
|
+
- utf-8
|
12
|
+
accept:
|
13
|
+
- ! '*/*'
|
14
|
+
user-agent:
|
15
|
+
- OAuth gem v0.4.7
|
16
|
+
content-length:
|
17
|
+
- '0'
|
18
|
+
content-type:
|
19
|
+
- application/x-www-form-urlencoded
|
20
|
+
authorization:
|
21
|
+
- OAuth oauth_consumer_key="TYMATGTPO5QEAWP8I307AOMBHSOJI2", oauth_nonce="op3Dhu2katMP8le9vB7p3vC1UHIJPHjNmMSZD3RYJ4",
|
22
|
+
oauth_signature="XDBdEuzFijTwE68oekbRE%2BArEv0gt13xMS6izN7qkCf4s6BuRt%2FtIjFKPCHsDXBfaPS%2FVykUTG77PNvvciWc7ImNQv5c23Gm7Mrvtkzw3aH1g%2Fd75QknBp%2FBo8Ik80Rn87Ug3NgKTCCgzlXe7uJ5Nvps02E7LLsb2uWd4nLyEQA%3D",
|
23
|
+
oauth_signature_method="RSA-SHA1", oauth_timestamp="1351978764", oauth_token="TYMATGTPO5QEAWP8I307AOMBHSOJI2",
|
24
|
+
oauth_version="1.0"
|
25
|
+
response:
|
26
|
+
status:
|
27
|
+
code: 200
|
28
|
+
message: OK
|
29
|
+
headers:
|
30
|
+
cache-control:
|
31
|
+
- private
|
32
|
+
content-type:
|
33
|
+
- text/xml; charset=utf-8
|
34
|
+
server:
|
35
|
+
- Microsoft-IIS/7.0
|
36
|
+
x-aspnetmvc-version:
|
37
|
+
- '2.0'
|
38
|
+
www-authenticate:
|
39
|
+
- OAuth Realm="api.xero.com"
|
40
|
+
x-aspnet-version:
|
41
|
+
- 4.0.30319
|
42
|
+
x-s:
|
43
|
+
- api2
|
44
|
+
x-powered-by:
|
45
|
+
- ASP.NET
|
46
|
+
date:
|
47
|
+
- Sat, 03 Nov 2012 21:39:22 GMT
|
48
|
+
connection:
|
49
|
+
- close
|
50
|
+
content-length:
|
51
|
+
- '2343'
|
52
|
+
body:
|
53
|
+
encoding: US-ASCII
|
54
|
+
string: ! "<Response xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\r\n
|
55
|
+
\ <Id>5321e06c-062f-4b99-9fe5-e48b56e04c5a</Id>\r\n <Status>OK</Status>\r\n
|
56
|
+
\ <ProviderName>GoHiring</ProviderName>\r\n <DateTimeUTC>2012-11-03T21:39:22.937917Z</DateTimeUTC>\r\n
|
57
|
+
\ <Invoices>\r\n <Invoice>\r\n <Contact>\r\n <ContactID>a18c8d85-7ac1-4f14-b470-50adf56ee45f</ContactID>\r\n
|
58
|
+
\ <ContactStatus>ACTIVE</ContactStatus>\r\n <Name>Xero Gem Test
|
59
|
+
Contact</Name>\r\n <Addresses>\r\n <Address>\r\n <AddressType>POBOX</AddressType>\r\n
|
60
|
+
\ </Address>\r\n <Address>\r\n <AddressType>STREET</AddressType>\r\n
|
61
|
+
\ </Address>\r\n </Addresses>\r\n <Phones>\r\n <Phone>\r\n
|
62
|
+
\ <PhoneType>DDI</PhoneType>\r\n </Phone>\r\n <Phone>\r\n
|
63
|
+
\ <PhoneType>MOBILE</PhoneType>\r\n </Phone>\r\n <Phone>\r\n
|
64
|
+
\ <PhoneType>FAX</PhoneType>\r\n </Phone>\r\n <Phone>\r\n
|
65
|
+
\ <PhoneType>DEFAULT</PhoneType>\r\n </Phone>\r\n </Phones>\r\n
|
66
|
+
\ <UpdatedDateUTC>2012-11-03T21:39:17.313</UpdatedDateUTC>\r\n <IsSupplier>false</IsSupplier>\r\n
|
67
|
+
\ <IsCustomer>true</IsCustomer>\r\n </Contact>\r\n <Date>2012-11-03T00:00:00</Date>\r\n
|
68
|
+
\ <Status>DRAFT</Status>\r\n <LineAmountTypes>Exclusive</LineAmountTypes>\r\n
|
69
|
+
\ <LineItems>\r\n <LineItem>\r\n <Description>A test line
|
70
|
+
item from the xero gem</Description>\r\n <UnitAmount>150.50</UnitAmount>\r\n
|
71
|
+
\ <TaxType>OUTPUT</TaxType>\r\n <TaxAmount>0.00</TaxAmount>\r\n
|
72
|
+
\ <LineAmount>301.00</LineAmount>\r\n <AccountCode>200</AccountCode>\r\n
|
73
|
+
\ <Quantity>2.0000</Quantity>\r\n </LineItem>\r\n </LineItems>\r\n
|
74
|
+
\ <SubTotal>301.00</SubTotal>\r\n <TotalTax>0.00</TotalTax>\r\n <Total>301.00</Total>\r\n
|
75
|
+
\ <UpdatedDateUTC>2012-11-03T21:39:22.89</UpdatedDateUTC>\r\n <CurrencyCode>EUR</CurrencyCode>\r\n
|
76
|
+
\ <Type>ACCREC</Type>\r\n <InvoiceID>22f90b95-d952-4664-88f9-06900af307e5</InvoiceID>\r\n
|
77
|
+
\ <InvoiceNumber>INV-0003</InvoiceNumber>\r\n <AmountDue>301.00</AmountDue>\r\n
|
78
|
+
\ <AmountPaid>0.00</AmountPaid>\r\n <SentToContact>false</SentToContact>\r\n
|
79
|
+
\ <CurrencyRate>1.000000</CurrencyRate>\r\n <HasAttachments>false</HasAttachments>\r\n
|
80
|
+
\ </Invoice>\r\n </Invoices>\r\n</Response>"
|
81
|
+
http_version: '1.1'
|
82
|
+
recorded_at: Sat, 03 Nov 2012 21:39:27 GMT
|
83
|
+
recorded_with: VCR 2.2.5
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-11-
|
12
|
+
date: 2012-11-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: active_attr
|
@@ -221,6 +221,7 @@ files:
|
|
221
221
|
- spec/vcr_cassettes/get_item.yml
|
222
222
|
- spec/vcr_cassettes/get_items.yml
|
223
223
|
- spec/vcr_cassettes/invoices.yml
|
224
|
+
- spec/vcr_cassettes/save_invoice.yml
|
224
225
|
- xero.gemspec
|
225
226
|
homepage: https://github.com/mattbeedle/xero
|
226
227
|
licenses: []
|
@@ -272,3 +273,4 @@ test_files:
|
|
272
273
|
- spec/vcr_cassettes/get_item.yml
|
273
274
|
- spec/vcr_cassettes/get_items.yml
|
274
275
|
- spec/vcr_cassettes/invoices.yml
|
276
|
+
- spec/vcr_cassettes/save_invoice.yml
|