xero 0.0.1.1 → 0.0.2

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.
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