xeroizer 2.15.5 → 2.15.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/README.md +14 -3
  2. data/lib/xeroizer.rb +5 -0
  3. data/lib/xeroizer/generic_application.rb +15 -9
  4. data/lib/xeroizer/http.rb +44 -34
  5. data/lib/xeroizer/models/account.rb +15 -11
  6. data/lib/xeroizer/models/allocation.rb +13 -0
  7. data/lib/xeroizer/models/attachment.rb +93 -0
  8. data/lib/xeroizer/models/bank_transaction.rb +3 -2
  9. data/lib/xeroizer/models/contact.rb +20 -12
  10. data/lib/xeroizer/models/contact_person.rb +20 -0
  11. data/lib/xeroizer/models/credit_note.rb +2 -0
  12. data/lib/xeroizer/models/expense_claim.rb +29 -0
  13. data/lib/xeroizer/models/invoice.rb +42 -29
  14. data/lib/xeroizer/models/line_item.rb +1 -0
  15. data/lib/xeroizer/models/organisation.rb +6 -1
  16. data/lib/xeroizer/models/payment.rb +16 -11
  17. data/lib/xeroizer/models/receipt.rb +39 -0
  18. data/lib/xeroizer/models/tax_component.rb +13 -0
  19. data/lib/xeroizer/models/tax_rate.rb +14 -3
  20. data/lib/xeroizer/models/user.rb +26 -0
  21. data/lib/xeroizer/oauth.rb +3 -3
  22. data/lib/xeroizer/record/base.rb +40 -31
  23. data/lib/xeroizer/record/base_model.rb +31 -25
  24. data/lib/xeroizer/record/base_model_http_proxy.rb +4 -1
  25. data/lib/xeroizer/record/record_association_helper.rb +35 -35
  26. data/lib/xeroizer/record/xml_helper.rb +1 -1
  27. data/lib/xeroizer/report/factory.rb +2 -1
  28. data/lib/xeroizer/version.rb +3 -0
  29. data/test/stub_responses/organisation.xml +30 -0
  30. data/test/stub_responses/tax_rates.xml +81 -1
  31. data/test/stub_responses/users.xml +17 -0
  32. data/test/unit/generic_application_test.rb +21 -0
  33. data/test/unit/http_test.rb +18 -0
  34. data/test/unit/models/bank_transaction_test.rb +1 -4
  35. data/test/unit/models/line_item_sum_test.rb +3 -2
  36. data/test/unit/models/tax_rate_test.rb +81 -0
  37. data/test/unit/oauth_test.rb +4 -2
  38. data/test/unit/record/base_test.rb +1 -1
  39. data/test/unit/record/model_definition_test.rb +9 -3
  40. data/test/unit/record/record_association_test.rb +1 -1
  41. data/test/unit/record_definition_test.rb +1 -1
  42. metadata +540 -205
  43. data/.bundle/config +0 -2
  44. data/.gitattributes +0 -22
  45. data/Gemfile +0 -20
  46. data/Gemfile.lock +0 -59
  47. data/Rakefile +0 -55
  48. data/VERSION +0 -1
  49. data/xeroizer.gemspec +0 -409
@@ -16,7 +16,8 @@ module Xeroizer
16
16
  # Parse parameters for GET requests.
17
17
  def parse_params(options)
18
18
  params = {}
19
- params[:ModifiedAfter] = options[:modified_since] if options[:modified_since]
19
+ params[:ModifiedAfter] = options[:modified_since] if options[:modified_since]
20
+ params[:includeArchived] = options[:include_archived] if options[:include_archived]
20
21
  params[:order] = options[:order] if options[:order]
21
22
 
22
23
  if options[:where]
@@ -26,6 +27,7 @@ module Xeroizer
26
27
  end
27
28
  end
28
29
  params[:offset] = options[:offset] if options[:offset]
30
+ params[:page] = options[:page] if options[:page]
29
31
  params
30
32
  end
31
33
 
@@ -106,6 +108,7 @@ module Xeroizer
106
108
  when :decimal then [field[:api_name], expression, value.to_s]
107
109
  when :date then [field[:api_name], expression, "DateTime.Parse(\"#{value.strftime("%Y-%m-%d")}\")"]
108
110
  when :datetime then [field[:api_name], expression, "DateTime.Parse(\"#{value.utc.strftime("%Y-%m-%dT%H:%M:%S")}\")"]
111
+ when :datetime_utc then [field[:api_name], expression, "DateTime.Parse(\"#{value.utc.strftime("%Y-%m-%dT%H:%M:%S")}\")"]
109
112
  when :belongs_to then
