xeroizer 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
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