xeroizer 2.17.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +246 -213
  3. data/lib/xeroizer/connection.rb +49 -0
  4. data/lib/xeroizer/exceptions.rb +4 -0
  5. data/lib/xeroizer/generic_application.rb +13 -5
  6. data/lib/xeroizer/http.rb +7 -80
  7. data/lib/xeroizer/http_response.rb +154 -0
  8. data/lib/xeroizer/models/bank_account.rb +1 -0
  9. data/lib/xeroizer/models/bank_transaction.rb +1 -0
  10. data/lib/xeroizer/models/batch_payment.rb +27 -0
  11. data/lib/xeroizer/models/branding_theme.rb +49 -9
  12. data/lib/xeroizer/models/contact.rb +12 -6
  13. data/lib/xeroizer/models/contact_group.rb +45 -0
  14. data/lib/xeroizer/models/credit_note.rb +24 -22
  15. data/lib/xeroizer/models/currency.rb +14 -2
  16. data/lib/xeroizer/models/from_bank_account.rb +1 -0
  17. data/lib/xeroizer/models/history_record.rb +72 -0
  18. data/lib/xeroizer/models/invoice.rb +17 -3
  19. data/lib/xeroizer/models/item.rb +2 -1
  20. data/lib/xeroizer/models/item_purchase_details.rb +1 -1
  21. data/lib/xeroizer/models/line_item.rb +17 -5
  22. data/lib/xeroizer/models/manual_journal.rb +2 -1
  23. data/lib/xeroizer/models/online_invoice.rb +37 -0
  24. data/lib/xeroizer/models/option.rb +1 -1
  25. data/lib/xeroizer/models/organisation.rb +2 -0
  26. data/lib/xeroizer/models/payment_service.rb +22 -0
  27. data/lib/xeroizer/models/payroll/address.rb +53 -0
  28. data/lib/xeroizer/models/payroll/bank_account.rb +18 -6
  29. data/lib/xeroizer/models/payroll/benefit_line.rb +26 -0
  30. data/lib/xeroizer/models/payroll/benefit_type.rb +45 -0
  31. data/lib/xeroizer/models/payroll/deduction_line.rb +32 -0
  32. data/lib/xeroizer/models/payroll/deduction_type.rb +49 -0
  33. data/lib/xeroizer/models/payroll/earnings_line.rb +39 -0
  34. data/lib/xeroizer/models/payroll/earnings_type.rb +53 -0
  35. data/lib/xeroizer/models/payroll/employee.rb +30 -8
  36. data/lib/xeroizer/models/payroll/leave_application.rb +27 -0
  37. data/lib/xeroizer/models/payroll/leave_line.rb +30 -0
  38. data/lib/xeroizer/models/payroll/leave_period.rb +15 -0
  39. data/lib/xeroizer/models/payroll/pay_items.rb +22 -0
  40. data/lib/xeroizer/models/payroll/pay_run.rb +33 -0
  41. data/lib/xeroizer/models/payroll/pay_schedule.rb +40 -0
  42. data/lib/xeroizer/models/payroll/pay_template.rb +24 -0
  43. data/lib/xeroizer/models/payroll/payment_method.rb +24 -0
  44. data/lib/xeroizer/models/payroll/paystub.rb +44 -0
  45. data/lib/xeroizer/models/payroll/reimbursement_line.rb +21 -0
  46. data/lib/xeroizer/models/payroll/reimbursement_type.rb +22 -0
  47. data/lib/xeroizer/models/payroll/salary_and_wage.rb +29 -0
  48. data/lib/xeroizer/models/payroll/super_line.rb +40 -0
  49. data/lib/xeroizer/models/payroll/tax_declaration.rb +50 -0
  50. data/lib/xeroizer/models/payroll/time_off_line.rb +20 -0
  51. data/lib/xeroizer/models/payroll/time_off_type.rb +32 -0
  52. data/lib/xeroizer/models/payroll/work_location.rb +25 -0
  53. data/lib/xeroizer/models/prepayment.rb +1 -0
  54. data/lib/xeroizer/models/purchase_order.rb +6 -6
  55. data/lib/xeroizer/models/quote.rb +76 -0
  56. data/lib/xeroizer/models/schedule.rb +1 -0
  57. data/lib/xeroizer/models/tax_component.rb +1 -0
  58. data/lib/xeroizer/models/to_bank_account.rb +1 -0
  59. data/lib/xeroizer/oauth.rb +12 -1
  60. data/lib/xeroizer/oauth2.rb +82 -0
  61. data/lib/xeroizer/oauth2_application.rb +49 -0
  62. data/lib/xeroizer/payroll_application.rb +8 -3
  63. data/lib/xeroizer/record/base.rb +11 -2
  64. data/lib/xeroizer/record/base_model.rb +1 -1
  65. data/lib/xeroizer/record/base_model_http_proxy.rb +37 -17
  66. data/lib/xeroizer/record/model_definition_helper.rb +1 -1
  67. data/lib/xeroizer/record/payroll_base.rb +4 -0
  68. data/lib/xeroizer/record/record_association_helper.rb +4 -4
  69. data/lib/xeroizer/record/validators/associated_validator.rb +1 -0
  70. data/lib/xeroizer/record/xml_helper.rb +18 -18
  71. data/lib/xeroizer/report/aged_receivables_by_contact.rb +1 -1
  72. data/lib/xeroizer/report/cell_xml_helper.rb +13 -13
  73. data/lib/xeroizer/response.rb +22 -17
  74. data/lib/xeroizer/version.rb +1 -1
  75. data/lib/xeroizer.rb +34 -4
  76. data/test/acceptance/about_creating_bank_transactions_test.rb +89 -81
  77. data/test/acceptance/about_creating_prepayment_test.rb +25 -30
  78. data/test/acceptance/about_fetching_bank_transactions_test.rb +12 -12
  79. data/test/acceptance/about_online_invoice_test.rb +25 -0
  80. data/test/acceptance/acceptance_test.rb +28 -26
  81. data/test/acceptance/bank_transfer_test.rb +12 -17
  82. data/test/acceptance/bulk_operations_test.rb +18 -16
  83. data/test/acceptance/connections_test.rb +11 -0
  84. data/test/stub_responses/bad_request.json +6 -0
  85. data/test/stub_responses/connections.json +16 -0
  86. data/test/stub_responses/expired_oauth2_token.json +6 -0
  87. data/test/stub_responses/generic_response_error.json +6 -0
  88. data/test/stub_responses/invalid_oauth2_request_token.json +6 -0
  89. data/test/stub_responses/invalid_tenant_header.json +6 -0
  90. data/test/stub_responses/object_not_found.json +6 -0
  91. data/test/stub_responses/organisations.xml +10 -0
  92. data/test/stub_responses/payment_service.xml +15 -0
  93. data/test/test_helper.rb +17 -12
  94. data/test/unit/generic_application_test.rb +21 -10
  95. data/test/unit/http_test.rb +282 -10
  96. data/test/unit/models/address_test.rb +2 -2
  97. data/test/unit/models/bank_transaction_model_parsing_test.rb +2 -2
  98. data/test/unit/models/bank_transaction_test.rb +1 -1
  99. data/test/unit/models/bank_transaction_validation_test.rb +1 -1
  100. data/test/unit/models/contact_test.rb +20 -11
  101. data/test/unit/models/credit_note_test.rb +8 -8
  102. data/test/unit/models/employee_test.rb +4 -4
  103. data/test/unit/models/invoice_test.rb +12 -12
  104. data/test/unit/models/journal_line_test.rb +6 -6
  105. data/test/unit/models/journal_test.rb +4 -4
  106. data/test/unit/models/line_item_sum_test.rb +1 -1
  107. data/test/unit/models/line_item_test.rb +29 -37
  108. data/test/unit/models/manual_journal_test.rb +3 -3
  109. data/test/unit/models/organisation_test.rb +16 -2
  110. data/test/unit/models/payment_service_test.rb +29 -0
  111. data/test/unit/models/phone_test.rb +7 -7
  112. data/test/unit/models/prepayment_test.rb +4 -4
  113. data/test/unit/models/repeating_invoice_test.rb +3 -3
  114. data/test/unit/models/tax_rate_test.rb +2 -2
  115. data/test/unit/oauth2_test.rb +171 -0
  116. data/test/unit/oauth_config_test.rb +1 -1
  117. data/test/unit/record/base_model_test.rb +13 -13
  118. data/test/unit/record/base_test.rb +73 -4
  119. data/test/unit/record/block_validator_test.rb +1 -1
  120. data/test/unit/record/connection_test.rb +60 -0
  121. data/test/unit/record/model_definition_test.rb +36 -36
  122. data/test/unit/record/parse_params_test.rb +59 -0
  123. data/test/unit/record/parse_where_hash_test.rb +13 -13
  124. data/test/unit/record/record_association_test.rb +14 -14
  125. data/test/unit/record/validators_test.rb +43 -43
  126. data/test/unit/record_definition_test.rb +7 -7
  127. data/test/unit/report_definition_test.rb +7 -7
  128. data/test/unit/report_test.rb +20 -20
  129. data/test/unit_test_helper.rb +16 -0
  130. metadata +117 -27
  131. data/lib/xeroizer/models/payroll/home_address.rb +0 -24
  132. data/lib/xeroizer/partner_application.rb +0 -51
  133. data/lib/xeroizer/private_application.rb +0 -25
  134. data/lib/xeroizer/public_application.rb +0 -21
  135. data/test/unit/oauth_test.rb +0 -118
  136. data/test/unit/private_application_test.rb +0 -20
