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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # Xero
2
2
 
3
- TODO: Write a gem description
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
- TODO: Write usage instructions here
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
 
@@ -4,7 +4,6 @@ module Xero
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  module ClassMethods
7
-
8
7
  def belongs_to(association_name, options = {})
9
8
 
10
9
  attr_accessor :"#{association_name}_id"
@@ -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
@@ -6,6 +6,10 @@ module Xero
6
6
  @target = ::Array.new(*args)
7
7
  end
8
8
 
9
+ def xero_attributes
10
+ target.map(&:xero_attributes)
11
+ end
12
+
9
13
  protected
10
14
 
11
15
  def target
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']['Items']['Item']
57
- model.id = attrs["#{model.class.to_s.demodulize}ID"]
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
- cleanup_hash(attributes).each { |key, value| send("#{key}=", value) }
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
@@ -22,6 +22,8 @@ module Xero
22
22
 
23
23
  has_many :addresses
24
24
  has_many :phones
25
+
26
+ validates :name, presence: true
25
27
  end
26
28
  end
27
29
  end
@@ -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 :contact
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
@@ -1,3 +1,3 @@
1
1
  module Xero
2
- VERSION = "0.0.1.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -131,31 +131,68 @@ describe Xero::Clients::PrivateApplication do
131
131
  describe '#save' do
132
132
  before { configure }
133
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
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
- let(:purchase_detail_attributes) do
142
- { unit_price: 100, account_code: '620', tax_type: 'NONE' }
143
- end
142
+ let(:purchase_detail_attributes) do
143
+ { unit_price: 100, account_code: '620', tax_type: 'NONE' }
144
+ end
144
145
 
145
- let(:sales_detail_attributes) do
146
- { unit_price: 550, account_code: '200', tax_type: 'NONE' }
147
- end
146
+ let(:sales_detail_attributes) do
147
+ { unit_price: 550, account_code: '200', tax_type: 'NONE' }
148
+ end
148
149
 
149
- before do
150
- VCR.use_cassette('create_item') { client.save(item) }
151
- end
150
+ before do
151
+ VCR.use_cassette('create_item') { client.save(item) }
152
+ end
152
153
 
153
- it 'should populate the item id' do
154
- item.id.should_not be_blank
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
- it 'should be persisted' do
158
- item.should be_persisted
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
 
@@ -1,4 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Xero::Models::Contact do
4
+
5
+ it { should validate_presence_of(:name) }
4
6
  end
@@ -3,4 +3,8 @@ require 'spec_helper'
3
3
  describe Xero::Models::Invoice do
4
4
 
5
5
  it { should validate_presence_of(:type) }
6
+
7
+ it { should validate_presence_of(:contact) }
8
+
9
+ it { should validate_presence_of(:line_items) }
6
10
  end
@@ -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.1.1
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-03 00:00:00.000000000 Z
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