xeroizer 2.16.5 → 2.17.1

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -27
  3. data/lib/class_level_inheritable_attributes.rb +3 -0
  4. data/lib/xeroizer.rb +13 -1
  5. data/lib/xeroizer/exceptions.rb +1 -1
  6. data/lib/xeroizer/generic_application.rb +13 -1
  7. data/lib/xeroizer/http.rb +128 -120
  8. data/lib/xeroizer/models/account.rb +1 -0
  9. data/lib/xeroizer/models/address.rb +18 -9
  10. data/lib/xeroizer/models/attachment.rb +1 -1
  11. data/lib/xeroizer/models/balances.rb +1 -0
  12. data/lib/xeroizer/models/bank_transaction.rb +2 -2
  13. data/lib/xeroizer/models/bank_transfer.rb +28 -0
  14. data/lib/xeroizer/models/contact.rb +11 -4
  15. data/lib/xeroizer/models/credit_note.rb +9 -4
  16. data/lib/xeroizer/models/from_bank_account.rb +12 -0
  17. data/lib/xeroizer/models/invoice.rb +11 -3
  18. data/lib/xeroizer/models/invoice_reminder.rb +19 -0
  19. data/lib/xeroizer/models/line_item.rb +21 -9
  20. data/lib/xeroizer/models/manual_journal.rb +6 -0
  21. data/lib/xeroizer/models/organisation.rb +4 -0
  22. data/lib/xeroizer/models/overpayment.rb +40 -0
  23. data/lib/xeroizer/models/payroll/bank_account.rb +23 -0
  24. data/lib/xeroizer/models/payroll/employee.rb +45 -0
  25. data/lib/xeroizer/models/payroll/home_address.rb +24 -0
  26. data/lib/xeroizer/models/prepayment.rb +1 -0
  27. data/lib/xeroizer/models/tax_rate.rb +5 -4
  28. data/lib/xeroizer/models/to_bank_account.rb +12 -0
  29. data/lib/xeroizer/oauth.rb +8 -8
  30. data/lib/xeroizer/partner_application.rb +4 -8
  31. data/lib/xeroizer/payroll_application.rb +28 -0
  32. data/lib/xeroizer/private_application.rb +2 -4
  33. data/lib/xeroizer/record/base_model.rb +137 -122
  34. data/lib/xeroizer/record/base_model_http_proxy.rb +1 -1
  35. data/lib/xeroizer/record/payroll_base.rb +25 -0
  36. data/lib/xeroizer/record/payroll_base_model.rb +29 -0
  37. data/lib/xeroizer/record/record_association_helper.rb +13 -14
  38. data/lib/xeroizer/record/validation_helper.rb +1 -1
  39. data/lib/xeroizer/record/xml_helper.rb +10 -8
  40. data/lib/xeroizer/report/aged_receivables_by_contact.rb +0 -1
  41. data/lib/xeroizer/report/base.rb +0 -1
  42. data/lib/xeroizer/report/factory.rb +3 -3
  43. data/lib/xeroizer/report/row/header.rb +4 -4
  44. data/lib/xeroizer/report/row/xml_helper.rb +2 -2
  45. data/lib/xeroizer/version.rb +1 -1
  46. data/test/acceptance/about_creating_prepayment_test.rb +46 -0
  47. data/test/acceptance/about_fetching_bank_transactions_test.rb +21 -21
  48. data/test/acceptance/acceptance_test.rb +4 -4
  49. data/test/acceptance/bank_transaction_reference_data.rb +3 -1
  50. data/test/acceptance/bank_transfer_test.rb +26 -0
  51. data/test/test_helper.rb +6 -4
  52. data/test/unit/models/address_test.rb +92 -0
  53. data/test/unit/models/bank_transaction_validation_test.rb +1 -1
  54. data/test/unit/models/contact_test.rb +20 -4
  55. data/test/unit/models/line_item_test.rb +20 -6
  56. data/test/unit/models/tax_rate_test.rb +52 -1
  57. data/test/unit/record/base_model_test.rb +1 -1
  58. data/test/unit/record/base_test.rb +9 -6
  59. data/test/unit/record/model_definition_test.rb +2 -2
  60. data/test/unit/report_test.rb +19 -21
  61. metadata +20 -3