@@ -3,14 +3,14 @@ require 'active_support/time'
3
3
  module Xeroizer
4
4
  module Record
5
5
  module XmlHelper
6
-
6
+
7
7
  def self.included(base)
8
8
  base.extend(ClassMethods)
9
9
  base.send :include, InstanceMethods
10
10
  end
11
-
11
+
12
12
  module ClassMethods
13
-
13
+
14
14
  # Build a record instance from the XML node.
15
15
  def build_from_node(node, parent, base_module)
16
16
  record = new(parent)
@@ -22,14 +22,14 @@ module Xeroizer
22
22
  when :string then element.text
23
23
  when :boolean then (element.text == 'true')
24
24
  when :integer then element.text.to_i
25
- when :decimal then BigDecimal.new(element.text)
25
+ when :decimal then BigDecimal(element.text)
26
26
  when :date then Date.parse(element.text)
27
27
  when :datetime then Time.parse(element.text)
28
28
  when :datetime_utc then ActiveSupport::TimeZone['UTC'].parse(element.text).utc
29
- when :belongs_to
29
+ when :belongs_to
30
30
  model_name = field[:model_name] ? field[:model_name].to_sym : element.name.to_sym
31
31
  base_module.const_get(model_name).build_from_node(element, parent, base_module)
32
-
32
+
33
33
  when :has_many
