bank_payments 0.5.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 (43) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +2 -0
  5. data/.todo.reek +3 -0
  6. data/.travis.yml +7 -0
  7. data/Gemfile +8 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +92 -0
  10. data/Rakefile +6 -0
  11. data/bank_payments.gemspec +38 -0
  12. data/bank_specifications/teknisk_manual_swedbank.pdf +0 -0
  13. data/bin/console +14 -0
  14. data/bin/setup +8 -0
  15. data/lib/bank_payments.rb +42 -0
  16. data/lib/bank_payments/beneficiary.rb +69 -0
  17. data/lib/bank_payments/spisu_record.rb +130 -0
  18. data/lib/bank_payments/swedbank_export/address_record.rb +40 -0
  19. data/lib/bank_payments/swedbank_export/bank_record.rb +28 -0
  20. data/lib/bank_payments/swedbank_export/credit_memo_record.rb +49 -0
  21. data/lib/bank_payments/swedbank_export/enums.rb +22 -0
  22. data/lib/bank_payments/swedbank_export/field_definition.rb +21 -0
  23. data/lib/bank_payments/swedbank_export/file.rb +26 -0
  24. data/lib/bank_payments/swedbank_export/money_record.rb +21 -0
  25. data/lib/bank_payments/swedbank_export/name_record.rb +15 -0
  26. data/lib/bank_payments/swedbank_export/opening_record.rb +30 -0
  27. data/lib/bank_payments/swedbank_export/payment_record.rb +20 -0
  28. data/lib/bank_payments/swedbank_export/reason_record.rb +16 -0
  29. data/lib/bank_payments/swedbank_export/reconciliation_record.rb +54 -0
  30. data/lib/bank_payments/swedbank_export/sequence.rb +148 -0
  31. data/lib/bank_payments/swedbank_import/account_record.rb +18 -0
  32. data/lib/bank_payments/swedbank_import/address_record.rb +35 -0
  33. data/lib/bank_payments/swedbank_import/amount_converter.rb +38 -0
  34. data/lib/bank_payments/swedbank_import/file.rb +35 -0
  35. data/lib/bank_payments/swedbank_import/money_record.rb +49 -0
  36. data/lib/bank_payments/swedbank_import/name_record.rb +20 -0
  37. data/lib/bank_payments/swedbank_import/opening_record.rb +25 -0
  38. data/lib/bank_payments/swedbank_import/reconciliation_record.rb +35 -0
  39. data/lib/bank_payments/swedbank_import/sequence.rb +42 -0
  40. data/lib/bank_payments/transaction.rb +38 -0
  41. data/lib/bank_payments/version.rb +3 -0
  42. data/lib/core_extensions/numeric/spisu.rb +15 -0
  43. metadata +169 -0