110
113
  when :has_many then
111
114
  end
@@ -1,41 +1,41 @@
1
1
  module Xeroizer
2
2
  module Record
3
3
  module RecordAssociationHelper
4
-
4
+
5
5
  def self.included(base)
6
- base.extend(ClassMethods)
6
+ base.extend(ClassMethods)
7
7
  end
8
-
8
+
9
9
  module ClassMethods
10
-
10
+
11
11
  def belongs_to(field_name, options = {})
12
12
  internal_field_name = options[:internal_name] || field_name
13
13
  internal_singular_field_name = internal_field_name.to_s.singularize
14
-
14
+
15
15
  define_association_attribute(field_name, internal_singular_field_name, :belongs_to, options)
16
-
16
+
17
17
  # Create a #build_record_name method to build the record.
18
18
  define_method "build_#{internal_singular_field_name}" do | *args |
19
19
  attributes = args.size == 1 ? args.first : {}
20
-
20
+
21
21
  # The name of the record model.
22
22
  model_name = options[:model_name] ? options[:model_name].to_sym : field_name.to_s.singularize.camelize.to_sym
23
-
23
+
24
24
  # The record's parent instance for this current application.
25
25
  model_parent = new_model_class(model_name)
26
-
26
+
27
27
  # Create a new record, binding it to it's parent instance.
28
28
  record = Xeroizer::Record.const_get(model_name).build(attributes, model_parent)
29
29
  self.attributes[field_name] = record
30
30
  end
31
31
  end
32
-
32
+
33
33
  def has_many(field_name, options = {})
34
34
  internal_field_name = options[:internal_name] || field_name
35
35
  internal_singular_field_name = internal_field_name.to_s.singularize
36
-
36
+
37
37
  define_association_attribute(field_name, internal_field_name, :has_many, options)
38
-
38
+
39
39
  # Create an #add_record_name method to build the record and add to the attributes.
40
40
  define_method "add_#{internal_singular_field_name}" do | *args |
41
41
  # The name of the record model.
@@ -43,7 +43,7 @@ module Xeroizer
43
43
 
44
44
  # The record's parent instance for this current application.
45
45
  model_parent = new_model_class(model_name)
46
-
46
+
47
47
  # The class of this record.
48
48
  record_class = Xeroizer::Record.const_get(model_name)
49
49
 
@@ -55,15 +55,15 @@ module Xeroizer
55
55
  records = []
56
56
  if args.size == 1 && args.first.is_a?(Array)
57
57
  records = args.first
58
- elsif args.size > 0
58
+ elsif args.size > 0
59
59
  records = args
60
60
  else
61
61
  raise StandardError.new("Invalid arguments for #{self.class.name}#add_#{internal_singular_field_name}(#{args.inspect}).")
62
62
  end
63
-
63
+
64
64
  # Ensure that complete record is downloaded before adding new records
65
- self.send(field_name)
66
-
65
+ self.send(internal_field_name)
66
+
67
67
  # Add each record.
68
68
  last_record = nil
69
69
  records.each do | record |
@@ -73,34 +73,34 @@ module Xeroizer
73
73
  self.attributes[field_name] << record
74
74
  last_record = record
75
75
  end
76
-
76
+
77
77
  last_record # last record
78
78
  end
79
-
79
+
80
80
  end
81
-
81
+
82
82
  def define_association_attribute(field_name, internal_field_name, association_type, options)
83
83
  define_simple_attribute(field_name, association_type, options.merge!(:skip_writer => true), ((association_type == :has_many) ? [] : nil))
84
-
84
+
85
85
  internal_field_name = options[:internal_name] || field_name
86
86
  internal_singular_field_name = internal_field_name.to_s.singularize
87
87
  model_name = options[:model_name] ? options[:model_name].to_sym : field_name.to_s.singularize.camelize.to_sym
88
-
89
- define_method "#{internal_field_name}=".to_sym do | value |
88
+
89
+ define_method "#{internal_field_name}=".to_sym do | value |
90
90
  record_class = Xeroizer::Record.const_get(model_name)
91
91
  case value
92
- when Hash
92
+ when Hash
93
93
  self.attributes[field_name] = ((association_type == :has_many) ? [] : nil)
94
94
  case association_type
95
- when :has_many
95
+ when :has_many
96
96
  self.attributes[field_name] = []
97
97
  self.send("add_#{internal_singular_field_name}".to_sym, value)
