xeroizer 0.3.4 → 0.3.5

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
@@ -58,12 +58,12 @@ Authentication occcurs in 3 steps:
58
58
 
59
59
  client = Xeroizer::PublicApplication.new(YOUR_OAUTH_CONSUMER_KEY, YOUR_OAUTH_CONSUMER_SECRET)
60
60
 
61
- # 1. Get a RequestToken from Xero. The :oauth_url is the URL the user will be redirected to
61
+ # 1. Get a RequestToken from Xero. :oauth_callback is the URL the user will be redirected to
62
62
  # after they have authenticated your application.
63
63
  #
64
64
  # Note: The callback URL's domain must match that listed for your application in http://api.xero.com
65
65
  # otherwise the user will not be redirected and only be shown the authentication code.
66
- request_token = client.request_token(:oauth_url => 'http://yourapp.com/oauth/callback')
66
+ request_token = client.request_token(:oauth_callback => 'http://yourapp.com/oauth/callback')
67
67
 
68
68
  # 2. Redirect the user to the URL specified by the RequestToken.
69
69
  #
@@ -90,7 +90,7 @@ You can now use the client to access the Xero API methods, e.g.
90
90
  public
91
91
 
92
92
  def new
93
- request_token = @xero_client.request_token(:oauth_url => 'http://yourapp.com/xero_session/create')
93
+ request_token = @xero_client.request_token(:oauth_callback => 'http://yourapp.com/xero_session/create')
94
94
  session[:request_token] = request_token.token
95
95
  session[:request_secret] = request_token.secret
96
96
 
@@ -194,12 +194,12 @@ Authentication occcurs in 3 steps:
194
194
  "/path/to/entrust-private-nopass.pem"
195
195
  )
196
196
 
197
- # 1. Get a RequestToken from Xero. The :oauth_url is the URL the user will be redirected to
197
+ # 1. Get a RequestToken from Xero. :oauth_callback is the URL the user will be redirected to
198
198
  # after they have authenticated your application.
199
199
  #
200
200
  # Note: The callback URL's domain must match that listed for your application in http://api.xero.com
201
201
  # otherwise the user will not be redirected and only be shown the authentication code.
202
- request_token = client.request_token(:oauth_url => 'http://yourapp.com/oauth/callback')
202
+ request_token = client.request_token(:oauth_callback => 'http://yourapp.com/oauth/callback')
203
203
 
204
204
  # 2. Redirect the user to the URL specified by the RequestToken.
205
205
  #
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.3.5
@@ -77,15 +77,21 @@ module Xeroizer
77
77
  has_many :payments
78
78
  has_many :credit_notes
79
79
 
80
- validates_presence_of :date, :due_date
80
+ validates_presence_of :date, :due_date, :unless => proc { |invoice| invoice.new_record? }
81
81
  validates_inclusion_of :type, :in => INVOICE_TYPES
82
- validates_inclusion_of :status, :in => INVOICE_STATUSES
83
- validates_inclusion_of :line_amount_types, :in => LINE_AMOUNT_TYPES
82
+ validates_inclusion_of :status, :in => INVOICE_STATUSES, :unless => proc { |invoice| invoice.new_record? }
83
+ validates_inclusion_of :line_amount_types, :in => LINE_AMOUNT_TYPES, :unless => proc { |invoice| invoice.new_record? }
84
84
  validates_associated :contact
85
- validates_associated :line_items
85
+ validates_associated :line_items, :allow_blanks => true, :unless => proc { |invoice| invoice.approved? }
86
+ validates_associated :line_items, :if => proc { |invoice| invoice.approved? }
86
87
 
87
88
  public
88
-
89
+
90
+ # Helper method to check if the invoice has been approved.
91
+ def approved?
92
+ [ 'AUTHORISED', 'PAID', 'VOIDED' ].include? status
93
+ end
94
+
89
95
  # Helper method to check if the invoice is accounts payable.
90
96
  def accounts_payable?
91
97
  type == 'ACCPAY'
@@ -4,7 +4,7 @@ module Xeroizer
4
4
  class ManualJournalModel < BaseModel
5
5
 
6
6
  set_permissions :read, :write, :update
7
-
7
+
8
8
  end
9
9
 
10
10
  class ManualJournal < Base
@@ -3,6 +3,9 @@ module Xeroizer
3
3
 
4
4
  class ManualJournalLineModel < BaseModel
5
5
 
6
+ set_xml_root_name 'JournalLines'
7
+ set_xml_node_name 'JournalLine'
8
+
6
9
  end
7
10
 
8
11
  class ManualJournalLine < Base
@@ -18,14 +18,16 @@ module Xeroizer
18
18
  # @param [Hash] options other options to pass to the GenericApplication constructor