@@ -44,7 +44,7 @@ module Xeroizer
44
44
  conditions = []
45
45
  where.each do | key, value |
46
46
  (attribute_name, expression) = extract_expression_from_attribute_name(key)
47
- (field_name, field) = model_class.fields.find { | k, v | v[:internal_name] == attribute_name }
47
+ (_, field) = model_class.fields.find { | k, v | v[:internal_name] == attribute_name }
48
48
  if field
49
49
  conditions << where_condition_part(field, expression, value)
50
50
  else
@@ -0,0 +1,25 @@
1
+ module Xeroizer
2
+ module Record
3
+
4
+ class PayrollBase < Xeroizer::Record::Base
5
+
6
+ class_inheritable_attributes :fields, :possible_primary_keys, :primary_key_name, :summary_only, :validators
7
+
8
+ def self.belongs_to(field_name, options = {})
9
+ super(field_name, {:base_module => Xeroizer::Record::Payroll}.merge(options))
10
+ end
11
+
12
+ def self.has_many(field_name, options = {})
13
+ super(field_name, {:base_module => Xeroizer::Record::Payroll}.merge(options))
14
+ end
15
+
16
+ public
17
+
18
+ def new_model_class(model_name)
19
+ Xeroizer::Record::Payroll.const_get("#{model_name}Model".to_sym).new(parent.application, model_name.to_s)
20
+ end
21
+
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ require 'xeroizer/record/base_model_http_proxy'
2
+
3
+ module Xeroizer
4
+ module Record
5
+
6
+ class PayrollBaseModel < Xeroizer::Record::BaseModel
7
+
8
+ class_inheritable_attributes :api_controller_name
9
+ class_inheritable_attributes :permissions
10
+ class_inheritable_attributes :xml_root_name
11
+ class_inheritable_attributes :optional_xml_root_name
12
+ class_inheritable_attributes :xml_node_name
13
+
14
+ include BaseModelHttpProxy
15
+
16
+ public
17
+
18
+ def model_class
19
+ @model_class ||= Xeroizer::Record::Payroll.const_get(model_name.to_sym)
20
+ end
21
+
22
+ def parse_response(response_xml, options = {})
23
+ super(response_xml, {:base_module => Xeroizer::Record::Payroll}.merge(options))
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -10,7 +10,7 @@ module Xeroizer
10
10
 
11
11
  def belongs_to(field_name, options = {})
12
12
  internal_field_name = options[:internal_name] || field_name
13
- internal_singular_field_name = internal_field_name.to_s.singularize
13
+ internal_singular_field_name = options[:internal_name_singular] || internal_field_name.to_s.singularize
14
14
 
15
15
  define_association_attribute(field_name, internal_singular_field_name, :belongs_to, options)
16
16
 
@@ -25,7 +25,7 @@ module Xeroizer
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
- record = Xeroizer::Record.const_get(model_name).build(attributes, model_parent)
28
+ record = (options[:base_module] || Xeroizer::Record).const_get(model_name).build(attributes, model_parent)
29
29
  self.attributes[field_name] = record
30
30
  end
31
31
  end
@@ -34,8 +34,8 @@ module Xeroizer
34
34
 
35
35
  def has_many(field_name, options = {})
36
36
  internal_field_name = options[:internal_name] || field_name
37
- internal_singular_field_name = internal_field_name.to_s.singularize
38
-
37
+ internal_singular_field_name = options[:internal_name_singular] || internal_field_name.to_s.singularize
38
+
39
39
  define_association_attribute(field_name, internal_field_name, :has_many, options)
40
40
 
41
41
  # Create an #add_record_name method to build the record and add to the attributes.
@@ -47,7 +47,7 @@ module Xeroizer
47
47
  model_parent = new_model_class(model_name)
48
48
 
49
49
  # The class of this record.
50
- record_class = Xeroizer::Record.const_get(model_name)
50
+ record_class = (options[:base_module] || Xeroizer::Record).const_get(model_name)
51
51
 
52
52
  # Parse the *args variable so that we can use this method like:
53
53
  # add_record({fields}, {fields}, ...)
@@ -60,7 +60,7 @@ module Xeroizer
60
60
  elsif args.size > 0