34
34
  if element.element_children.size > 0
35
35
  sub_field_name = field[:model_name] ? field[:model_name].to_sym : element.children.first.name.to_sym
@@ -51,13 +51,13 @@ module Xeroizer
51
51
  parent.mark_clean(record)
52
52
  record
53
53
  end
54
-
54
+
55
55
  end
56
-
56
+
57
57
  module InstanceMethods
58
-
58
+
59
59
  public
60
-
60
+
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 |c|
@@ -70,9 +70,9 @@ module Xeroizer
70
70
  }
71
71
  end
72
72
  end
73
-
73
+
74
74
  protected
75
-
75
+
76
76
  # Add top-level root name if required.
77
77
  # E.g. Payments need specifying in the form:
78
78
  # <Payments>
@@ -87,7 +87,7 @@ module Xeroizer
87
87
  yield(b)
88
88
  end
89
89
  end
90
-
90
+
91
91
  # Format an attribute for use in the XML passed to Xero.
92
92
  def xml_value_from_field(b, field, value)
93
93
  case field[:type]
@@ -95,10 +95,10 @@ module Xeroizer
95
95
  when :string then b.tag!(field[:api_name], value)
96
96
  when :boolean then b.tag!(field[:api_name], value ? 'true' : 'false')
97
97
  when :integer then b.tag!(field[:api_name], value.to_i)
98
- when :decimal
98
+ when :decimal
99
99
  real_value = case value
100
100
  when BigDecimal then value.to_s
101
- when String then BigDecimal.new(value).to_s
101
+ when String then BigDecimal(value).to_s
102
102
  else value
103
103
  end
104
104
  b.tag!(field[:api_name], real_value)
@@ -111,13 +111,13 @@ module Xeroizer
111
111
  else raise ArgumentError.new("Expected Date or Time object for the #{field[:api_name]} field")
112
112
  end
113
113
  b.tag!(field[:api_name], real_value)
114
-
114
+
115
115
  when :datetime then b.tag!(field[:api_name], value.utc.strftime("%Y-%m-%dT%H:%M:%S"))
116
- when :belongs_to
116
+ when :belongs_to
117
117
  value.to_xml(b)
118
118
  nil