19
19
  # @return [PartnerApplication] instance of PrivateApplication
20
20
  def initialize(consumer_key, consumer_secret, path_to_private_key, path_to_ssl_client_cert, path_to_ssl_client_key, options = {})
21
- options.merge!(
22
- :xero_url => 'https://api-partner.network.xero.com/api.xro/2.0',
23
- :site => 'https://api-partner.network.xero.com',
24
- :authorize_url => 'https://api.xero.com/oauth/Authorize',
25
- :signature_method => 'RSA-SHA1',
21
+ default_options = {
22
+ :xero_url => 'https://api-partner.network.xero.com/api.xro/2.0',
23
+ :site => 'https://api-partner.network.xero.com',
24
+ :authorize_url => 'https://api.xero.com/oauth/Authorize',
25
+ :signature_method => 'RSA-SHA1'
26
+ }
27
+ options = default_options.merge(options).merge(
26
28
  :private_key_file => path_to_private_key,
27
- :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read(path_to_ssl_client_cert)),
28
- :ssl_client_key => OpenSSL::PKey::RSA.new(File.read(path_to_ssl_client_key))
29
+ :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read(path_to_ssl_client_cert)),
30
+ :ssl_client_key => OpenSSL::PKey::RSA.new(File.read(path_to_ssl_client_key))
29
31
  )
30
32
  super(consumer_key, consumer_secret, options)
31
33
 
@@ -81,6 +81,7 @@ module Xeroizer
81
81
  else
82
82
  update
83
83
  end
84
+ @complete_record_downloaded = true
84
85
  true
85
86
  end
86
87
 
@@ -61,6 +61,9 @@ module Xeroizer
61
61
  raise StandardError.new("Invalid arguments for #{self.class.name}#add_#{internal_singular_field_name}(#{args.inspect}).")
62
62
  end
63
63
 
64
+ # Ensure that complete record is downloaded before adding new records
65
+ self.send(field_name)
66
+
64
67
  # Add each record.
65
68
  record = nil
66
69
  records.each do | record |
@@ -109,6 +112,9 @@ module Xeroizer
109
112
  when record_class
110
113
  self.attributes[field_name] = ((association_type == :has_many) ? [value] : value)
111
114
 
115
+ when NilClass
116
+ self.attributes[field_name] = []
117
+
112
118
  else
113
119
  raise AssociationTypeMismatch.new(record_class, value.class)
114
120
  end
@@ -58,10 +58,9 @@ module Xeroizer
58
58
  def to_xml(b = Builder::XmlMarkup.new(:indent => 2))
59
59
  b.tag!(parent.class.xml_node_name || parent.model_name) {
60
60
  attributes.each do | key, value |
61
- unless value.nil?
62
- field = self.class.fields[key]
63
- xml_value_from_field(b, field, value)
64
- end
61
+ field = self.class.fields[key]
62
+ value = self.send(key) if field[:calculated]
63
+ xml_value_from_field(b, field, value) unless value.nil?
65
64
  end
66
65
  }
67
66
  end
@@ -1849,5 +1849,51 @@
1849
1849
  <AmountDue>0.00</AmountDue>
1850
1850
  <AmountPaid>1500.00</AmountPaid>
1851
1851
  </Invoice>
1852
+ <Invoice>
1853
+ <Contact>
1854
+ <ContactID>9601cac0-db41-4255-8cc6-f38b555ce53f</ContactID>
1855
+ <ContactStatus>ACTIVE</ContactStatus>
1856
+ <Name>ABC</Name>
1857
+ <Addresses>
1858
+ <Address>
1859
+ <AddressType>STREET</AddressType>
1860
+ </Address>
1861
+ <Address>
1862
+ <AddressType>POBOX</AddressType>
1863
+ </Address>
1864
+ </Addresses>
1865
+ <Phones>
1866
+ <Phone>
1867
+ <PhoneType>MOBILE</PhoneType>
1868
+ </Phone>
1869
+ <Phone>
1870
+ <PhoneType>DEFAULT</PhoneType>
1871
+ </Phone>
1872
+ <Phone>
1873
+ <PhoneType>DDI</PhoneType>
1874
+ </Phone>
1875
+ <Phone>
1876
+ <PhoneType>FAX</PhoneType>
1877
+ </Phone>
1878
+ </Phones>
1879
+ <UpdatedDateUTC>2011-06-21T09:22:54.097</UpdatedDateUTC>
1880
+ <IsSupplier>false</IsSupplier>
1881
+ <IsCustomer>true</IsCustomer>
1882
+ </Contact>
1883
+ <Date>2011-06-21T00:00:00</Date>
1884
+ <Status>DRAFT</Status>
1885
+ <LineAmountTypes>Exclusive</LineAmountTypes>
1886
+ <SubTotal>0.00</SubTotal>
1887
+ <TotalTax>0.00</TotalTax>
1888
+ <Total>0.00</Total>
1889
+ <UpdatedDateUTC>2011-06-21T09:22:54.143</UpdatedDateUTC>
1890
+ <CurrencyCode>NZD</CurrencyCode>
1891
+ <Type>ACCREC</Type>
1892
+ <InvoiceID>762aa45d-4632-45b5-8087-b4f47690665e</InvoiceID>
1893
+ <InvoiceNumber>INV-0039</InvoiceNumber>
1894
+ <AmountDue>0.00</AmountDue>
1895
+ <AmountPaid>0.00</AmountPaid>
1896
+ <SentToContact>false</SentToContact>
1897
+ </Invoice>
1852
1898
  </Invoices>