61
61
  records = args
62
62
  else
63
- raise StandardError.new("Invalid arguments for #{self.class.name}#add_#{internal_singular_field_name}(#{args.inspect}).")
63
+ raise XeroizerError.new("Invalid arguments for #{self.class.name}#add_#{internal_singular_field_name}(#{args.inspect}).")
64
64
  end
65
65
 
66
66
  # Ensure that complete record is downloaded before adding new records
@@ -70,7 +70,7 @@ module Xeroizer
70
70
  last_record = nil
71
71
  records.each do | record |
72
72
  record = record_class.build(record, model_parent) if record.is_a?(Hash)
73
- raise StandardError.new("Record #{record.class.name} is not a #{record_class.name}.") unless record.is_a?(record_class)
73
+ raise XeroizerError.new("Record #{record.class.name} is not a #{record_class.name}.") unless record.is_a?(record_class)
74
74
  self.attributes[field_name] ||= []
75
75
  self.attributes[field_name] << record
76
76
  last_record = record
@@ -85,11 +85,10 @@ module Xeroizer
85
85
  define_simple_attribute(field_name, association_type, options.merge!(:skip_writer => true), ((association_type == :has_many) ? [] : nil))
86
86
 
87
87
  internal_field_name = options[:internal_name] || field_name
88
- internal_singular_field_name = internal_field_name.to_s.singularize
88
+ internal_singular_field_name = options[:internal_name_singular] || internal_field_name.to_s.singularize
89
89
  model_name = options[:model_name] ? options[:model_name].to_sym : field_name.to_s.singularize.camelize.to_sym
90
-
91
- define_method "#{internal_field_name}=".to_sym do | value |
92
- record_class = Xeroizer::Record.const_get(model_name)
90
+ define_method "#{internal_field_name}=".to_sym do | value |
91
+ record_class = (options[:base_module] || Xeroizer::Record).const_get(model_name)
93
92
  case value
94
93
  when Hash
95
94
  self.attributes[field_name] = ((association_type == :has_many) ? [] : nil)
@@ -98,9 +97,9 @@ module Xeroizer
98
97
  self.attributes[field_name] = []
99
98
  self.send("add_#{internal_singular_field_name}".to_sym, value)
100
99
 
101
- when :belongs_to
102
- self.attributes[field_name] = Xeroizer::Record.const_get(model_name).build(value, new_model_class(model_name))
103
-
100
+ when :belongs_to
101
+ self.attributes[field_name] = (options[:base_module] || Xeroizer::Record).const_get(model_name).build(value, new_model_class(model_name))
102
+
104
103
  end
105
104
 
106
105
  when Array
@@ -64,7 +64,7 @@ module Xeroizer
64
64
 
65
65
  def errors_for(attribute)
66
66
  if errors.is_a?(Array)
67
- errors.find_all { | (attr, msg) | attr == attribute }.map { | (attr, msg) | msg }
67
+ errors.find_all { | (attr, _) | attr == attribute }.map { | (_, msg) | msg }
68
68
  end
69
69
  end
70
70
 
@@ -12,7 +12,7 @@ module Xeroizer
12
12
  module ClassMethods
13
13
 
14
14
  # Build a record instance from the XML node.
15
- def build_from_node(node, parent)
15
+ def build_from_node(node, parent, base_module)
16
16
  record = new(parent)
17
17
  node.elements.each do | element |
18
18
  field = self.fields[element.name.to_s.underscore.to_sym]
@@ -25,17 +25,17 @@ module Xeroizer
25
25
  when :decimal then BigDecimal.new(element.text)
26
26
  when :date then Date.parse(element.text)
27
27
  when :datetime then Time.parse(element.text)
28
- when :datetime_utc then ActiveSupport::TimeZone['UTC'].parse(element.text).utc.round(3)
28
+ when :datetime_utc then ActiveSupport::TimeZone['UTC'].parse(element.text).utc
29
29
  when :belongs_to
30
30
  model_name = field[:model_name] ? field[:model_name].to_sym : element.name.to_sym
31
- Xeroizer::Record.const_get(model_name).build_from_node(element, parent)
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
36
36
  sub_parent = record.new_model_class(sub_field_name)