98
-
99
- when :belongs_to
98
+
99
+ when :belongs_to
100
100
  self.attributes[field_name] = Xeroizer::Record.const_get(model_name).build(value, new_model_class(model_name))
101
-
101
+
102
102
  end
103
-
103
+
104
104
  when Array
105
105
  self.attributes[field_name] = ((association_type == :has_many) ? [] : nil)
106
106
  value.each do | single_value |
@@ -110,18 +110,18 @@ module Xeroizer
110
110
  else raise AssociationTypeMismatch.new(record_class, single_value.class)
111
111
  end
112
112
  end
113
-
113
+
114
114
  when record_class
115
115
  self.attributes[field_name] = ((association_type == :has_many) ? [value] : value)
116
-
116
+
117
117
  when NilClass
118
118
  self.attributes[field_name] = []
119
-
119
+
120
120
  else
121
121
  raise AssociationTypeMismatch.new(record_class, value.class)
122
122
  end
123
123
  end
124
-
124
+
125
125
  # Override reader for this association if this association belongs
126
126
  # to a summary-typed record. This will automatically attempt to download
127
127
  # the complete version of the record before accessing the association.
@@ -132,9 +132,9 @@ module Xeroizer
132
132
  end
133
133
  end
134
134
  end
135
-
135
+
136
136
  end
137
-
137
+
138
138
  end
139
139
  end
140
140
  end
@@ -61,7 +61,7 @@ module Xeroizer
61
61
  # Turn a record into its XML representation.
62
62
  def to_xml(b = Builder::XmlMarkup.new(:indent => 2))
63
63
  optional_root_tag(parent.class.optional_xml_root_name, b) do |b|