1853
1899
  </Response>
@@ -0,0 +1,54 @@
1
+ <Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <Id>8837eff8-5b9d-4788-a735-d61dd5d56a56</Id>
3
+ <Status>OK</Status>
4
+ <ProviderName>Xero API Previewer</ProviderName>
5
+ <DateTimeUTC>2011-06-21T09:22:54.1911951Z</DateTimeUTC>
6
+ <Invoices>
7
+ <Invoice>
8
+ <Contact>
9
+ <ContactID>9601cac0-db41-4255-8cc6-f38b555ce53f</ContactID>
10
+ <ContactStatus>ACTIVE</ContactStatus>
11
+ <Name>ABC</Name>
12
+ <Addresses>
13
+ <Address>
14
+ <AddressType>STREET</AddressType>
15
+ </Address>
16
+ <Address>
17
+ <AddressType>POBOX</AddressType>
18
+ </Address>
19
+ </Addresses>
20
+ <Phones>
21
+ <Phone>
22
+ <PhoneType>MOBILE</PhoneType>
23
+ </Phone>
24
+ <Phone>
25
+ <PhoneType>DEFAULT</PhoneType>
26
+ </Phone>
27
+ <Phone>
28
+ <PhoneType>DDI</PhoneType>
29
+ </Phone>
30
+ <Phone>
31
+ <PhoneType>FAX</PhoneType>
32
+ </Phone>
33
+ </Phones>
34
+ <UpdatedDateUTC>2011-06-21T09:22:54.097</UpdatedDateUTC>
35
+ <IsSupplier>false</IsSupplier>
36
+ <IsCustomer>true</IsCustomer>
37
+ </Contact>
38
+ <Date>2011-06-21T00:00:00</Date>
39
+ <Status>DRAFT</Status>
40
+ <LineAmountTypes>Exclusive</LineAmountTypes>
41
+ <SubTotal>0.00</SubTotal>
42
+ <TotalTax>0.00</TotalTax>
43
+ <Total>0.00</Total>
44
+ <UpdatedDateUTC>2011-06-21T09:22:54.143</UpdatedDateUTC>
45
+ <CurrencyCode>NZD</CurrencyCode>
46
+ <Type>ACCREC</Type>
47
+ <InvoiceID>762aa45d-4632-45b5-8087-b4f47690665e</InvoiceID>
48
+ <InvoiceNumber>INV-0039</InvoiceNumber>
49
+ <AmountDue>0.00</AmountDue>
50
+ <AmountPaid>0.00</AmountPaid>
51
+ <SentToContact>false</SentToContact>
52
+ </Invoice>
53
+ </Invoices>
54
+ </Response>
@@ -48,4 +48,39 @@ class InvoiceTest < Test::Unit::TestCase
48
48
 
49
49
  end
50
50
 
51
+ context "invoice validations" do
52
+
53
+ should "build an invalid invoice if there are no attributes" do
54
+ assert_equal(false, @client.Invoice.build.valid?)
55
+ end
56
+
57
+ should "build a valid DRAFT invoice with minimal attributes" do
58
+ invoice = @client.Invoice.build :type => "ACCREC", :contact => { :name => "ABC Limited" }
59
+ assert_equal(true, invoice.valid?)
60
+ end
61
+
62
+ should "build a invalid AUTHORISED invoice with minimal attributes" do
63
+ invoice = @client.Invoice.build :type => "ACCREC", :contact => { :name => "ABC Limited" }, :status => "AUTHORISED"
64
+ assert_equal(false, invoice.valid?)
65
+ end
66
+
67
+ should "build a valid AUTHORISED invoice with complete attributes" do
68
+ invoice = @client.Invoice.build({
69
+ :type => "ACCREC",
70
+ :contact => { :name => "ABC Limited" },
71
+ :status => "AUTHORISED",
72
+ :date => Date.today,
73
+ :due_date => Date.today,
74
+ :line_items => [{
75
+ :description => "Consulting services as agreed",
76
+ :quantity => 5,
77
+ :unit_amount => 120,
78
+ :account_code => 200
79
+ }]
80
+ })
81
+ assert_equal(true, invoice.valid?)
82
+ end
83
+
84
+ end
85
+
51
86
  end