37
- element.children.inject([]) do | list, element |
38
- list << Xeroizer::Record.const_get(sub_field_name).build_from_node(element, sub_parent)
37
+ element.children.inject([]) do | list, inner_element |
38
+ list << base_module.const_get(sub_field_name).build_from_node(inner_element, sub_parent, base_module)
39
39
  end
40
40
  end
41
41
 
@@ -60,8 +60,8 @@ module Xeroizer
60
60
 
61
61
  # Turn a record into its XML representation.
62
62
  def to_xml(b = Builder::XmlMarkup.new(:indent => 2))
63
- optional_root_tag(parent.class.optional_xml_root_name, b) do |b|
64
- b.tag!(model.class.xml_node_name || model.model_name) {
63
+ optional_root_tag(parent.class.optional_xml_root_name, b) do |c|
64
+ c.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]
@@ -82,7 +82,7 @@ module Xeroizer
82
82
  # </Payments>
83
83
  def optional_root_tag(root_name, b, &block)
84
84
  if root_name
85
- b.tag!(root_name) { |b| yield(b) }
85
+ b.tag!(root_name) { |c| yield(c) }
86
86
  else
87
87
  yield(b)
88
88
  end
@@ -107,6 +107,8 @@ module Xeroizer
107
107
  real_value = case value
108
108
  when Date then value.strftime("%Y-%m-%d")
109
109
  when Time then value.utc.strftime("%Y-%m-%d")
110
+ when NilClass then nil
111
+ else raise ArgumentError.new("Expected Date or Time object for the #{field[:api_name]} field")
110
112
  end
111
113
  b.tag!(field[:api_name], real_value)
112
114
 
@@ -32,7 +32,6 @@ module Xeroizer
32
32
 
33
33
  def sum(column_name, &block)
34
34
  sections.first.rows.inject(BigDecimal.new('0')) do | sum, row |
35
- cell = row.cell(column_name)
36
35
  sum += row.cell(column_name).value if row.class == Xeroizer::Report::Row && (block.nil? || block.call(row))
37
36
  sum
38
37
  end
@@ -1,4 +1,3 @@
1
- require 'xeroizer/report/base'
2
1
  require 'xeroizer/report/cell'
3
2
  require 'xeroizer/report/row/row'
4
3
  require 'xeroizer/report/row/header'
@@ -23,8 +23,8 @@ module Xeroizer
23
23
  # valid query-string parameters to pass to the API.
24
24
  def get(options = {})
25
25
  @response_xml = options[:cache_file] ? File.read(options[:cache_file]) : http_get(options)
26
- response = Response.parse(response_xml, options) do | response, elements |
27
- parse_reports(response, elements)
26
+ response = Response.parse(response_xml, options) do | inner_response, elements |
27
+ parse_reports(inner_response, elements)
28
28
  end
29
29
  response.response_items.first # there is is only one
30
30
  end
@@ -36,7 +36,7 @@ module Xeroizer
36
36
  def klass
37
37
  begin
38
38
  @_klass_cache ||= Xeroizer::Report.const_get(report_type, false)
39
- rescue NameError => ex # use default class
39
+ rescue NameError # use default class
40
40
  Base
41
41
  end
42
42
  end
@@ -2,10 +2,10 @@ module Xeroizer
2
2
  module Report
3
3
  class HeaderRow < Row
4
4
 
5
- def column_index(column_name)
6
- @_column_index_cache ||= {}
7
- @_column_index_cache[column_name] ||= cells.find_index { | cell | cell.value == column_name.to_s }
8
- end
5
+ def column_index(column_name)
6
+ @_column_index_cache ||= {}
7
+ @_column_index_cache[column_name] ||= cells.find_index { | cell | cell.value == column_name.to_s }
8
+ end
9
9
 
10
10
  end
11
11
  end
@@ -16,7 +16,7 @@ module Xeroizer
16
16
  row = nil
17
17
  case row_type
18
18
  when 'Header'
19
- row = HeaderRow.new(report);
19
+ row = HeaderRow.new(report)
20
20
  parent.header = row if parent
21
21
  report.header ||= row
22
22
 
@@ -26,7 +26,7 @@ module Xeroizer
26
26
  report.sections << row
27
27
 
28
28
  when 'SummaryRow'