@@ -0,0 +1,18 @@
1
+ module BankPayments
2
+ module SwedbankImport
3
+ class AccountRecord < SpisuRecord
4
+
5
+ define_field :debit_account, '2:12:N'
6
+ define_field :transaction_date, '13:18:N'
7
+
8
+ def initialize(raw_record)
9
+ super
10
+ self.type = '1'
11
+ end
12
+
13
+ def transaction_date
14
+ extract_date __callee__
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ module BankPayments
2
+ module SwedbankImport
3
+ class AddressRecord < SpisuRecord
4
+
5
+ define_field :transaction_id, '2:8:N'
6
+ define_field :payment_method, '9:9:N'
7
+ define_field :priority, '10:10:N'
8
+ define_field :address, '11:75:AN'
9
+ define_field :country_code, '76:77:AN'
10
+
11
+ def initialize(raw_record)
12
+ super
13
+ self.type = '3'
14
+ end
15
+
16
+ def express?
17
+ priority == '1'
18
+ end
19
+
20
+ # Enum where
21
+ # '0' => 'Paid by check'
22
+ # '1' => 'Paid by depositing into an account'
23
+ def payment_method
24
+ extract_raw_value __callee__
25
+ end
26
+
27
+ # Enum where
28
+ # '0' => 'Normal priority'
29
+ # '1' => 'Express priority'
30
+ def priority
31
+ extract_raw_value __callee__
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ require 'bigdecimal'
2
+
3
+ module BankPayments
4
+ module SwedbankImport
5
+
6
+ # Used to convert Swedbanks numeric representation to a Ruby BigDecimal. It
7
+ # especially handles the convetion that that negative numbers have the last
8
+ # digits set as a char according to the DIGIT_MAP
9
+ #
10
+ # @author Michael Litton
11
+ class AmountConverter
12
+
13
+ DIGIT_MAP = {
14
+ 'å' => '0',
15
+ 'J' => '1',
16
+ 'K' => '2',
17
+ 'L' => '3',
18
+ 'M' => '4',
19
+ 'N' => '5',
20
+ 'O' => '6',
21
+ 'P' => '7',
22
+ 'Q' => '8',
23
+ 'R' => '9',
24
+ }.freeze
25
+
26
+ def self.value_to_decimal(value)
27
+ modifier = 1
28
+
29
+ if value[-1] =~ /\D/
30
+ modifier = -1
31
+ value = value[0..-2] + DIGIT_MAP[value[-1]]
32
+ end
33
+
34
+ BigDecimal("#{value[0..-3]}.#{value[-2..-1]}") * modifier
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ module BankPayments::SwedbankImport
2
+
3
+ # Contains payments that have been made at the bank for a particular date.
4
+ # This maps to multiple export files created ealier. It will contain up to
5
+ # all payments requested earlier. When payouts fail the informaiton must be
6
+ # generated elsewhere.
7
+ #
8
+ # @author Michael Litton
9
+ class File
10
+ attr_accessor :sequences
11
+
12
+ # Given the a string of file data the sequeces and records are
13
+ # created
14
+ def initialize(data)
15
+ @sequences = []
16
+ current_sequence = nil
17
+
18
+ data.gsub(/(\r|\n)+/,"\n").each_line do |raw_record|
19
+ if opening_post?(raw_record)
20
+ current_sequence = Sequence.new
21
+ current_sequence << raw_record
22
+ @sequences << current_sequence
23
+ else
24
+ current_sequence << raw_record
25
+ end
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def opening_post?(raw_record)
32
+ raw_record[0] == '0'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,49 @@
1
+ module BankPayments
2
+ module SwedbankImport
3
+ class MoneyRecord < SpisuRecord
4
+
5
+ define_field :serial_number, '2:8:N'
6
+ define_field :reference, '9:33:AN'
7
+ define_field :amount_sek, '34:44:N'
8
+ define_field :bank_amount_sek, '45:55:N'
9
+ define_field :amount_foreign, '64:76:N'
10
+ define_field :recalculation_code, '78:78:N'
11
+ define_field :error_code, '79:79:N'
12
+
13
+ def initialize(raw_record)
14
+ super
15
+ self.type = '5'
16
+ end
17
+
18
+ def corrected_by_bank?
19
+ error_code == '1'
20
+ end
21
+
22
+ def amount_sek
23
+ AmountConverter.value_to_decimal(extract_raw_value __callee__)
24
+ end
25
+
26
+ def bank_amount_sek
27
+ AmountConverter.value_to_decimal(extract_raw_value __callee__)
28
+ end
29
+
30
+ def amount_foreign
31
+ AmountConverter.value_to_decimal(extract_raw_value __callee__)
32
+ end
33
+
34
+ # Enum with
35
+ # '0' => The bank has calculated it's value from the foreign amount'
36
+ # '9' => The bank has calculated it's value form the SEK amount
37
+ def recalculation_code
38
+ extract_raw_value __callee__
39
+ end
40
+
41
+ # Enum with
42
+ # '0' = OK
43
+ # '1' = Payment corrected by the bank
44
+ def error_code
45
+ extract_raw_value __callee__
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ module BankPayments
2
+ module SwedbankImport
3
+ class NameRecord < SpisuRecord
4
+
5
+ define_field :serial_number, '2:8:N'
6
+ define_field :name, '9:73:AN'
7
+ define_field :currency_code, '74:76'
8
+ define_field :merges_payments, '77:77:N'
9
+
10
+ def initialize(raw_record)
11
+ super
12
+ self.type = '2'
13
+ end
14
+
15
+ def merges_payments
16
+ extract_raw_value __callee__
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ module BankPayments
2
+ module SwedbankImport
3
+ class OpeningRecord < SpisuRecord
4
+
5
+ define_field :sender, '2:12:N'
6
+ define_field :creation_date, '13:18:N'
7
+ define_field :previous_bank_day, '19:24:N'
8
+ define_field :layout, '25:30:AN'
9
+ define_field :customer_id, '31:42:AN'
10
+
11
+ def initialize(raw_record)
12
+ super
13
+ self.type = '0'
14
+ end
15
+
16
+ def creation_date
17
+ extract_date __callee__
18
+ end
19
+
20
+ def previous_bank_day
21
+ extract_date __callee__
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ module BankPayments
2
+ module SwedbankImport
3
+ class ReconciliationRecord < SpisuRecord
4
+
5
+ define_field :sum_amount_sek, '2:13:N'
6
+ define_field :sum_bank_amount_sek, '14:25:N'
7
+ define_field :sum_amount_foreign, '26:40:N'
8
+ define_field :transaction_cost, '41:52:N'
9
+ define_field :total_beneficiaries, '53:64:N'
10
+ define_field :total_records, '65:76:N'
11
+
12
+ def initialize(raw_record)
13
+ super
14
+ self.type = '6'
15
+ end
16
+
17
+ def sum_amount_sek
18
+ AmountConverter.value_to_decimal(extract_raw_value __callee__)
19
+ end
20
+
21
+ def sum_bank_amount_sek
22
+ AmountConverter.value_to_decimal(extract_raw_value __callee__)
23
+ end
24
+
25
+ def sum_amount_foreign
26
+ AmountConverter.value_to_decimal(extract_raw_value __callee__)
27
+ end
28
+
29
+ def transaction_cost
30
+ AmountConverter.value_to_decimal(extract_raw_value __callee__)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ module BankPayments
2
+ module SwedbankImport
3
+
4
+ # Contains all records for a sequence. The sequence starts with an opening
5
+ # record followed by an account record, i.e. which account that was debited.
6
+ # It then alternates three records: Name, Address-and Money Record to
7
+ # describe a transaction with it's beneficiary.
8
+ #
9
+ # Records are expected to be a text string
10
+ # and passed to the sequence through the "<<"-method.
11
+ #
12
+ # @author Michael Litton
13
+ class Sequence
14
+ attr_reader :records
15
+
16
+ def initialize
17
+ @records = []
18
+ end
19
+
20
+ def <<(raw_record)
21
+ new_record = case raw_record[0]
22
+ when '0'
23
+ OpeningRecord.new(raw_record)
24
+ when '1'
25
+ AccountRecord.new(raw_record)
26
+ when '2'
27
+ NameRecord.new(raw_record)
28
+ when '3'
29
+ AddressRecord.new(raw_record)
30
+ when '5'
31
+ MoneyRecord.new(raw_record)
32
+ when '6'
33
+ ReconciliationRecord.new(raw_record)
34
+ else
35
+ raise 'Unknown record'
36
+ end
37
+
38
+ @records << new_record
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ module BankPayments
2
+
3
+ # Represents a monetary transaction
4
+ class Transaction
5
+ attr_reader :amount_sek, :amount_foreign, :currency, :message, :pay_date, :reason
6
+
7
+ def initialize(amount_sek:, amount_foreign:, currency:, message:, pay_date:, reason:)
8
+ @amount_sek = amount_sek
9
+ @amount_foreign = amount_foreign
10
+ @currency = currency
11
+ @message = message
12
+ @pay_date = pay_date
13
+ @reason = reason
14
+ end
15
+
16
+ def to_spisu_records
17
+ money_record = if amount_sek >= 0
18
+ BankPayments::SwedbankExport::PaymentRecord.new
19
+ else
20
+ BankPayments::SwedbankExport::CreditMemoRecord.new
21
+ end
22
+
23
+ money_record.reference_msg = @message
24
+ money_record.amount_sek = @amount_sek
25
+ money_record.amount_foreign = @amount_foreign
26
+ money_record.currency_code = @currency
27
+ money_record.date = @pay_date
28
+
29
+ if amount_sek.abs >= 150_000
30
+ reason_record = BankPayments::SwedbankExport::ReasonRecord.new
31
+ reason_record.code = @reason
32
+ [money_record, reason_record]
33
+ else
34
+ [money_record]
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module BankPayments
2
+ VERSION = "0.5.1"
3
+ end
@@ -0,0 +1,15 @@
1
+ module CoreExtensions
2
+ module Numeric
3
+
4
+ # Adds a general format method that belongs in more than one class and
5
+ # is more a utility function belonging to the SPISU-format more than
6
+ # anything else.
7
+ #
8
+ # @author Michael Litton
9
+ module SPISU
10
+ def spisu_format
11
+ ("%.2f" % self).gsub(".","")
12
+ end
13
+ end
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bank_payments
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Litton
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-08-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.5'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.12'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.12'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ibandit
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.11'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.11'
83
+ - !ruby/object:Gem::Dependency
84
+ name: unicode_utils
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.4'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.4'
97
+ description:
98
+ email:
99
+ - michael.litton@apoex.se
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".coveralls.yml"
105
+ - ".gitignore"
106
+ - ".rspec"
107
+ - ".todo.reek"
108
+ - ".travis.yml"
109
+ - Gemfile
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - bank_payments.gemspec
114
+ - bank_specifications/teknisk_manual_swedbank.pdf
115
+ - bin/console
116
+ - bin/setup
117
+ - lib/bank_payments.rb
118
+ - lib/bank_payments/beneficiary.rb
119
+ - lib/bank_payments/spisu_record.rb
120
+ - lib/bank_payments/swedbank_export/address_record.rb
121
+ - lib/bank_payments/swedbank_export/bank_record.rb
122
+ - lib/bank_payments/swedbank_export/credit_memo_record.rb
123
+ - lib/bank_payments/swedbank_export/enums.rb
124
+ - lib/bank_payments/swedbank_export/field_definition.rb
125
+ - lib/bank_payments/swedbank_export/file.rb
126
+ - lib/bank_payments/swedbank_export/money_record.rb
127
+ - lib/bank_payments/swedbank_export/name_record.rb
128
+ - lib/bank_payments/swedbank_export/opening_record.rb
129
+ - lib/bank_payments/swedbank_export/payment_record.rb
130
+ - lib/bank_payments/swedbank_export/reason_record.rb
131
+ - lib/bank_payments/swedbank_export/reconciliation_record.rb
132
+ - lib/bank_payments/swedbank_export/sequence.rb
133
+ - lib/bank_payments/swedbank_import/account_record.rb
134
+ - lib/bank_payments/swedbank_import/address_record.rb
135
+ - lib/bank_payments/swedbank_import/amount_converter.rb
136
+ - lib/bank_payments/swedbank_import/file.rb
137
+ - lib/bank_payments/swedbank_import/money_record.rb
138
+ - lib/bank_payments/swedbank_import/name_record.rb
139
+ - lib/bank_payments/swedbank_import/opening_record.rb
140
+ - lib/bank_payments/swedbank_import/reconciliation_record.rb
141
+ - lib/bank_payments/swedbank_import/sequence.rb
142
+ - lib/bank_payments/transaction.rb
143
+ - lib/bank_payments/version.rb
144
+ - lib/core_extensions/numeric/spisu.rb
145
+ homepage: https://github.com/apoex/bank_payments
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.5.1
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: For generating payment files for various banks
169
+ test_files: []