bankserv 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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