29
- row = SummaryRow.new(report);
29
+ row = SummaryRow.new(report)
30
30
  row.header = report.header
31
31
  if parent
32
32
  parent.summary = row
@@ -1,3 +1,3 @@
1
1
  module Xeroizer
2
- VERSION = "2.16.5".freeze
2
+ VERSION = "2.17.1".freeze
3
3
  end
@@ -0,0 +1,46 @@
1
+ require "test_helper"
2
+ require "acceptance_test"
3
+
4
+ class AboutCreatingPrepayment < Test::Unit::TestCase
5
+ include AcceptanceTest
6
+
7
+ let :client do
8
+ Xeroizer::PrivateApplication.new(@consumer_key, @consumer_secret, @key_file)
9
+ end
10
+
11
+ def setup
12
+ super
13
+ all_accounts = client.Account.all
14
+ @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
16
+ end
17
+
18
+ can "create a new PrePayment bank transaction" do
19
+ new_transaction = client.BankTransaction.build(
20
+ :type => "RECEIVE-PREPAYMENT",
21
+ :contact => { :name => "Jazz Kang" },
22
+ :line_items => any_line_items(@account),
23
+ :bank_account => { :account_id => @bank_account.account_id }
24
+ )
25
+
26
+ assert new_transaction.save, "Save failed with the following errors: #{new_transaction.errors.inspect}"
27
+ assert_exists new_transaction
28
+ end
29
+
30
+ def any_line_items(account)
31
+ [{
32
+ :description => "Clingfilm bike shorts",
33
+ :quantity => 1,
34
+ :unit_amount => "200.00",
35
+ :account_code => account.code,
36
+ :tax_type => account.tax_type
37
+ }]
38
+ end
39
+
40
+ def assert_exists(prepayment)
41
+ assert_not_nil prepayment.id,
42
+ "Cannot check for exitence unless the prepayment (bank transaction) has non-null identifier"
43
+ assert_not_nil client.BankTransaction.find prepayment.id
44
+ end
45
+
46
+ end
@@ -9,6 +9,26 @@ class AboutFetchingBankTransactions < Test::Unit::TestCase
9
9
  @client ||= Xeroizer::PrivateApplication.new(@consumer_key, @consumer_secret, @key_file)
10
10
  end
11
11
 
12
+ context "when requesting a single bank transaction with a reference" do
13
+ setup do
14
+ @a_new_bank_transaction = BankTransactionReferenceData.new(client).bank_transaction
15
+ end
16
+
17
+ it "has the extended set of attributes" do
18
+ keys = [:line_amount_types, :contact, :date, :status, :line_items,
19
+ :updated_date_utc, :currency_code, :bank_transaction_id,
20
+ :bank_account, :type, :reference, :is_reconciled, :currency_rate]
21
+ assert_equal(@a_new_bank_transaction.attributes.keys, keys)
22
+ end
23
+
24
+ it "returns full line item details" do
25
+ single_bank_transaction = client.BankTransaction.find @a_new_bank_transaction.id
26
+
27
+ assert_not_empty single_bank_transaction.line_items,
28
+ "expected the bank transaction's line items to have been included"
29
+ end
30
+ end
31
+
12
32
  context "when requesting all bank transactions (i.e., without filter)" do
13
33
  setup do
14
34
  @the_first_bank_transaction = client.BankTransaction.all.first
@@ -16,7 +36,7 @@ class AboutFetchingBankTransactions < Test::Unit::TestCase
16
36
 
17
37
  it "has the limited set of attributes" do
18
38
  keys = [:line_amount_types, :contact, :date, :status, :updated_date_utc,
19
- :currency_code, :bank_transaction_id, :bank_account, :type,
39
+ :currency_code, :bank_transaction_id, :bank_account, :type, :reference,
20
40
  :is_reconciled]
21
41
  assert_equal(@the_first_bank_transaction.attributes.keys, keys)
22
42
  end
@@ -29,25 +49,5 @@ class AboutFetchingBankTransactions < Test::Unit::TestCase
29
49
  assert_not_nil @the_first_bank_transaction.bank_account
30
50
  end
31
51
  end
