bankserv 0.1.3

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 (75) hide show
  1. data/.gitignore +6 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +16 -0
  4. data/Rakefile +8 -0
  5. data/bankserv.gemspec +31 -0
  6. data/config.ru +7 -0
  7. data/lib/bankserv.rb +48 -0
  8. data/lib/bankserv/account_holder_verification.rb +90 -0
  9. data/lib/bankserv/bank_account.rb +19 -0
  10. data/lib/bankserv/configuration.rb +67 -0
  11. data/lib/bankserv/credit.rb +70 -0
  12. data/lib/bankserv/debit.rb +94 -0
  13. data/lib/bankserv/eft.rb +83 -0
  14. data/lib/bankserv/engine.rb +183 -0
  15. data/lib/bankserv/engine/engine_configuration.rb +12 -0
  16. data/lib/bankserv/engine/engine_process.rb +3 -0
  17. data/lib/bankserv/request.rb +27 -0
  18. data/lib/bankserv/transaction.rb +22 -0
  19. data/lib/bankserv/transmission/document.rb +43 -0
  20. data/lib/bankserv/transmission/input_document.rb +84 -0
  21. data/lib/bankserv/transmission/output_document.rb +27 -0
  22. data/lib/bankserv/transmission/record.rb +13 -0
  23. data/lib/bankserv/transmission/reply_document.rb +27 -0
  24. data/lib/bankserv/transmission/set.rb +120 -0
  25. data/lib/bankserv/transmission/set/account_holder_verification.rb +81 -0
  26. data/lib/bankserv/transmission/set/account_holder_verification_output.rb +17 -0
  27. data/lib/bankserv/transmission/set/credit.rb +44 -0
  28. data/lib/bankserv/transmission/set/debit.rb +44 -0
  29. data/lib/bankserv/transmission/set/document.rb +45 -0
  30. data/lib/bankserv/transmission/set/eft.rb +228 -0
  31. data/lib/bankserv/transmission/set/eft_output.rb +12 -0
  32. data/lib/bankserv/transmission/set/eft_redirect.rb +18 -0
  33. data/lib/bankserv/transmission/set/eft_unpaid.rb +18 -0
  34. data/lib/bankserv/transmission/set/reply.rb +47 -0
  35. data/lib/bankserv/transmission/statement.rb +46 -0
  36. data/lib/bankserv/version.rb +3 -0
  37. data/lib/config/ahv.yml +9 -0
  38. data/lib/core_extensions.rb +37 -0
  39. data/lib/generators/active_record/bankserv_generator.rb +30 -0
  40. data/lib/generators/active_record/templates/migration.rb +141 -0
  41. data/spec/examples/ahv_input_file.txt +7 -0
  42. data/spec/examples/ahv_output_file.txt +7 -0
  43. data/spec/examples/credit_eft_input.txt +166 -0
  44. data/spec/examples/debit_eft_input_file.txt +20 -0
  45. data/spec/examples/eft_input_with_2_sets.txt +8 -0
  46. data/spec/examples/eft_output_file.txt +35 -0
  47. data/spec/examples/host2host/tmp.log +1 -0
  48. data/spec/examples/reply/rejected_transmission.txt +7 -0
  49. data/spec/examples/reply/reply_file.txt +5 -0
  50. data/spec/examples/statement4_unpacked.dat +51 -0
  51. data/spec/examples/tmp/OUTPUT0412153500.txt +35 -0
  52. data/spec/examples/tmp/REPLY0412153000.txt +5 -0
  53. data/spec/factories.rb +90 -0
  54. data/spec/internal/config/database.yml.sample +3 -0
  55. data/spec/internal/config/routes.rb +3 -0
  56. data/spec/internal/db/schema.rb +138 -0
  57. data/spec/internal/log/.gitignore +1 -0
  58. data/spec/internal/public/favicon.ico +0 -0
  59. data/spec/lib/bankserv/account_holder_verification_spec.rb +104 -0
  60. data/spec/lib/bankserv/configuration_spec.rb +34 -0
  61. data/spec/lib/bankserv/core_ext_spec.rb +43 -0
  62. data/spec/lib/bankserv/credit_spec.rb +92 -0
  63. data/spec/lib/bankserv/debit_spec.rb +187 -0
  64. data/spec/lib/bankserv/engine/engine_spec.rb +142 -0
  65. data/spec/lib/bankserv/transaction_spec.rb +32 -0
  66. data/spec/lib/bankserv/transmission/input_document_spec.rb +207 -0
  67. data/spec/lib/bankserv/transmission/output_document_spec.rb +210 -0
  68. data/spec/lib/bankserv/transmission/reply_document_spec.rb +117 -0
  69. data/spec/lib/bankserv/transmission/set/account_holder_verification_spec.rb +108 -0
  70. data/spec/lib/bankserv/transmission/set/credit_spec.rb +96 -0
  71. data/spec/lib/bankserv/transmission/set/debit_spec.rb +103 -0
  72. data/spec/lib/bankserv/transmission/statement_spec.rb +109 -0
  73. data/spec/spec_helper.rb +28 -0
  74. data/spec/support/helpers.rb +207 -0
  75. metadata +223 -0
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ spec/internal/db/bankserv_test.sqlite
6
+ spec/internal/config/database.yml
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2@bankserv --create
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bankserv.gemspec
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'mysql2'
8
+ gem 'rspec'
9
+ gem 'rspec-rails'
10
+ gem 'sqlite3'
11
+ gem 'timecop'
12
+ gem 'factory_girl'
13
+ gem 'faker'
14
+ end
15
+
16
+ gem "holidays"
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ # If you want to make this the default task
7
+ task :default => :spec
8
+ require "bundler/gem_tasks"
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "bankserv/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "bankserv"
7
+ s.version = Bankserv::VERSION
8
+ s.authors = ["Jeffrey van Aswegen", "Douglas Anderson"]
9
+ s.email = ["jeffmess@gmail.com", "i.am.douglas.anderson@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{ A rails 3 engine wrapped around the Absa Host 2 Host gem.}
12
+ s.description = %q{This engine allows users to inject requests into a queue to be processed.
13
+
14
+ The queue handles bank account validations, credit payments, debit orders
15
+ and collecting bank statements. }
16
+
17
+ s.rubyforge_project = "bankserv"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ s.add_dependency "activesupport"
25
+ s.add_dependency "activerecord", "~> 3.0"
26
+ s.add_dependency "i18n"
27
+ s.add_dependency "absa-h2h", "~> 0.0.11"
28
+ s.add_dependency "absa-esd", "~> 0.0.1"
29
+
30
+ s.add_development_dependency 'combustion', '~> 0.3.1'
31
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ Bundler.require :default, :development
5
+
6
+ Combustion.initialize!
7
+ run Combustion::Application
@@ -0,0 +1,48 @@
1
+ require "absa-h2h"
2
+ require "active_record"
3
+ require "core_extensions"
4
+ require "bankserv/version"
5
+
6
+ module Bankserv
7
+
8
+ def self.table_name_prefix
9
+ 'bankserv_'
10
+ end
11
+
12
+ CONFIG_DIR = File.expand_path(File.dirname(__FILE__)) + "/config"
13
+
14
+ end
15
+
16
+ require "bankserv/configuration"
17
+ require "bankserv/eft"
18
+ require "bankserv/request"
19
+ require "bankserv/bank_account"
20
+ require "bankserv/account_holder_verification"
21
+ require "bankserv/debit"
22
+ require "bankserv/credit"
23
+
24
+ require 'bankserv/transmission/document'
25
+ require 'bankserv/transmission/output_document'
26
+ require 'bankserv/transmission/input_document'
27
+ require 'bankserv/transmission/reply_document'
28
+ require 'bankserv/transmission/statement'
29
+
30
+ require 'bankserv/transmission/set'
31
+ require 'bankserv/transmission/record'
32
+
33
+ require 'bankserv/transmission/set/document'
34
+ require 'bankserv/transmission/set/account_holder_verification'
35
+ require 'bankserv/transmission/set/account_holder_verification_output'
36
+ require 'bankserv/transmission/set/eft'
37
+ require 'bankserv/transmission/set/debit'
38
+ require 'bankserv/transmission/set/credit'
39
+ require 'bankserv/transmission/set/eft_output'
40
+ require 'bankserv/transmission/set/eft_redirect'
41
+ require 'bankserv/transmission/set/eft_unpaid'
42
+ require 'bankserv/transmission/set/reply'
43
+
44
+ require 'bankserv/engine'
45
+ require 'bankserv/engine/engine_configuration'
46
+ require 'bankserv/engine/engine_process'
47
+
48
+ require 'bankserv/transaction'
@@ -0,0 +1,90 @@
1
+ module Bankserv
2
+
3
+ class AccountHolderVerification < ActiveRecord::Base
4
+
5
+ self.inheritance_column = :_type_disabled
6
+ serialize :response
7
+
8
+ belongs_to :bank_account, :foreign_key => 'bankserv_bank_account_id'
9
+ belongs_to :request, :foreign_key => 'bankserv_request_id'
10
+
11
+ scope :unprocessed, where(status: "new")
12
+ scope :internal, where(internal: true)
13
+ scope :external, where(internal: false)
14
+
15
+ after_create :generate_internal_user_ref
16
+
17
+ def generate_internal_user_ref
18
+ self.internal_user_ref = "AHV#{id}"
19
+ save!
20
+ end
21
+
22
+ def self.request(options = {})
23
+ options.merge!(type: 'ahv')
24
+ Request.create!(options)
25
+ end
26
+
27
+ def self.test_request(options)
28
+ Request.create!(options.merge(test: true))
29
+ end
30
+
31
+ def self.for_reference(reference)
32
+ self.where(:user_ref => reference)
33
+ end
34
+
35
+ def self.for_internal_reference(reference)
36
+ self.where(:internal_user_ref => reference)
37
+ end
38
+
39
+ def self.build!(options)
40
+ bank_account = BankAccount.new options[:bank_account].filter_attributes(BankAccount)
41
+ is_internal = bank_account.branch_code == Bankserv::Configuration.internal_branch_code
42
+ options = options.filter_attributes(self).merge(bank_account: bank_account, internal: is_internal)
43
+
44
+ create!(options)
45
+ end
46
+
47
+ def internal?
48
+ internal == true
49
+ end
50
+
51
+ def external?
52
+ !internal?
53
+ end
54
+
55
+ def new?
56
+ status == "new"
57
+ end
58
+
59
+ def pending?
60
+ status == "pending"
61
+ end
62
+
63
+ def error?
64
+ status == "error"
65
+ end
66
+
67
+ def completed?
68
+ status == "completed"
69
+ end
70
+
71
+ def process_response(data)
72
+ file_name = "#{Bankserv::CONFIG_DIR}/ahv.yml"
73
+ return_code_mapping = YAML.load(File.open(file_name))['return_codes']
74
+
75
+ hash = {
76
+ account_number: return_code_mapping[data[:return_code_1]].to_sym,
77
+ id_number: return_code_mapping[data[:return_code_2]].to_sym,
78
+ initials: return_code_mapping[data[:return_code_3]].to_sym,
79
+ surname: return_code_mapping[data[:return_code_4]].to_sym
80
+ }
81
+
82
+ self.response = hash
83
+ self.status = "completed"
84
+ self.save!
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+
@@ -0,0 +1,19 @@
1
+ module Bankserv
2
+
3
+ class BankAccount < ActiveRecord::Base
4
+
5
+ def account_type_id
6
+ if self.account_type.to_i != 0
7
+ self.account_type.to_s
8
+ else
9
+ { "current" => "1",
10
+ "savings" => "2",
11
+ "transmission" => "3",
12
+ "bond" => "4",
13
+ "subscription" => "6" }[self.account_type.downcase]
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ end
@@ -0,0 +1,67 @@
1
+ module Bankserv
2
+
3
+ class Configuration < ActiveRecord::Base
4
+
5
+ def self.active
6
+ self.where(active: true).last
7
+ end
8
+
9
+ def self.client_code
10
+ self.active.client_code
11
+ end
12
+
13
+ def self.client_name
14
+ self.active.client_name
15
+ end
16
+
17
+ def self.client_abbreviated_name
18
+ self.active.client_abbreviated_name
19
+ end
20
+
21
+ def self.user_code
22
+ self.active.user_code
23
+ end
24
+
25
+ def self.department_code
26
+ self.active.department_code
27
+ end
28
+
29
+ def self.user_generation_number
30
+ self.active.user_generation_number
31
+ end
32
+
33
+ def self.internal_branch_code
34
+ self.active.internal_branch_code
35
+ end
36
+
37
+ def self.transmission_number
38
+ self.active.transmission_number
39
+ end
40
+
41
+ def self.set_transmission_number!(number)
42
+ self.active.update_attributes!(transmission_number: number)
43
+ end
44
+
45
+ def self.reserve_transmission_number!
46
+ reserved = self.transmission_number
47
+ self.set_transmission_number!(reserved + 1)
48
+ reserved
49
+ end
50
+
51
+ def self.set_user_generation_number!(number)
52
+ self.active.update_attributes!(user_generation_number: number)
53
+ end
54
+
55
+ def self.reserve_user_generation_number!
56
+ reserved = self.user_generation_number
57
+ self.set_user_generation_number!(reserved + 1)
58
+ reserved
59
+ end
60
+
61
+ def self.live_env?
62
+ self.active.live_env
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,70 @@
1
+ module Bankserv
2
+
3
+ class Credit < ActiveRecord::Base
4
+ extend Eft
5
+
6
+ serialize :response
7
+ scope :unprocessed, where(status: "new")
8
+
9
+ belongs_to :bank_account, :foreign_key => 'bankserv_bank_account_id'
10
+ belongs_to :request, :foreign_key => 'bankserv_request_id'
11
+
12
+ after_create :generate_internal_user_ref
13
+
14
+ def generate_internal_user_ref
15
+ self.internal_user_ref = "CREDIT#{id}"
16
+ save!
17
+ end
18
+
19
+ def self.for_reference(reference)
20
+ self.where(:user_ref => reference)
21
+ end
22
+
23
+ def self.for_internal_reference(reference)
24
+ self.where(:internal_user_ref => reference)
25
+ end
26
+
27
+ def amount_in_cents
28
+ (amount * 100).to_i
29
+ end
30
+
31
+ def new?
32
+ status == "new"
33
+ end
34
+
35
+ def pending?
36
+ status == "pending"
37
+ end
38
+
39
+ def error?
40
+ status == "error"
41
+ end
42
+
43
+ def completed?
44
+ status == "completed"
45
+ end
46
+
47
+ def standard?
48
+ record_type == "standard"
49
+ end
50
+
51
+ def contra?
52
+ record_type == "contra"
53
+ end
54
+
55
+ def formatted_user_ref
56
+ can_length = 10 - Configuration.client_abbreviated_name.length
57
+ "#{Configuration.client_abbreviated_name[0..9] << (' ' * can_length)}#{user_ref}"
58
+ end
59
+
60
+ def contra_bank_details
61
+ if self.standard?
62
+ Credit.where(record_type: "contra", batch_id: self.batch_id, status: "new").first.bank_account
63
+ else
64
+ self.bank_account
65
+ end
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,94 @@
1
+ module Bankserv
2
+
3
+ class Debit < ActiveRecord::Base
4
+ extend Eft
5
+
6
+ serialize :response
7
+ scope :unprocessed, where(status: "new")
8
+
9
+ belongs_to :bank_account, :foreign_key => 'bankserv_bank_account_id'
10
+ belongs_to :request, :foreign_key => 'bankserv_request_id'
11
+
12
+ after_create :generate_internal_user_ref
13
+
14
+ def generate_internal_user_ref
15
+ self.internal_user_ref = "DEBIT#{id}"
16
+ save!
17
+ end
18
+
19
+ def standard?
20
+ record_type == "standard"
21
+ end
22
+
23
+ def contra?
24
+ record_type == "contra"
25
+ end
26
+
27
+ def amount_in_cents
28
+ (amount * 100).to_i
29
+ end
30
+
31
+ def formatted_user_ref
32
+ can_length = 10 - Configuration.client_abbreviated_name.length
33
+ "#{Configuration.client_abbreviated_name[0..9] << (' ' * can_length)}#{user_ref}"
34
+ end
35
+
36
+ def contra_bank_details
37
+ if self.standard?
38
+ Debit.where(record_type: "contra", batch_id: self.batch_id, status: "new").first.bank_account
39
+ else
40
+ self.bank_account
41
+ end
42
+ end
43
+
44
+ def self.for_reference(reference)
45
+ self.where(:user_ref => reference)
46
+ end
47
+
48
+ def self.for_internal_reference(reference)
49
+ self.where(:internal_user_ref => reference)
50
+ end
51
+
52
+ def process_response(data)
53
+ save_data = if data[:response_status] == 'unpaid'
54
+ {
55
+ rejection_reason_description: Absa::H2h::Eft::RejectionCode.reason_for_code(data[:rejection_reason]),
56
+ rejection_reason: data[:rejection_reason],
57
+ rejection_qualifier_description: Absa::H2h::Eft::RejectionCode.qualifier_for_code(data[:rejection_qualifier]),
58
+ rejection_qualifier: data[:rejection_qualifier]
59
+ }
60
+ elsif data[:response_status] == 'redirect'
61
+ data.only([:new_homing_branch, :new_homing_account_number, :new_homing_account_type])
62
+ end
63
+
64
+ self.response = save_data
65
+ self.status = data[:response_status]
66
+ self.save!
67
+ end
68
+
69
+ def new?
70
+ status == "new"
71
+ end
72
+
73
+ def pending?
74
+ status == "pending"
75
+ end
76
+
77
+ def error?
78
+ status == "error"
79
+ end
80
+
81
+ def completed?
82
+ status == "completed"
83
+ end
84
+
85
+ def unpaid?
86
+ status == "unpaid"
87
+ end
88
+
89
+ def redirect?
90
+ status == "redirect"
91
+ end
92
+ end
93
+
94
+ end