119
119
 
120
- when :has_many
120
+ when :has_many
121
121
  if value.size > 0
122
122
  sub_parent = value.first.parent
123
123
  b.tag!(sub_parent.class.xml_root_name || sub_parent.model_name.pluralize) {
@@ -31,7 +31,7 @@ module Xeroizer
31
31
  end
32
32
 
33
33
  def sum(column_name, &block)
34
- sections.first.rows.inject(BigDecimal.new('0')) do | sum, row |
34
+ sections.first.rows.inject(BigDecimal('0')) do | sum, row |
35
35
  sum += row.cell(column_name).value if row.class == Xeroizer::Report::Row && (block.nil? || block.call(row))
36
36
  sum
37
37
  end
@@ -1,19 +1,19 @@
1
1
  module Xeroizer
2
2
  module Report
3
3
  module CellXmlHelper
4
-
4
+
5
5
  def self.included(base)
6
6
  base.extend(ClassMethods)
7
7
  base.send :include, InstanceMethods
8
8
  end
9
-
9
+
10
10
  module ClassMethods
11
-
11
+
12
12
  public
13
-
13
+
14
14
  # Create an instance of Cell from the node.
15
15
  #
16
- # Additionally, parse the attributes and return them as a hash to the
16
+ # Additionally, parse the attributes and return them as a hash to the
17
17
  # cell. If a cell's attributes look like:
18
18
  #
19
19
  # <Attributes>
@@ -22,7 +22,7 @@ module Xeroizer
22
22
  # <Id>account</Id>
23
23
  # </Attribute>
24
24
  # </Attributes>
25
- #
25
+ #
26
26
  # Return a hash like:
27
27
  #
28
28
  # {
@@ -42,17 +42,17 @@ module Xeroizer
42
42
  end
43
43
  cell
44
44
  end
45
-
45
+
46
46
  protected
47
47
 
48
48
  def parse_value(value)
49
49
  case value
50
- when /^[-]?\d+(\.\d+)?$/ then BigDecimal.new(value)
51
- when /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$/ then Time.xmlschema(value)
52
- else value
50
+ when /\A[-]?\d+(\.\d+)?\z/ then BigDecimal(value)
51
+ when /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\z/ then Time.xmlschema(value)
52
+ else value
53
53
  end
54
54
  end
55
-
55
+
56
56
  def parse_attribute(attribute_node)
57
57
  id = nil
58
58
  value = nil
@@ -65,10 +65,10 @@ module Xeroizer
65
65
  [id, value]
66
66
  end
67
67
  end
68
-
68
+
69
69
  module InstanceMethods
70
70
  end
71
-
71
+
72
72
  end
73
73
  end
74
74
  end
@@ -1,9 +1,9 @@
1
1
  # Copyright (c) 2008 Tim Connor <tlconnor@gmail.com>
2
- #
2
+ #
3
3
  # Permission to use, copy, modify, and/or distribute this software for any
4
4
  # purpose with or without fee is hereby granted, provided that the above
5
5
  # copyright notice and this permission notice appear in all copies.
6
- #
6
+ #
7
7
  # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
8
  # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
9
  # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
@@ -14,23 +14,23 @@
14
14
 
15
15
  module Xeroizer
16
16
  class Response
17
-
17
+
18
18
  attr_accessor :id, :status, :errors, :provider, :date_time, :response_items, :request_params, :request_xml, :response_xml
19
-
19
+
20
20
  class << self
21
-
21
+
22
22
  # Parse the response retreived during any request.
23
23
  def parse(raw_response, request = {}, options = {}, &block)
24
24
  response = Xeroizer::Response.new
25
25
  response.response_xml = raw_response
26
-
26
+
27
27
  doc = Nokogiri::XML(raw_response) { | cfg | cfg.noblanks }
28
-
28
+
29
29
  # check for responses we don't understand
30
30
  raise Xeroizer::UnparseableResponse.new(doc.root.name) unless doc.root.name == 'Response'
31
-
31
+
32
32
  doc.root.elements.each do | element |
33
-
33
+
34
34
  # Text element
35
35
  if element.children && element.children.size == 1 && element.children.first.text?
36
36
  case element.name
@@ -39,31 +39,36 @@ module Xeroizer
39
39
  when 'ProviderName' then response.provider = element.text
40
40
  when 'DateTimeUTC' then response.date_time = Time.parse(element.text)
41
41
  end
42
-
42
+
43
+ # Special case for Paystubs and PayItems because they are not wrapped in plural element or
44
+ # don't have singular children
45
+ elsif element.children && element.children.size > 0 && (element.name == 'Paystub' || element.name == 'PayItems')
46
+ yield(response, [element], element.name)
47
+
43
48
  # Records in response
44
49
  elsif element.children && element.children.size > 0
45
50
  yield(response, element.children, element.children.first.name)
46
51
  end
47
52
  end
48
-
53
+
49
54
  response
50
55
  end
51
-
56
+
52
57
  end
53
-
58
+
54
59
  public
55
-
60
+
56
61
  def initialize
57
62
  @response_items = []
58
63
  end
59
-
64
+
60
65
  def success?
61
66
  status == 'OK'
62
67
  end
63
-
68
+
64
69
  def error
65
70
  errors.blank? ? nil : errors[0]
66
71
  end
67
-
72
+
68
73
  end
69
74
  end
@@ -1,3 +1,3 @@
1
1
  module Xeroizer
2
- VERSION = "2.17.1".freeze
2
+ VERSION = "3.0.0".freeze
3
3
  end
data/lib/xeroizer.rb CHANGED
@@ -5,6 +5,7 @@ require 'active_support/inflector'
5
5
  require "active_support/core_ext/array"
6
6
  require "active_support/core_ext/big_decimal/conversions"
7
7
  require 'oauth'
8
+ require 'oauth2'
8
9
  require 'oauth/signature/rsa/sha1'
9
10
  require 'nokogiri'
10
11
  require 'builder'
@@ -17,14 +18,17 @@ $: << File.expand_path(File.dirname(__FILE__))
17
18
  require 'class_level_inheritable_attributes'
18
19
  require 'xeroizer/exceptions'
19
20
  require 'xeroizer/oauth'
21
+ require 'xeroizer/oauth2'
20
22
  require 'xeroizer/http_encoding_helper'
21
23
  require 'xeroizer/http'
24
+ require 'xeroizer/connection'
22
25
 
23
26
  require 'xeroizer/record/base_model'
24
27
  require 'xeroizer/record/payroll_base_model'
25
28
  require 'xeroizer/record/base'
26
29
  require 'xeroizer/record/payroll_base'
27
30
  require 'xeroizer/configuration'
31
+ require 'xeroizer/http_response'
28
32
 
29
33
  # Include models
30
34
  require 'xeroizer/models/account'
@@ -33,6 +37,7 @@ require 'xeroizer/models/allocation'
33
37
  require 'xeroizer/models/branding_theme'
34
38
  require 'xeroizer/models/bank_transaction'
35
39
  require 'xeroizer/models/bank_account'
40
+ require 'xeroizer/models/batch_payment'
36
41
  require 'xeroizer/models/from_bank_account'
37
42
  require 'xeroizer/models/to_bank_account'
38
43
  require 'xeroizer/models/bank_transfer'
@@ -42,8 +47,10 @@ require 'xeroizer/models/credit_note'
42
47
  require 'xeroizer/models/currency'
43
48
  require 'xeroizer/models/employee'
44
49
  require 'xeroizer/models/expense_claim'
50
+ require 'xeroizer/models/history_record'
45
51
  require 'xeroizer/models/invoice'
46
52
  require 'xeroizer/models/invoice_reminder'
53
+ require 'xeroizer/models/online_invoice'
47
54
  require 'xeroizer/models/item'
48
55
  require 'xeroizer/models/item_purchase_details'
49
56
  require 'xeroizer/models/item_sales_details'
@@ -55,10 +62,12 @@ require 'xeroizer/models/manual_journal_line'
55
62
  require 'xeroizer/models/option'
56
63
  require 'xeroizer/models/organisation'
57
64
  require 'xeroizer/models/payment'
65
+ require 'xeroizer/models/payment_service'
58
66
  require 'xeroizer/models/prepayment'
59
67
  require 'xeroizer/models/overpayment'
60
68
  require 'xeroizer/models/phone'
61
69
  require 'xeroizer/models/purchase_order'
70
+ require 'xeroizer/models/quote'
62
71
  require 'xeroizer/models/receipt'
63
72
  require 'xeroizer/models/repeating_invoice'
64
73
  require 'xeroizer/models/schedule'
@@ -71,16 +80,37 @@ require 'xeroizer/models/journal_line_tracking_category'
71
80
  require 'xeroizer/models/contact_sales_tracking_category'
72
81
  require 'xeroizer/models/contact_purchases_tracking_category'
73
82
 
74
- require 'xeroizer/models/payroll/home_address'
75
83
  require 'xeroizer/models/payroll/bank_account'
84
+ require 'xeroizer/models/payroll/benefit_line'
85
+ require 'xeroizer/models/payroll/benefit_type'
86
+ require 'xeroizer/models/payroll/deduction_line'
87
+ require 'xeroizer/models/payroll/deduction_type'
88
+ require 'xeroizer/models/payroll/earnings_line'
89
+ require 'xeroizer/models/payroll/earnings_type'
76
90
  require 'xeroizer/models/payroll/employee'
91
+ require 'xeroizer/models/payroll/address'
92
+ require 'xeroizer/models/payroll/leave_line'
93
+ require 'xeroizer/models/payroll/pay_items'
94
+ require 'xeroizer/models/payroll/pay_run'
95
+ require 'xeroizer/models/payroll/pay_template'
96
+ require 'xeroizer/models/payroll/payment_method'
97
+ require 'xeroizer/models/payroll/pay_schedule'
98
+ require 'xeroizer/models/payroll/paystub'
99
+ require 'xeroizer/models/payroll/reimbursement_line'
100
+ require 'xeroizer/models/payroll/reimbursement_type'
101
+ require 'xeroizer/models/payroll/salary_and_wage'
102
+ require 'xeroizer/models/payroll/super_line'
103
+ require 'xeroizer/models/payroll/tax_declaration'
104
+ require 'xeroizer/models/payroll/time_off_line'
105
+ require 'xeroizer/models/payroll/time_off_type'
106
+ require 'xeroizer/models/payroll/work_location'
107
+ require 'xeroizer/models/payroll/leave_application'
108
+ require 'xeroizer/models/payroll/leave_period'
77
109
 
78
110
  require 'xeroizer/report/factory'
79
111
 
80
112
  require 'xeroizer/response'
81
113
 
82
114
  require 'xeroizer/generic_application'
83
- require 'xeroizer/public_application'
84
- require 'xeroizer/private_application'
85
- require 'xeroizer/partner_application'
115
+ require 'xeroizer/oauth2_application'
86
116
  require 'xeroizer/payroll_application'
@@ -4,40 +4,67 @@ require "acceptance_test"
4
4
  class AboutCreatingBankTransactions < Test::Unit::TestCase
5
5
  include AcceptanceTest
6
6
 
7
- let :client do
8
- Xeroizer::PrivateApplication.new(@consumer_key, @consumer_secret, @key_file)
7
+ def assert_exists(bank_transaction, client)
8
+ assert_not_nil bank_transaction.id,
9
+ "Cannot check for exitence unless the bank transaction has non-null identifier"
10
+ assert_not_nil client.BankTransaction.find bank_transaction.id
11
+ end
12
+
13
+ def any_line_items(account)
14
+ [{
15
+ :description => "Clingfilm bike shorts",
16
+ :quantity => 1,
17
+ :unit_amount => "17.00",
18
+ :account_code => account.code,
19
+ :tax_type => account.tax_type
20
+ }]
9
21
  end
10
22
 
11
- def setup
12
- super
13
- all_accounts = client.Account.all
23
+ def get_inclusive_tax(amount, tax_rate)
24
+ inclusive_tax = amount * (1 - (100/(100 + tax_rate)))
25
+ BigDecimal(inclusive_tax.to_s).round(2)
26
+ end
27
+
28
+ def get_exclusive_tax(amount, tax_rate)
29
+ exclusive_tax = amount * (tax_rate/100)
30
+ BigDecimal(exclusive_tax.to_s).round(2)
31
+ end
32
+
33
+ def get_tax_rate(tax_type, client)
34
+ @all_tax_types ||= client.TaxRate.all
35
+ @all_tax_types.select{|tax_rate| tax_rate.tax_type == tax_type}.first
36
+ end
37
+
38
+ setup do
39
+ @client = AcceptanceTestHelpers.oauth2_client
40
+ all_accounts = @client.Account.all
14
41
  @account = all_accounts.select{|acct| acct.status == "ACTIVE" && acct.type == "REVENUE"}.first
15
- @bank_account = all_accounts.select{|acct| acct.status == "ACTIVE" && acct.type == "BANK"}.first
42
+ @bank_account = all_accounts.select{|acct| acct.status == "ACTIVE" && acct.type == "BANK"}.first
16
43
  end
17
44
 
18
45
  can "create a new SPEND bank transaction" do
19
- new_transaction = client.BankTransaction.build(
20
- :type => "SPEND",
21
- :contact => { :name => "Jazz Kang" },
22
- :line_items => any_line_items(@account),
23
- :bank_account => { :account_id => @bank_account.account_id }
46
+ new_transaction = @client.BankTransaction.build(
47
+ :type => "SPEND",
48
+ :contact => { :name => "Jazz Kang" },
49
+ :line_items => any_line_items(@account),
50
+ :bank_account => { :account_id => @bank_account.account_id }
24
51
  )
25
52
 
26
53
  assert new_transaction.save, "Save failed with the following errors: #{new_transaction.errors.inspect}"
27
- assert_exists new_transaction
54
+ assert_exists(new_transaction, @client)
28
55
  end
29
56
 
30
57
  can "update a SPEND bank transaction, for example by setting its status" do
31
- new_transaction = client.BankTransaction.build(
32
- :type => "SPEND",
33
- :contact => { :name => "Jazz Kang" },
34
- :line_items => any_line_items(@account),
35
- :bank_account => { :account_id => @bank_account.account_id }
58
+ new_transaction = @client.BankTransaction.build(
59
+ :type => "SPEND",
60
+ :contact => { :name => "Jazz Kang" },
61
+ :line_items => any_line_items(@account),
62
+ :bank_account => { :account_id => @bank_account.account_id }
36
63
  )
37
64
 
38
65
  assert new_transaction.save, "Save failed with the following errors: #{new_transaction.errors.inspect}"
39
66
 
40
- assert_exists new_transaction
67
+ assert_exists new_transaction, @client
41
68
 
42
69
  the_new_type = "RECEIVE"
43
70
 
@@ -49,114 +76,95 @@ class AboutCreatingBankTransactions < Test::Unit::TestCase
49
76
 
50
77
  assert_equal expected_id, new_transaction.id, "Expected the id to be the same because it has been updated"
51
78
 
52
- refreshed_bank_transaction = client.BankTransaction.find expected_id
79
+ refreshed_bank_transaction = @client.BankTransaction.find expected_id
53
80
 
54
81
  assert_equal the_new_type, refreshed_bank_transaction.type,
55
- "Expected the bank transaction to've had its type updated"
82
+ "Expected the bank transaction to've had its type updated"
56
83
  end
57
84
 
58
85
  can "update a bank transaction by adding line items provided you calculate the tax_amount correctly" do
59
- new_transaction = client.BankTransaction.build(
60
- :type => "SPEND",
61
- :contact => { :name => "Jazz Kang" },
62
- :line_items => any_line_items(@account),
63
- :bank_account => { :account_id => @bank_account.account_id },
64
- :line_amount_types => "Exclusive"
86
+ new_transaction = @client.BankTransaction.build(
87
+ :type => "SPEND",
88
+ :contact => { :name => "Jazz Kang" },
89
+ :line_items => any_line_items(@account),
90
+ :bank_account => { :account_id => @bank_account.account_id },
91
+ :line_amount_types => "Exclusive"
65
92
  )
66
93
 
67
94
  assert new_transaction.save, "Save failed with the following errors: #{new_transaction.errors.inspect}"
68
- assert_exists new_transaction
95
+ assert_exists new_transaction, @client
69
96
 
70
97
  expected_id = new_transaction.id
71
98
 
72
- tax_rate = get_tax_rate(@account.tax_type).effective_rate
99
+ tax_rate = get_tax_rate(@account.tax_type, @client).effective_rate
73
100
 
74
101
  unit_price = BigDecimal("1337.00")
75
102
 
76
103
  the_new_line_items = [
77
- {
78
- :description => "Burrito skin",
79
- :quantity => 1,
80
- :unit_amount => unit_price,
81
- :account_code => @account.code,
82
- :tax_type => @account.tax_type,
83
- :tax_amount => get_exclusive_tax(unit_price, tax_rate)
84
- }
104
+ {
105
+ :description => "Burrito skin",
106
+ :quantity => 1,
107
+ :unit_amount => unit_price,
108
+ :account_code => @account.code,
109
+ :tax_type => @account.tax_type,
110
+ :tax_amount => get_exclusive_tax(unit_price, tax_rate)
111
+ }
85
112
  ]
86
113
 
87
114
  new_transaction.line_items = the_new_line_items
88
115
 
89
116
  assert new_transaction.save, "Update failed with the following errors: #{new_transaction.errors.inspect}"
90
117
 
91
- refreshed_bank_transaction = client.BankTransaction.find expected_id
118
+ refreshed_bank_transaction = @client.BankTransaction.find expected_id
92
119
 
93
120
  assert_equal expected_id, new_transaction.id,
94
- "Expected the id to be the same because it has been updated"
121
+ "Expected the id to be the same because it has been updated"
95
122
 
96
123
  assert_equal 1, refreshed_bank_transaction.line_items.size,
97
- "Expected the bank transaction to've had its line items updated to just one"
124
+ "Expected the bank transaction to've had its line items updated to just one"
98
125
 
99
126
  the_first_line_item = refreshed_bank_transaction.line_items.first
100
127
 
101
128
  assert_equal "Burrito skin", the_first_line_item.description,
102
- "Expected the bank transaction to've had its line items updated, " +
103
- "but the first one's description does not match: #{the_first_line_item.inspect}"
104
- end
105
-
106
- def get_inclusive_tax(amount, tax_rate)
107
- inclusive_tax = amount * (1 - (100/(100 + tax_rate)))
108
- BigDecimal(inclusive_tax.to_s).round(2)
109
- end
110
-
111
- def get_exclusive_tax(amount, tax_rate)
112
- exclusive_tax = amount * (tax_rate/100)
113
- BigDecimal(exclusive_tax.to_s).round(2)
114
- end
115
-
116
- def get_tax_rate tax_type
117
- @all_tax_types ||= client.TaxRate.all
118
- @all_tax_types.select{|tax_rate| tax_rate.tax_type == tax_type}.first
129
+ "Expected the bank transaction to've had its line items updated, " +
130
+ "but the first one's description does not match: #{the_first_line_item.inspect}"
119
131
  end
120
132
 
121
133
  can "create a new RECEIVE bank transaction" do
122
- new_transaction = client.BankTransaction.build(
123
- :type => "RECEIVE",
124
- :contact => { :name => "Jazz Kang" },
125
- :line_items => any_line_items(@account),
126
- :bank_account => { :account_id => @bank_account.account_id }
134
+ new_transaction = @client.BankTransaction.build(
135
+ :type => "RECEIVE",
136
+ :contact => { :name => "Jazz Kang" },
137
+ :line_items => any_line_items(@account),
138
+ :bank_account => { :account_id => @bank_account.account_id }
127
139
  )
128
140
 
129
141
  assert new_transaction.save, "Save failed with the following errors: #{new_transaction.errors.inspect}"
130
- assert_exists new_transaction
142
+ assert_exists new_transaction, @client
131
143
  end
132
144
 
133
145
  it "treats line item unit_amounts as tax EXCLUSIVE"
134
146
  must "not set the tax_amount manually on line items"
135
147
 
136
- def assert_exists(bank_transaction)
137
- assert_not_nil bank_transaction.id,
138
- "Cannot check for exitence unless the bank transaction has non-null identifier"
139
- assert_not_nil client.BankTransaction.find bank_transaction.id
140
- end
141
148
 
142
- def any_line_items(account)
143
- [{
144
- :description => "Clingfilm bike shorts",
145
- :quantity => 1,
146
- :unit_amount => "17.00",
147
- :account_code => account.code,
148
- :tax_type => account.tax_type
149
- }]
150
- end
151
149
 
152
- it "fails with ApiException when you try and create a new bank account with missing account type" do
153
- new_account = client.Account.build(
154
- :name => "Example bank account",
155
- :code => "ACC-001"
150
+ it "fails with ApiException when you try and create a new bank account with missing account type with save! method" do
151
+ new_account = @client.Account.build(
152
+ :name => "Example bank account",
153
+ :code => "ACC-001"
156
154
  )
157
155
 
158
156
  assert_raise Xeroizer::ApiException do
159
- new_account.save
157
+ new_account.save!
160
158
  end
161
159
  end
160
+
161
+ it "returns false when you try and create a new bank account with a missing account type with save method" do
162
+ new_account = @client.Account.build(
163
+ :name => "Example bank account",
164
+ :code => "ACC-001"
165
+ )
166
+
167
+ assert new_account.save == false, "Account save method expected to return false"
168
+
169
+ end
162
170
  end