32
-
33
- context "when requesting a single bank transaction for example" do
34
- setup do
35
- @a_new_bank_transaction = BankTransactionReferenceData.new(client).bank_transaction
36
- end
37
-
38
- it "has the extended set of attributes" do
39
- keys = [:line_amount_types, :contact, :date, :status, :line_items,
40
- :updated_date_utc, :currency_code, :bank_transaction_id,
41
- :bank_account, :type, :is_reconciled, :currency_rate]
42
- assert_equal(@a_new_bank_transaction.attributes.keys, keys)
43
- end
44
-
45
- it "returns full line item details" do
46
- single_bank_transaction = client.BankTransaction.find @a_new_bank_transaction.id
47
-
48
- assert_not_empty single_bank_transaction.line_items,
49
- "expected the bank transaction's line items to have been included"
50
- end
51
- end
52
52
  end
53
53
 
@@ -38,7 +38,7 @@ module AcceptanceTest
38
38
  def load_config_from_file
39
39
  the_file_name = File.join(File.dirname(__FILE__), '..', '..', '.oauth')
40
40
 
41
- return nil unless File.exists? the_file_name
41
+ return nil unless File.exist? the_file_name
42
42
 
43
43
  Xeroizer::OAuthConfig.load IO.read the_file_name
44
44
  end
@@ -46,8 +46,8 @@ module AcceptanceTest
46
46
  def load_config_from_env
47
47
  assert_not_nil ENV["CONSUMER_KEY"], "No CONSUMER_KEY environment variable specified."
48
48
  assert_not_nil ENV["CONSUMER_SECRET"], "No CONSUMER_SECRET environment variable specified."
49
- assert_not_nil ENV["KEY_FILE"], "No KEY_FILE environment variable specified."
50
- assert File.exists?(ENV["KEY_FILE"]), "The file <#{ENV["KEY_FILE"]}> does not exist."
51
- Xeroizer::OAuthCredentials.new ENV["CONSUMER_KEY"], ENV["CONSUMER_SECRET"], ENV["KEY_FILE"]
49
+ assert_not_nil ENV["PRIVATE_KEY_PATH"], "No PRIVATE_KEY_PATH environment variable specified."
50
+ assert File.exist?(ENV["PRIVATE_KEY_PATH"]), "The file <#{ENV["PRIVATE_KEY_PATH"]}> does not exist."
51
+ Xeroizer::OAuthCredentials.new ENV["CONSUMER_KEY"], ENV["CONSUMER_SECRET"], ENV["PRIVATE_KEY_PATH"]
52
52
  end
53
53
  end
@@ -20,11 +20,13 @@ class BankTransactionReferenceData
20
20
  :account_code => account.code,
21
21
  :tax_type => account.tax_type
22
22
  ],
23
- :bank_account => { :account_id => bank_account.account_id }
23
+ :bank_account => { :account_id => bank_account.account_id },
24
+ :reference => "BTF323"
24
25
  )
25
26
 
26
27
  fail("Expected save to have succeeded, but it failed. #{result.errors.inspect}") unless result.save
27
28
 
28
29
  result
29
30
  end
31
+
30
32
  end
@@ -0,0 +1,26 @@
1
+ require "test_helper"
2
+ require "acceptance_test"
3
+
4
+ class BankTransfer < Test::Unit::TestCase
5
+ include AcceptanceTest
6
+
7
+ let :client do
8
+ Xeroizer::PrivateApplication.new(@consumer_key, @consumer_secret, @key_file)
9
+ end
10
+
11
+ def setup
12
+ super
13
+ all_accounts = client.Account.all
14
+ @from_bank_account = all_accounts.select { |acct| acct.status == "ACTIVE" && acct.type == "BANK" }.first
15
+ @to_bank_account = all_accounts.select { |acct| acct.status == "ACTIVE" && acct.type == "BANK" }.last
16
+ end
17
+
18
+ can "create a bank transfer" do
19
+ new_transfer = client.BankTransfer.build(
20
+ :amount => 300,
21
+ :from_bank_account => { :account_id => @from_bank_account.account_id },
22
+ :to_bank_account => { :account_id => @to_bank_account.account_id }
23
+ )
24
+ assert new_transfer.save, "Save failed with the following errors: #{new_transfer.errors.inspect}"
25
+ end
26
+ end