64
- b.tag!(parent.class.xml_node_name || parent.model_name) {
64
+ b.tag!(model.class.xml_node_name || model.model_name) {
65
65
  attributes.each do | key, value |
66
66
  field = self.class.fields[key]
67
67
  value = self.send(key) if field[:calculated]
@@ -10,6 +10,7 @@ module Xeroizer
10
10
 
11
11
  attr_reader :application
12
12
  attr_reader :report_type
13
+ attr_reader :response_xml
13
14
 
14
15
  public
15
16
 
@@ -21,7 +22,7 @@ module Xeroizer
21
22
  # Retreive a report with the `options` as a hash containing
22
23
  # valid query-string parameters to pass to the API.
23
24
  def get(options = {})
24
- response_xml = options[:cache_file] ? File.read(options[:cache_file]) : http_get(options)
25
+ @response_xml = options[:cache_file] ? File.read(options[:cache_file]) : http_get(options)
25
26
  response = Response.parse(response_xml, options) do | response, elements |
26
27
  parse_reports(response, elements)
27
28
  end
@@ -0,0 +1,3 @@
1
+ module Xeroizer
2
+ VERSION = "2.15.6".freeze
3
+ end
@@ -20,6 +20,36 @@
20
20
  <FinancialYearEndMonth>6</FinancialYearEndMonth>
21
21
  <PeriodLockDate>2008-06-30T00:00:00</PeriodLockDate>
22
22
  <CreatedDateUTC>2011-05-19T05:26:03.95</CreatedDateUTC>
23
+ <Addresses>
24
+ <Address>
25
+ <AddressType>STREET</AddressType>
26
+ </Address>
27
+ <Address>
28
+ <AddressType>POBOX</AddressType>
29
+ <AddressLine1>23 Main Street</AddressLine1>
30
+ <AddressLine2>Central City</AddressLine2>
31
+ <City>Oaktown</City>
32
+ <Region>NY</Region>
33
+ <PostalCode>12123</PostalCode>
34
+ <Country>USA</Country>
35
+ </Address>
36
+ </Addresses>
37
+ <Phones>
38
+ <Phone>
39
+ <PhoneType>DDI</PhoneType>
40
+ </Phone>
41
+ <Phone>
42
+ <PhoneType>MOBILE</PhoneType>
43
+ </Phone>
44
+ <Phone>
45
+ <PhoneType>DEFAULT</PhoneType>
46
+ <PhoneNumber>1234 5678</PhoneNumber>
47
+ <PhoneAreaCode>800</PhoneAreaCode>
48
+ </Phone>
49
+ <Phone>
50
+ <PhoneType>FAX</PhoneType>
51
+ </Phone>
52
+ </Phones>
23
53
  </Organisation>
24
54
  </Organisations>
25
55
  </Response>
@@ -14,6 +14,14 @@
14
14
  <CanApplyToRevenue>true</CanApplyToRevenue>
15
15
  <DisplayTaxRate>0.0000</DisplayTaxRate>
16
16
  <EffectiveRate>0.0000</EffectiveRate>
17
+ <Status>ACTIVE</Status>
18
+ <TaxComponents>
19
+ <TaxComponent>
20
+ <Name>GST</Name>
21
+ <Rate>0.0000</Rate>
22
+ <IsCompound>false</IsCompound>
23
+ </TaxComponent>
24
+ </TaxComponents>
17
25
  </TaxRate>
18
26
  <TaxRate>
19
27
  <Name>GST Free Exports</Name>
@@ -25,6 +33,14 @@
25
33
  <CanApplyToRevenue>true</CanApplyToRevenue>
26
34
  <DisplayTaxRate>0.0000</DisplayTaxRate>
27
35
  <EffectiveRate>0.0000</EffectiveRate>
36
+ <Status>ACTIVE</Status>
37
+ <TaxComponents>
38
+ <TaxComponent>
39
+ <Name>GST</Name>
40
+ <Rate>0.0000</Rate>
41
+ <IsCompound>false</IsCompound>
42
+ </TaxComponent>
43
+ </TaxComponents>
28
44
  </TaxRate>
29
45
  <TaxRate>
30
46
  <Name>GST Free Income</Name>
@@ -36,6 +52,14 @@
36
52
  <CanApplyToRevenue>true</CanApplyToRevenue>
37
53
  <DisplayTaxRate>0.0000</DisplayTaxRate>
38
54
  <EffectiveRate>0.0000</EffectiveRate>
55
+ <Status>ACTIVE</Status>
56
+ <TaxComponents>
57
+ <TaxComponent>
58
+ <Name>GST</Name>
59
+ <Rate>0.0000</Rate>
60
+ <IsCompound>false</IsCompound>
61
+ </TaxComponent>
62
+ </TaxComponents>
39
63
  </TaxRate>
40
64
  <TaxRate>
41
65
  <Name>GST on Capital</Name>
@@ -47,6 +71,14 @@
47
71
  <CanApplyToRevenue>false</CanApplyToRevenue>
48
72
  <DisplayTaxRate>10.0000</DisplayTaxRate>
49
73
  <EffectiveRate>10.0000</EffectiveRate>
74
+ <Status>ACTIVE</Status>
75
+ <TaxComponents>
76
+ <TaxComponent>
77
+ <Name>GST</Name>
78
+ <Rate>10.0000</Rate>
79
+ <IsCompound>false</IsCompound>
80
+ </TaxComponent>
81
+ </TaxComponents>
50
82
  </TaxRate>
51
83
  <TaxRate>
52
84
  <Name>GST on Capital Imports</Name>
@@ -58,6 +90,14 @@
58
90
  <CanApplyToRevenue>false</CanApplyToRevenue>
59
91
  <DisplayTaxRate>0.0000</DisplayTaxRate>
60
92
  <EffectiveRate>0.0000</EffectiveRate>
93
+ <Status>ACTIVE</Status>
94
+ <TaxComponents>
95
+ <TaxComponent>
96
+ <Name>GST</Name>
97
+ <Rate>0.0000</Rate>
98
+ <IsCompound>false</IsCompound>
99
+ </TaxComponent>
100
+ </TaxComponents>
61
101
  </TaxRate>
62
102
  <TaxRate>
63
103
  <Name>GST on Expenses</Name>
@@ -69,6 +109,14 @@
69
109
  <CanApplyToRevenue>false</CanApplyToRevenue>
70
110
  <DisplayTaxRate>10.0000</DisplayTaxRate>
71
111
  <EffectiveRate>10.0000</EffectiveRate>
112
+ <Status>ACTIVE</Status>
113
+ <TaxComponents>
114
+ <TaxComponent>
115
+ <Name>GST</Name>
116
+ <Rate>10.0000</Rate>
117
+ <IsCompound>false</IsCompound>
118
+ </TaxComponent>
119
+ </TaxComponents>
72
120
  </TaxRate>
73
121
  <TaxRate>
74
122
  <Name>GST on Imports</Name>
@@ -80,6 +128,14 @@
80
128
  <CanApplyToRevenue>false</CanApplyToRevenue>
81
129
  <DisplayTaxRate>0.0000</DisplayTaxRate>
82
130
  <EffectiveRate>0.0000</EffectiveRate>
131
+ <Status>ACTIVE</Status>
132
+ <TaxComponents>
133
+ <TaxComponent>
134
+ <Name>GST</Name>
135
+ <Rate>0.0000</Rate>
136
+ <IsCompound>false</IsCompound>
137
+ </TaxComponent>
138
+ </TaxComponents>
83
139
  </TaxRate>
84
140
  <TaxRate>
85
141
  <Name>GST on Income</Name>
@@ -91,6 +147,14 @@
91
147
  <CanApplyToRevenue>true</CanApplyToRevenue>
92
148
  <DisplayTaxRate>10.0000</DisplayTaxRate>
93
149
  <EffectiveRate>10.0000</EffectiveRate>
150
+ <Status>ACTIVE</Status>
151
+ <TaxComponents>
152
+ <TaxComponent>
153
+ <Name>GST</Name>
154
+ <Rate>10.0000</Rate>
155
+ <IsCompound>false</IsCompound>
156
+ </TaxComponent>
157
+ </TaxComponents>
94
158
  </TaxRate>
95
159
  <TaxRate>
96
160
  <Name>Input Taxed</Name>
@@ -102,6 +166,14 @@
102
166
  <CanApplyToRevenue>true</CanApplyToRevenue>
103
167
  <DisplayTaxRate>0.0000</DisplayTaxRate>
104
168
  <EffectiveRate>0.0000</EffectiveRate>
169
+ <Status>ACTIVE</Status>
170
+ <TaxComponents>
171
+ <TaxComponent>
172
+ <Name>GST</Name>
173
+ <Rate>0.0000</Rate>
174
+ <IsCompound>false</IsCompound>
175
+ </TaxComponent>
176
+ </TaxComponents>
105
177
  </TaxRate>
106
178
  <TaxRate>
107
179
  <Name>No GST</Name>
@@ -113,6 +185,14 @@
113
185
  <CanApplyToRevenue>true</CanApplyToRevenue>
114
186
  <DisplayTaxRate>0.0000</DisplayTaxRate>
115
187
  <EffectiveRate>0.0000</EffectiveRate>
188
+ <Status>ACTIVE</Status>
189
+ <TaxComponents>
190
+ <TaxComponent>
191
+ <Name>GST</Name>
192
+ <Rate>0.0000</Rate>
193
+ <IsCompound>false</IsCompound>
194
+ </TaxComponent>
195
+ </TaxComponents>
116
196
  </TaxRate>
117
197
  </TaxRates>
118
- </Response>
198
+ </Response>
@@ -0,0 +1,17 @@
1
+ <Response xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2
+ <Id>82fc227d-ad9f-42ed-98aa-583abc49bb54</Id>
3
+ <Status>OK</Status>
4
+ <ProviderName>Test Provider Name</ProviderName>
5
+ <DateTimeUTC>2013-12-05T05:36:43.1758494Z</DateTimeUTC>
6
+ <Users>
7
+ <User>
8
+ <UserID>1a535a0d-68fa-403a-b101-36c019c1995a</UserID>
9
+ <EmailAddress>user.name@example.com</EmailAddress>
10
+ <FirstName>User</FirstName>
11
+ <LastName>Name</LastName>
12
+ <UpdatedDateUTC>2013-07-08T07:27:11.62</UpdatedDateUTC>
13
+ <IsSubscriber>true</IsSubscriber>
14
+ <OrganisationRole>STANDARD</OrganisationRole>
15
+ </User>
16
+ </Users>
17
+ </Response>
@@ -0,0 +1,21 @@
1
+ require 'test_helper'
2
+
3
+ class GenericApplicationTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @headers = {"User-Agent" => "Xeroizer/2.15.5"}
8
+ @client = Xeroizer::GenericApplication.new(CONSUMER_KEY, CONSUMER_SECRET, :default_headers => @headers)
9
+ end
10
+
11
+ context "initialization" do
12
+
13
+ should "pass default headers" do
14
+ assert_equal(@headers, @client.default_headers)
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
21
+
@@ -0,0 +1,18 @@
1
+ require 'test_helper'
2
+
3
+ class HttpTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ def setup
7
+ @headers = {"User-Agent" => "Xeroizer/2.15.5"}
8
+ @application = Xeroizer::PublicApplication.new(CONSUMER_KEY, CONSUMER_SECRET, :default_headers => @headers)
9
+ end
10
+
11
+ context "default_headers" do
12
+ should "recognize default_headers" do
13
+ Xeroizer::OAuth.any_instance.expects(:get).with("/test", has_entry(@headers)).returns(stub(:plain_body => "", :code => "200"))
14
+ @application.http_get(@application.client, "http://example.com/test")
15
+ end
16
+ end
17
+ end
18
+