xeroizer 2.15.5 → 2.15.6

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