bankserv 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.rvmrc +1 -0
- data/Gemfile +16 -0
- data/Rakefile +8 -0
- data/bankserv.gemspec +31 -0
- data/config.ru +7 -0
- data/lib/bankserv.rb +48 -0
- data/lib/bankserv/account_holder_verification.rb +90 -0
- data/lib/bankserv/bank_account.rb +19 -0
- data/lib/bankserv/configuration.rb +67 -0
- data/lib/bankserv/credit.rb +70 -0
- data/lib/bankserv/debit.rb +94 -0
- data/lib/bankserv/eft.rb +83 -0
- data/lib/bankserv/engine.rb +183 -0
- data/lib/bankserv/engine/engine_configuration.rb +12 -0
- data/lib/bankserv/engine/engine_process.rb +3 -0
- data/lib/bankserv/request.rb +27 -0
- data/lib/bankserv/transaction.rb +22 -0
- data/lib/bankserv/transmission/document.rb +43 -0
- data/lib/bankserv/transmission/input_document.rb +84 -0
- data/lib/bankserv/transmission/output_document.rb +27 -0
- data/lib/bankserv/transmission/record.rb +13 -0
- data/lib/bankserv/transmission/reply_document.rb +27 -0
- data/lib/bankserv/transmission/set.rb +120 -0
- data/lib/bankserv/transmission/set/account_holder_verification.rb +81 -0
- data/lib/bankserv/transmission/set/account_holder_verification_output.rb +17 -0
- data/lib/bankserv/transmission/set/credit.rb +44 -0
- data/lib/bankserv/transmission/set/debit.rb +44 -0
- data/lib/bankserv/transmission/set/document.rb +45 -0
- data/lib/bankserv/transmission/set/eft.rb +228 -0
- data/lib/bankserv/transmission/set/eft_output.rb +12 -0
- data/lib/bankserv/transmission/set/eft_redirect.rb +18 -0
- data/lib/bankserv/transmission/set/eft_unpaid.rb +18 -0
- data/lib/bankserv/transmission/set/reply.rb +47 -0
- data/lib/bankserv/transmission/statement.rb +46 -0
- data/lib/bankserv/version.rb +3 -0
- data/lib/config/ahv.yml +9 -0
- data/lib/core_extensions.rb +37 -0
- data/lib/generators/active_record/bankserv_generator.rb +30 -0
- data/lib/generators/active_record/templates/migration.rb +141 -0
- data/spec/examples/ahv_input_file.txt +7 -0
- data/spec/examples/ahv_output_file.txt +7 -0
- data/spec/examples/credit_eft_input.txt +166 -0
- data/spec/examples/debit_eft_input_file.txt +20 -0
- data/spec/examples/eft_input_with_2_sets.txt +8 -0
- data/spec/examples/eft_output_file.txt +35 -0
- data/spec/examples/host2host/tmp.log +1 -0
- data/spec/examples/reply/rejected_transmission.txt +7 -0
- data/spec/examples/reply/reply_file.txt +5 -0
- data/spec/examples/statement4_unpacked.dat +51 -0
- data/spec/examples/tmp/OUTPUT0412153500.txt +35 -0
- data/spec/examples/tmp/REPLY0412153000.txt +5 -0
- data/spec/factories.rb +90 -0
- data/spec/internal/config/database.yml.sample +3 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +138 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/lib/bankserv/account_holder_verification_spec.rb +104 -0
- data/spec/lib/bankserv/configuration_spec.rb +34 -0
- data/spec/lib/bankserv/core_ext_spec.rb +43 -0
- data/spec/lib/bankserv/credit_spec.rb +92 -0
- data/spec/lib/bankserv/debit_spec.rb +187 -0
- data/spec/lib/bankserv/engine/engine_spec.rb +142 -0
- data/spec/lib/bankserv/transaction_spec.rb +32 -0
- data/spec/lib/bankserv/transmission/input_document_spec.rb +207 -0
- data/spec/lib/bankserv/transmission/output_document_spec.rb +210 -0
- data/spec/lib/bankserv/transmission/reply_document_spec.rb +117 -0
- data/spec/lib/bankserv/transmission/set/account_holder_verification_spec.rb +108 -0
- data/spec/lib/bankserv/transmission/set/credit_spec.rb +96 -0
- data/spec/lib/bankserv/transmission/set/debit_spec.rb +103 -0
- data/spec/lib/bankserv/transmission/statement_spec.rb +109 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/support/helpers.rb +207 -0
- metadata +223 -0
data/.gitignore
ADDED
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"
|
data/Rakefile
ADDED
data/bankserv.gemspec
ADDED
@@ -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
|
data/config.ru
ADDED
data/lib/bankserv.rb
ADDED
@@ -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
|