@@ -5,8 +5,8 @@ class RecordAssociationTest < Test::Unit::TestCase
5
5
 
6
6
  def setup
7
7
  @client = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET)
8
- @client.stubs(:http_get).with {|client, url, params| url =~ /Invoices\/[^\/]+$/ }.returns(get_record_xml(:invoice))
9
- @client.stubs(:http_get).with {|client, url, params| url =~ /Invoices$/ }.returns(get_record_xml(:invoices))
8
+ mock_api('Invoices')
9
+ @client.stubs(:http_put).returns(get_record_xml(:invoice, "762aa45d-4632-45b5-8087-b4f47690665e"))
10
10
  end
11
11
 
12
12
  context "belongs_to association" do
@@ -64,6 +64,30 @@ class RecordAssociationTest < Test::Unit::TestCase
64
64
  end
65
65
  end
66
66
 
67
+ should "retain unsaved items after create" do
68
+ invoice = @client.Invoice.build :type => "ACCREC", :contact => { :name => "A" }
69
+ invoice.save
70
+ invoice.add_line_item :description => "1"
71
+ assert_equal(1, invoice.line_items.size, "There should be one line item.")
72
+ end
73
+
74
+ should "retain unsaved items after find" do
75
+ invoice = @client.Invoice.find "762aa45d-4632-45b5-8087-b4f47690665e"
76
+ invoice.add_line_item :description => "1"
77
+ assert_equal(1, invoice.line_items.size, "There should be one line item.")
78
+ end
79
+
80
+ should "retain unsaved items after summary find" do
81
+ invoice = @client.Invoice.all.last
82
+ invoice.add_line_item :description => "1"
83
+ assert_equal(1, invoice.line_items.size, "There should be one line item.")
84
+ end
85
+
86
+ should "retain unsaved items when set explicitly" do
87
+ invoice = @client.Invoice.all.last
88
+ invoice.line_items = [{ :description => "1" }]
89
+ assert_equal(1, invoice.line_items.size, "There should be one line item.")
90
+ end
67
91
  end
68
92
 
69
93
  end
data/xeroizer.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{xeroizer}
8
- s.version = "0.3.4"
8
+ s.version = "0.3.5"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Wayne Robinson"]
12
- s.date = %q{2011-06-15}
12
+ s.date = %q{2011-06-27}
13
13
  s.description = %q{Ruby library for the Xero accounting system API.}
14
14
  s.email = %q{wayne.robinson@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -257,6 +257,7 @@ Gem::Specification.new do |s|
257
257
  "test/stub_responses/records/invoice-673dd7cc-beb7-4697-83d4-0c47cb400cc2.xml",
258
258
  "test/stub_responses/records/invoice-69fc971e-9b37-41c5-9c87-174330f22343.xml",
259
259
  "test/stub_responses/records/invoice-70e6db69-e5a4-42c7-a397-aa3212c2945f.xml",
260
+ "test/stub_responses/records/invoice-762aa45d-4632-45b5-8087-b4f47690665e.xml",
260
261
  "test/stub_responses/records/invoice-766d1289-b440-4675-a656-1a0612ecac77.xml",
261
262
  "test/stub_responses/records/invoice-76bcb361-f93b-4513-b312-5a4af306d276.xml",
262
263
  "test/stub_responses/records/invoice-76e3f056-479f-417c-a72b-f3d767899b87.xml",
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xeroizer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 4
10
- version: 0.3.4
9
+ - 5
10
+ version: 0.3.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Wayne Robinson
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-15 00:00:00 +10:00
18
+ date: 2011-06-27 00:00:00 +10:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -416,6 +416,7 @@ files:
416
416
  - test/stub_responses/records/invoice-673dd7cc-beb7-4697-83d4-0c47cb400cc2.xml
417
417
  - test/stub_responses/records/invoice-69fc971e-9b37-41c5-9c87-174330f22343.xml
418
418
  - test/stub_responses/records/invoice-70e6db69-e5a4-42c7-a397-aa3212c2945f.xml
419
+ - test/stub_responses/records/invoice-762aa45d-4632-45b5-8087-b4f47690665e.xml
419
420
  - test/stub_responses/records/invoice-766d1289-b440-4675-a656-1a0612ecac77.xml
420
421
  - test/stub_responses/records/invoice-76bcb361-f93b-4513-b312-5a4af306d276.xml
421
422
  - test/stub_responses/records/invoice-76e3f056-479f-417c-a72b-f3d767899b87.xml